bolderflight / invensense-imu

Arduino and CMake library for communicating with the InvenSense MPU-6500, MPU-9250 and MPU-9255 nine-axis IMUs.
MIT License
497 stars 210 forks source link

.Begin() giving errors on Teensy 4.0 and possible fix #88

Closed ChSt15 closed 2 years ago

ChSt15 commented 3 years ago

When using MPU9250 over SPI bus .Begin() was failing to start the IMU. Errors occured at random places until i increased the delayNanoseconds to 200ns in the ReadRegisters function for the Teensy 4.0. This caused the error in .Begin() to allways occur at the first AK8963 WHOAMI check. I then added a delay to the WriteRegister function

bool Mpu9250::WriteRegister(uint8_t reg, uint8_t data) {
  uint8_t ret_val;
  if (iface_ == I2C) {
    i2c_->beginTransmission(conn_);
    i2c_->write(reg);
    i2c_->write(data);
    i2c_->endTransmission();
  } else {
    spi_->beginTransaction(SPISettings(spi_clock_, MSBFIRST, SPI_MODE3));
    #if defined(__MK20DX128__) || defined(__MK20DX256__) || \
        defined(__MK64FX512__) || defined(__MK66FX1M0__) || \
        defined(__MKL26Z64__)  || defined(__IMXRT1062__) || \
        defined(__IMXRT1052__)
    digitalWriteFast(conn_, LOW);
    #else
    digitalWrite(conn_, LOW);
    #endif
    #if defined(__IMXRT1062__)
      delayNanoseconds(200);
    #endif
    spi_->transfer(reg);
    spi_->transfer(data);
    #if defined(__MK20DX128__) || defined(__MK20DX256__) || \
        defined(__MK64FX512__) || defined(__MK66FX1M0__) || \
        defined(__MKL26Z64__)  || defined(__IMXRT1062__) || \
        defined(__IMXRT1052__)
    digitalWriteFast(conn_, HIGH);
    #else
    digitalWrite(conn_, HIGH);
    #endif
    #if defined(__IMXRT1062__)
      delayNanoseconds(200);
    #endif
    spi_->endTransaction();
  }
  delay(10);
  ReadRegisters(reg, sizeof(ret_val), &ret_val);
  delay(10);  <------------------------------------------------------------ This delay!
  if (data == ret_val) {
    return true;
  } else {
    return false;
  }
}

This lets the .Begin() function run reliably successfully. I havent tested if they can be shorter, but this seems to be reliable and i havent had issues since

flybrianfly commented 3 years ago

Thanks! Have you tried the newest version on this repo? I have a delayNanoseconds(50) for the Teensy 4.1 included and it was working fine for me, but I'm wondering if I need to increase it or include in more places.

ChSt15 commented 3 years ago

Yes this is with the newest repo. After some further testing i seems to randomly start to get the issue again and across all my boards i can test. I also tested with the example sketch for SPI only changing the NCS pin to work with my custom PCB, so this isnt an issue resulting from my code. Further information on the issue: it comes up once i upload new code to the teensy and stays even when reuploading. I'll then start trying to change things to solve the problem and uploading them until it randomly starts working again after uploading new code, itll then randomly showup at some new code upload. So resetting doesnt change anything, only after uploads does the problem showup and solve itsself. I doubt its due to the custom PCB as the communication between the sensor works, but the Magnetometer doesnt.

flybrianfly commented 3 years ago

Makes sense to me that it stays after reuploading. The MPU-9250 is a SiP with the MPU-6500 IMU and AK8963 magnetometer combined in the same package. The MPU-6500 can act as I2C master to the AK8963 to collect the magnetometer data and store it in some registers reserved for external sensor data. When the Teensy 4.1 interacts with the MPU-9250 its gathering both the IMU data and the "external" magnetometer data in one burst read.

When something screws up the communication with the magnetometer, it typically hangs the AK8963. Unfortunately, we don't have access to any pin or register to reset the AK8963 (there is a software reset, but since the communication bus is hung, it doesn't work), so the only recovery is to reset power to the MPU-9250.

Most of my time is spent working with the Teensy 3.6, but I'll be transitioning to having most of my workload on the Teensy 4.1 over the next couple months. I'll keep an eye out to see if we can figure out a specific cause of these issues. If you're able to find a way of consistently repeating the problem, please let me know and I'll try to reproduce it as well.

ChSt15 commented 3 years ago

Makes sense, i guess there was residual power from a capacitor that kept the AK8963 powered after i disconnected the board for a reset. I guess as an easy workaround is one could add the ability to keep using the sensor but without the AK8963. This wouldnt be a problem for me as im going to use an external one anyway. Other than skipping further commands to the AK8963, is there anything important i would need to disable to get reliable information from the MPU6500? Like from .Read()?

Edit: I've added the feature and it works, sensor values from MPU6500 are correct. Should i create a branch with this modification? Im also working on a modification to allow disabling of the DLPF and get 32kHz from the gyro.

flybrianfly commented 3 years ago

These files should do the trick for removing the mag. mpu9250.zip