Closed filipcoja closed 2 years ago
FYI I just added it fix a Few days ago related to:
"the classic I2C bus 'freeze' problem, and if so, it has nothing at all to do with the MPU6060. I2C bus freezes are a known problem with Arduino, and it has only been recently addressed. See this post for all the gory details. The good news is, if you use the latest Wire library code and add the timeout setting line to your setup() function like this
Wire.setWireTimeout(3000, true); //timeout value in uSec
then the I2C freeze problem should go away. Note that if you aren't using the latest Wire library, the above code line won't compile, so it's easy to tell one way or the other." jrowberg/i2cdevlib#543 (comment)
I already added the Wire.setWireTimeout() in my Code
mpu.on_FIFO(refresh_data);
on_FIFO does the following
empties the FIFO buffer and captures the latest packet in the most efficient way and passes it to your function as input variables.
No new data will become available between on_FIFO events. attempting to capture data with mpu.dmp_read_fifo(true); may cause other issues.
You won't need a separate function outside of your refresh_data
void refresh_angles(float *q_arr) {
mpu.dmp_read_fifo(true);
for (int i = 0; i < 4; ++i) {
q_arr[0] = q.w;
q_arr[1] = q.x;
q_arr[2] = q.y;
q_arr[3] = q.z;
}
}
consider adding refresh_angles to the refresh_data function
Spamming your serial port at 100Hz will likely be your crash
mpu.Set_DMP_Output_Rate(DMP_100Hz);
// Because of mpu.on_FIFO(refresh_data); the following line will be triggered only when new data is retrieved
// from the fifo buffer. afterwords the fifo buffer will be empty and the latest packet will populate the variables.
// Everything realted to this data retrieval should reside here.
void refresh_data(int16_t *gyro, int16_t *accel, int32_t *quat, uint32_t *timestamp) {
mpu.GetQuaternion(&q, quat);
// for (int i = 0; i < 4; ++i) { // Not shure why we need to loop 4 times
q_arr[0] = q.w;
q_arr[1] = q.x;
q_arr[2] = q.y;
q_arr[3] = q.z;
// }
// added a spam timer to keep the serial port alive.
static unsigned long SpamTimer;
if ((millis() - SpamTimer) >= (100)) { // only 10Hz insted of 100Hz
SpamTimer= millis();
Serial.println("test");
// mpu.GetYawPitchRoll(test, &q);
// Serial.print(test[0] * 180 / PI);
// Serial.print(';');
// Serial.print(test[1] * 180 / PI);
// Serial.print(';');
// Serial.println(test[2] * 180 / PI);
}
}
Z
And just a fun FYI MPU 6050 Temperature
int16_t TEMP_OUT ;
mpu.TEMP_OUT_H_READ_TEMP_OUT(*TEMP_OUT);
The math: Temperature in degrees C = (TEMP_OUT Register Value as a signed quantity)/340 + 36.53
Oh, I completely missed out on the temperature sensor on the mpu, thanks!
I don't understand it quite, the dmp_read_fifo is also in your example, so should I remove that function call?
I will try changing the code when I get back home, big thanks for your help!
I should add that it works line 99% of the time, it gets stuck rarely so debugging it is quite hard..
Added your suggestions, but I have to keep mpu.dmp_read_fifo(true) since if this is missing, the mpu doesn't do anything. Besides, if I do mpu.dmp_read_fifo(false) and still have the interrupt to pin 2 connected, it still gets interrupted
Sorry about that, I didn't look over the rest of your code.
move dmp_read_fifo() to here or create a separate function in sensors.cpp that triggers dmp_read_fifo()
void loop() {
handle_servo_change();
update_power_led(last_control_update);
mpu.dmp_read_fifo(false); // true means interrupt is required to have triggered. false will query the mpu for FIFO buffer size (slower).
// once the resulting interrupt or FIFO size is true then the callback function is triggered.
// mpu.on_FIFO(refresh_data); ---> refresh_data() function is your callback function
update_sensor_data();
check_calibration();
handle_radio();
// Serial.print(sensors.temperature);
// Serial.print(";");
// Serial.print(sensors.altitude);
// for (int i = 0; i < 4; ++i) {
// Serial.print(";");
// Serial.print(sensors.q[i]);
// }
// Serial.print(';');
// Serial.println(millis() - time);
// wdt_reset();
// Serial.println(millis() - time);
}
Z
You can look at my code again, it should be updated, hopefully I got everything right.
Made some changed and did a pull request for your convenience. Z
Set_DMP_Output_Rate_HZ doesnt exist in your repo, do you have it locally maybe and its not pushed yet?
Looks to be there now forgot to push one button :)
Starting at line 364:
Simple_MPU6050 & Simple_MPU6050::Set_DMP_Output_Rate(uint16_t value){ // 100 HZ Default
DMP_Output_Rate[0] = (uint8_t)((value & 0xFF00) >> 8);
DMP_Output_Rate[1] = (uint8_t)(value & 0x00FF);
return *this;
}
Simple_MPU6050 & Simple_MPU6050::Set_DMP_Output_Rate_Hz(float rate){ // 100 HZ Default
rate = (rate>200) ? 200 : rate;
rate = (rate<0) ? 0.0032 : rate;
uint16_t div = (uint16_t)( 200 / rate - 1);
Set_DMP_Output_Rate(div);
return *this;
}
Simple_MPU6050 & Simple_MPU6050::Set_DMP_Output_Rate_Seconds(float rate){ // 1Hz Default
rate = (rate>300) ? 300 : rate;
rate = (rate<0) ? 0 : rate;
uint16_t div = (uint16_t)( 200 / (1/rate) - 1);
Set_DMP_Output_Rate(div);
return *this;
}
Simple_MPU6050 & Simple_MPU6050::Set_DMP_Output_Rate_Minutes(float rate){ // 1 minute Default
rate = (rate>5) ? 5 : rate;
rate = (rate<0) ? 0 : rate;
Set_DMP_Output_Rate_Seconds(rate/60);
return *this;
}
Z
Thanks!
Tried it out, still gets stuck sometimes, this looks like a sensor error? The "L" Led on my Arduino Mega blinks tho.. Also I recognized that when I move my IMU the output gets slower so something takes longer to execute
You are polling the mpu6050 every loop through the i2c buss but you are only requesting data 10 times a second mpu.Set_DMP_Output_Rate_Hz(10);
If the MPU data isn't a high-value item then use a blink without delay timer to decrease the number of checks caused by mpu.dmp_read_fifo();
something like
static unsigned long FIFO_DelayTimer;
if ((millis() - FIFO_DelayTimer) >= (100)) { // only 10Hz insted of ?Hz
FIFO_DelayTimer= millis();
mpu.dmp_read_fifo();
}
your readings will be within 1/100 of a second of when it was live.
I realized I can improve the performance of this so... I made a change in my library that should improve performance the change allows for this code to work.
static unsigned long FIFO_DelayTimer;
if ((millis() - FIFO_DelayTimer) >= (99)) { // 99ms insted of 100ms to start polling the MPU 1ms prior to data arriving.
if( mpu.dmp_read_fifo()) FIFO_DelayTimer= millis() ; when data arrives reset the timer
}
your readings will now be live
with these changes, your load on your processor and i2c bus will be 1000 times faster. Z
Yea well, I guess there is something fundamentaly wrong with my sensor or I don't know.. but gonna try that one too.
I'm now already trying for a whole year to get this sensor working properly, problem is I just cant get it to work reliably.
As already a lot of other people figured out, the MPU6050 somehow gets the master (arduino) stuck, I've now tried doing the following:
My last resort is still using the built in watchdog, but this is such a bad workaround I'd really just want the watchdog to work as a backup, not as a regular backdrop if the MPU6050 gets stuck.
Maybe you can guide me in a direction to get this thing finally working.
(This is my repo, you can look through the code if you want to) https://github.com/filipppp/airplane