ZHomeSlice / Simple_MPU6050

Going Live
MIT License
88 stars 24 forks source link

what are potential reasons to cause data stop output from IMUs #38

Open GUIMINLONG opened 1 year ago

GUIMINLONG commented 1 year ago

I am trying to collect data from 6 imu units, and serial.print those data in an order manner. During all my test process, some phenomemon confuse me for long time, but I can not figure them out. Those phenomenom are: (1) when all IMU in static state, all data from six imu are output fluenctly. But it was often blocked and no data were outputed when some or one IMU is in moving state. Close and re-open the port monitoring (reset arduino programe), then same phenomenon is very likely again.

(2) Sometime after the blocking in case (1), reset arduino program still do not work. I have to turn off the power of Arduino (power of all IMU are simtaneouly turn off). After turn on and reset the arduino, imus work again. By the way, for reset process the calibration at least one imu seems needed. Because, when I try to only load calibrated data and skip the "mpu.CalibrateMPU()" it also do not work.

(3) IMU stop output data are more likely happen when I try to transmit data with bluetotth(HC05). Especially, every time when I stop read data from the serial port for several seconds, the block is almost 100% pencent happen. What I can do is to reset arduino software programe in (1), and sometimes reset software programe do not work, then I have to turn off all the power and restart all this system.

For (3) is it potential because the data blocking in MPU6050-dmp? and what potential cuase (1) and (2)?

below are my code reference from the 4-imu exaple in this project.

void setup() {
  time1 = micros();
  time4 = micros();
  // initialize serial communication
  Serial.begin(230400);
  Serial.println(F("Start:"));
  mpu.begin();
  mpu.SetAddress(MPU6050_DEFAULT_ADDRESS);
  mpu.Set_DMP_Output_Rate_Seconds(200);   // Set the DMP output rate in Seconds

  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(13, OUTPUT);

  for (int i = 8; i < 14; i++) {
       if (i == 8) 
    {
      digitalWrite(8, !(i == 8)); // when i == 6 set pin LOW
      digitalWrite(9, !(i == 9)); // when i == 7 set pin LOW
      digitalWrite(10, !(i == 10)); // when i == 8 set pin LOW
      digitalWrite(11, !(i == 11)); // when i == 9 set pin LOW
      digitalWrite(12, !(i == 12)); // when i == 8 set pin LOW
      digitalWrite(13, !(i == 13)); // when i == 9 set pin LOW
      mpu.CalibrateMPU();  // Calibration  bsxzv
      mpu.Enable_Reload_of_DMP(Six_Axis_Quaternions); 
      mpu.load_DMP_Image(-2362,48,902,-183,-87,14); // Load the DMP Firmware  imu1
    }
     else if (i == 9) 
    {
      digitalWrite(8, !(i == 8)); // when i == 6 set pin LOW
      digitalWrite(9, !(i == 9)); // when i == 7 set pin LOW
      digitalWrite(10, !(i == 10)); // when i == 8 set pin LOW
      digitalWrite(11, !(i == 11)); // when i == 9 set pin LOW
      digitalWrite(12, !(i == 12)); // when i == 8 set pin LOW
      digitalWrite(13, !(i == 13)); // when i == 9 set pin LOW
      mpu.Enable_Reload_of_DMP(Six_Axis_Quaternions); 
      mpu.load_DMP_Image(-4642,160,834,29,-25,45); // Load the DMP Firmware  imu2
    }
      else if (i == 10) 
    {
      digitalWrite(8, !(i == 8)); // when i == 6 set pin LOW
      digitalWrite(9, !(i == 9)); // when i == 7 set pin LOW
      digitalWrite(10, !(i == 10)); // when i == 8 set pin LOW
      digitalWrite(11, !(i == 11)); // when i == 9 set pin LOW
      digitalWrite(12, !(i == 12)); // when i == 8 set pin LOW
      digitalWrite(13, !(i == 13)); // when i == 9 set pin LOW
      mpu.Enable_Reload_of_DMP(Six_Axis_Quaternions); 
      mpu.load_DMP_Image(-3126,774,1926,163,-17,-69); // Load the DMP Firmware  imu3
    }
      else if (i == 11) 
    {
      digitalWrite(8, !(i == 8)); // when i == 6 set pin LOW
      digitalWrite(9, !(i == 9)); // when i == 7 set pin LOW
      digitalWrite(10, !(i == 10)); // when i == 8 set pin LOW
      digitalWrite(11, !(i == 11)); // when i == 9 set pin LOW
      digitalWrite(12, !(i == 12)); // when i == 8 set pin LOW
      digitalWrite(13, !(i == 13)); // when i == 9 set pin LOW
      mpu.Enable_Reload_of_DMP(Six_Axis_Quaternions); 
      mpu.load_DMP_Image(-1520,-158,520,233,25,-33); // Load the DMP Firmware  imu4
    }
      else if (i == 12) 
    {
      digitalWrite(8, !(i == 8)); // when i == 6 set pin LOW
      digitalWrite(9, !(i == 9)); // when i == 7 set pin LOW
      digitalWrite(10, !(i == 10)); // when i == 8 set pin LOW
      digitalWrite(11, !(i == 11)); // when i == 9 set pin LOW
      digitalWrite(12, !(i == 12)); // when i == 8 set pin LOW
      digitalWrite(13, !(i == 13)); // when i == 9 set pin LOW
      mpu.Enable_Reload_of_DMP(Six_Axis_Quaternions); 
      mpu.load_DMP_Image(1198,-838,894,50,25,33); // Load the DMP Firmware  imu5
    }
    else if (i == 13) 
    {
      digitalWrite(8, !(i == 8)); // when i == 6 set pin LOW
      digitalWrite(9, !(i == 9)); // when i == 7 set pin LOW
      digitalWrite(10, !(i == 10)); // when i == 8 set pin LOW
      digitalWrite(11, !(i == 11)); // when i == 9 set pin LOW
      digitalWrite(12, !(i == 12)); // when i == 8 set pin LOW
      digitalWrite(13, !(i == 13)); // when i == 9 set pin LOW
      mpu.Enable_Reload_of_DMP(Six_Axis_Quaternions); 
      mpu.load_DMP_Image(-1468,-2228,1870,129,-40,-35); // Load the DMP Firmware  imu6
    }
  }
  mpu.on_FIFO(print_Values);
  Serial.println(" ");
}

void loop() {
    if (Serial.available() > 0) // check if there are any order
    {  
      resetFunc();
      }

    time2 = micros();
    deltat = 0.000001*(time2 - time1);  //timing of loop test

    for (MPUNumber = 0; MPUNumber < 6; MPUNumber++)   
      {
         if (deltat >= 20)   // after start for 20 seconds, read data from six imus in an order manner
        {
          digitalWrite(8, !(MPUNumber == 0)); // when MPUNumber == 1 set pin 6 LOW
          digitalWrite(9, !(MPUNumber == 1)); // when MPUNumber == 2 set pin 7 LOW
          digitalWrite(10, !(MPUNumber == 2)); // when MPUNumber == 3 set pin 8 LOW
          digitalWrite(11, !(MPUNumber == 3)); // when MPUNumber == 4 set pin 9 LOW
          digitalWrite(12, !(MPUNumber == 4)); // when MPUNumber == 3 set pin 8 LOW
          digitalWrite(13, !(MPUNumber == 5)); // when MPUNumber == 4 set pin 9 LOW    
        }
          else   //at first 20 seconds, read data from  imu-1
        {
          digitalWrite(8, 0); // when MPUNumber == 1 set pin 6 LOW
          digitalWrite(9, 1); // when MPUNumber == 2 set pin 7 LOW
          digitalWrite(10, 1); // when MPUNumber == 3 set pin 8 LOW
          digitalWrite(11, 1); // when MPUNumber == 4 set pin 9 LOW
          digitalWrite(12, 1); // when MPUNumber == 3 set pin 8 LOW
          digitalWrite(13, 1); // when MPUNumber == 4 set pin 9 LOW
          }
      while (!(mpu.dmp_read_fifo(0))){}  //wait till the data from target imu are readed.
      }
}
ZHomeSlice commented 1 year ago

Let's try changing this delay to 1 second. mpu.Set_DMP_Output_Rate_Seconds(1); // Set the DMP output rate in Seconds

We have a lot of time to gather data and my program is designed to handle FIFO overflow. At one second we will obviously overflow the FIFO buffer after the 200 second delay. What will happen is when we request the data after the 200 second delay My program will see that the FIFO buffer has overflowed and will automatically clear it and wait for the next reading that will occur within one second. Then we will get a brand new reading that is accurate at that moment in time. The mpu will maintain and calculate its position even if the FIFO buffer overflows.

Now we just need to set the delay outside the MPU to 200 seconds.

void loop() { if (Serial.available() > 0) // check if there are any order {
resetFunc(); }

time2 = micros();
deltat = 0.000001*(time2 - time1);  //timing of loop test

delay (200000);  // brute Force delay you'll probably want to change this to a blink without delay statement to allow other things to happen. Don't forget to add a 1 millisecond delay somewhere in here to allow your ESP 32 or other ESP based device to do other things like Bluetooth communication.

for (MPUNumber = 0; MPUNumber < 6; MPUNumber++)   
  {
     if (deltat >= 20)   // after start for 20 seconds, read data from six imus in an order manner
    {
      digitalWrite(8, !(MPUNumber == 0)); // when MPUNumber == 1 set pin 6 LOW
      digitalWrite(9, !(MPUNumber == 1)); // when MPUNumber == 2 set pin 7 LOW
      digitalWrite(10, !(MPUNumber == 2)); // when MPUNumber == 3 set pin 8 LOW
      digitalWrite(11, !(MPUNumber == 3)); // when MPUNumber == 4 set pin 9 LOW
      digitalWrite(12, !(MPUNumber == 4)); // when MPUNumber == 3 set pin 8 LOW
      digitalWrite(13, !(MPUNumber == 5)); // when MPUNumber == 4 set pin 9 LOW    
    }
      else   //at first 20 seconds, read data from  imu-1
    {
      digitalWrite(8, 0); // when MPUNumber == 1 set pin 6 LOW
      digitalWrite(9, 1); // when MPUNumber == 2 set pin 7 LOW
      digitalWrite(10, 1); // when MPUNumber == 3 set pin 8 LOW
      digitalWrite(11, 1); // when MPUNumber == 4 set pin 9 LOW
      digitalWrite(12, 1); // when MPUNumber == 3 set pin 8 LOW
      digitalWrite(13, 1); // when MPUNumber == 4 set pin 9 LOW
      }
  while (!(mpu.dmp_read_fifo(0))){
     delay(100)// we are likely beating up the I2C bus by reading the data from the MPUs at a super fast rate putting this delay here will decrease the rate at which we beat up the I2C bus no new data will occur more often than once a second from the MPU at the rate we have it set so let's check every 100 milliseconds for new data to appear. We will likely read from the MPU no more than 10 times before new data arrives and the data will be within one second in accuracy.
  }  //wait till the data from target imu are readed.

  }

}

The likely cause of your trouble is that we were reading from the I2C bus and not giving the device and assuming an ESP 32 or similar to have time to do other things. Having a one millisecond delay ever so often it is vital for those devices to be able to take a break from focusing on Your program to do things like transmit data over Bluetooth.

If you are still struggling to read data, the blocking code that is trying to read the next chunk of data from the FIFO buffer after resetting it maybe the issue. Let's try changing this to even a shorter period of time such as: mpu.Set_DMP_Output_Rate_Hz(10); // Set the DMP output rate in Hz

This way when the FIFO buffer is reset the ESP 32 will only need to wait with My behind the scenes blocking while loop code for 100 milliseconds. And the new reading will be accurate within that time also.

This is an incredibly example that you've presented of reading six MPU's. I may try to incorporate an example code concept of what you did. let me know how this goes.

Z