I'm building a robot that uses an MPU6050 module, it works perfectly fine for a bit and then suddenly stops. No output is being sent to the serial monitor, and everything freezes up. It seems like all code execution is stopped. But the thing is, this doesn't always happen the same time. It happens more randomly.
Here's my code:
#include <Adafruit_Sensor.h>
#include <Wire.h>
Adafruit_MPU6050 mpu;
double roll, pitch;
double rolld, pitchd;
double rollf, pitchf;
void setup(void) {
pinMode(35,OUTPUT);
pinMode(36,OUTPUT);
pinMode(37,OUTPUT);
pinMode(38,OUTPUT);
Serial.begin(115200);
// Try to initialize!
if (!mpu.begin()) {
Serial.println("Failed to find MPU6050 chip");
while (1) {
delay(10);
}
}
// set accelerometer range to +-8G
mpu.setAccelerometerRange(MPU6050_RANGE_8_G);
// set gyro range to +- 500 deg/s
mpu.setGyroRange(MPU6050_RANGE_500_DEG);
// set filter bandwidth to 21 Hz
mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);
delay(100);
roll = 0;
pitch = 0;
pinMode(35,OUTPUT);
}
unsigned long currentTime = 0;
unsigned long dt = 0;
double dp;
double dr;
double pr;
double pp;
float k = 0.30; // Filtering constant
double ms = 0.25; // Motor microstep multiplier
int s1 = 0; // Motor speeds in RPM
int s2 = 0;
void loop() {
dp = pitch - pp;
dr = roll - pr;
pp = pitch;
pr = roll;
/* Get new sensor events with the readings */
dt = millis() - currentTime;
sensors_event_t a, g, temp;
mpu.getEvent(&a, &g, &temp);
/* Print out the values */
Serial.print("Time elapsed:");
Serial.println(dt);
currentTime = millis();
roll = (roll + g.gyro.x*dt/1000)*0.5 + 0.5*atan(a.acceleration.y / sqrt(pow(a.acceleration.x, 2) + pow(a.acceleration.z, 2)));
pitch = (pitch + g.gyro.y*dt/1000)*0.5 + 0.5*atan(-1 * a.acceleration.x / sqrt(pow(a.acceleration.y, 2) + pow(a.acceleration.z, 2)));
rollf = (1-k)*rollf + k*roll;
pitchf = (1-k)*pitchf + k*pitch;
rolld = rollf * 180 / 3.1415926;
pitchd = pitchf * 180 / 3.1415926;
Serial.println("");
Serial.print("Roll: ");
Serial.print(rolld);
Serial.print(" Pitch: ");
Serial.print(pitchd);
Serial.println("");
delay(10);
}
The MPU-6050 was discontinued by the original manufacturer many years ago, and you can only hope that the counterfeits or clones you can buy today will perform correctly and reliably, if at all.
Try this much simpler code and see if it shows a similar problem.
// minimal MPU-6050 tilt and roll. Works with MPU-9250 too.
// works perfectly with GY-521, pitch and roll signs agree with arrows on sensor module 7/2019
//
// Tested with 3.3V eBay Pro Mini with no external pullups on I2C bus (worked with internal pullups)
// Add 4.7K pullup resistors to 3.3V if required. A4 = SDA, A5 = SCL
#include<Wire.h>
const int MPU_addr1 = 0x68;
float xa, ya, za, roll, pitch;
void setup() {
Wire.begin(); //begin the wire communication
Wire.beginTransmission(MPU_addr1); //begin, send the slave adress (in this case 68)
Wire.write(0x6B); //make the reset (place a 0 into the 6B register)
Wire.write(0);
Wire.endTransmission(true); //end the transmission
Serial.begin(9600);
}
void loop() {
Wire.beginTransmission(MPU_addr1);
Wire.write(0x3B); //send starting register address, accelerometer high byte
Wire.endTransmission(false); //restart for read
Wire.requestFrom(MPU_addr1, 6); //get six bytes accelerometer data
int t = Wire.read();
xa = (t << 8) | Wire.read();
t = Wire.read();
ya = (t << 8) | Wire.read();
t = Wire.read();
za = (t << 8) | Wire.read();
// formula from https://wiki.dfrobot.com/How_to_Use_a_Three-Axis_Accelerometer_for_Tilt_Sensing
roll = atan2(ya , za) * 180.0 / PI;
pitch = atan2(-xa , sqrt(ya * ya + za * za)) * 180.0 / PI; //account for roll already applied
Serial.print("roll = ");
Serial.print(roll,1);
Serial.print(", pitch = ");
Serial.println(pitch,1);
delay(400);
}
I was able to confirm it was in fact the floating pin by running it for extended time while grounded, no freezing. Then I disconnected the pin and it would occasionally freeze. And I could reproduce the issue and cause instant freeze by feeding the pin a logic high.