I am trying to interface with an MPU6050 sensor with my nano 33 IoT but it is not working for some reason. This is my code:
#include "Wire.h"
#include <MPU6050_light.h>
MPU6050 mpu(Wire);
unsigned long timer = 0;
void setup()
{
Serial.begin(9600);
Wire.begin();
byte status = mpu.begin();
Serial.print(F("MPU6050 status: "));
Serial.println(status);
while (status != 0)
{
} // Stop program execution if connection to MPU6050 fails
Serial.println(F("Calculating offsets, do not move MPU6050"));
delay(1000);
mpu.calcOffsets(); // Calculate offsets for Gyroscope and Accelerometer
Serial.println("Done!\n");
}
void loop()
{
mpu.update();
if ((millis() - timer) > 10) // Print the data every 10ms
{
Serial.print("Pitch (X): ");
Serial.print(mpu.getAngleX());
Serial.print("\t\t\tRoll (Y): ");
Serial.print(mpu.getAngleY());
Serial.print("\t\t\tYaw (Z): ");
Serial.println(mpu.getAngleZ());
timer = millis();
}
}
This code works perfectly fine on an arduino nano classic, however, when I switch over to the nano 33 IoT, it seems to skip the setup function because it doesnt print the status of the sensor like it should in the setup. Then it goes straight to the loop function where all the values printed are just 0.00, which is obviously incorrect. Any idea why? Thank you so much!
With a new I2C sensor, it is a great idea to always run the Arduino I2C address scanner program as the first step.
That will verify communications, and report the discovered addresses. Check for the expected sensor I2C address, which must be used in the code as well.
Hint: this library is one of the worst for the MPU6050, and has several conceptual errors:
#include <MPU6050_light.h>
To collect basic 6DOF data, only the Wire library is needed. This is the minimal example:
// MPU-6050 Short Example Sketch
// By Arduino User JohnChi
// August 17, 2014
// Public Domain
#include<Wire.h>
const int MPU_addr = 0x68; // I2C address of the MPU-6050
int16_t AcX, AcY, AcZ, Tmp, GyX, GyY, GyZ;
void setup() {
Wire.begin();
Wire.beginTransmission(MPU_addr);
Wire.write(0x6B); // PWR_MGMT_1 register
Wire.write(0); // set to zero (wakes up the MPU-6050)
Wire.endTransmission(true);
Serial.begin(9600);
}
void loop() {
Wire.beginTransmission(MPU_addr);
Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H)
Wire.endTransmission(false);
Wire.requestFrom(MPU_addr, 14); // request a total of 14 registers
int16_t t = Wire.read();
AcX = (t << 8) | Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
t = Wire.read();
AcY = (t << 8) | Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
t = Wire.read();
AcZ = (t << 8) | Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
t = Wire.read();
Tmp = (t << 8) | Wire.read(); // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)
t = Wire.read();
GyX = (t << 8) | Wire.read(); // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
t = Wire.read();
GyY = (t << 8) | Wire.read(); // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
t = Wire.read();
GyZ = (t << 8) | Wire.read(); // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)
t = Wire.read();
Serial.print("AcX = "); Serial.print(AcX);
Serial.print(" | AcY = "); Serial.print(AcY);
Serial.print(" | AcZ = "); Serial.print(AcZ);
Serial.print(" | Tmp = "); Serial.print(Tmp / 340.00 + 36.53); //equation for temperature in degrees C from datasheet
Serial.print(" | GyX = "); Serial.print(GyX);
Serial.print(" | GyY = "); Serial.print(GyY);
Serial.print(" | GyZ = "); Serial.println(GyZ);
delay(333);
}
I mean I only used the MPU6050_light library because it seemed to be the only one that worked for me in terms of grabbing accurate data. But I mean I wouldn't mind switching if the data is accurate. I'm assuming that I could also calculate the pitch, roll, and yaw angles with the provided code? Sorry, I'm still a newbie on all of this. Thank you so much!
With the MPU-6050 you can estimate pitch and roll, which uses gravity as the reference. To estimate yaw (angle from true North), you need a horizon reference, like the magnetometer in a 9DOF sensor.
This simple code prints out the pitch and roll tilt angles:
// minimal MPU-6050 tilt and roll (sjr). 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);
}