MPU-6050 nan Output un Redboard Artemis

Hello,

I am currently working on rewriting my ongoing drone auto level program from an Arduino Uno to a faster Sparkfun Redboard Artemis. First step is to get the angle data from the MPU-6050(Accelerometer and gyroscope combined). So I got a working Arduino Code for testing and it works fine on my old Arduino Uno, but when I load the same code to the Redboard it outputs really weird data or “Nan”.

The MPU-6050 is attached to the sda and scl Pin.

Here is the testing programm:

#include <Wire.h>


int escm1, escm2, escm3, escm4;
int all_esc, e1, e2, e3, e4, es1, es2, es3, es4, emp;
int gyro_x, gyro_y, gyro_z;
long acc_x, acc_y, acc_z, acc_total_vector;
int temperature;
long gyro_x_cal, gyro_y_cal, gyro_z_cal, angle_pitch_acc_cal, angle_roll_acc_cal;
float angle_pitch, angle_roll;
int angle_pitch_buffer, angle_roll_buffer;
boolean set_gyro_angles;
float angle_roll_acc, angle_pitch_acc;
float angle_pitch_output, angle_roll_output;
double pwm1, pwm2, pwm3, pwm4;


void setup() 
{
  Serial.begin(57600);
  Wire.begin();
  //Wire.setClock(400000);

  setup_mpu_6050_registers();                          

  Serial.print("MPU-6050 IMU");
  Serial.println("\t");
  delay(1500);
  Serial.print("Kalibriere Gyro:");


    for (int cal_int = 0; cal_int < 2000 ; cal_int ++){                
    if(cal_int % 125 == 0)Serial.print(".");                           
    read_mpu_6050_data();                                             
    gyro_x_cal += gyro_x;                                             
    gyro_y_cal += gyro_y;                                             
    gyro_z_cal += gyro_z;                                            
    delay(3);                                                         
  }
  gyro_x_cal /= 2000;                                                  
  gyro_y_cal /= 2000;                                                  
  gyro_z_cal /= 2000;    
}

void loop() {
  read_mpu_6050_data();

  gyro_x -= gyro_x_cal;                                                
  gyro_y -= gyro_y_cal;                                                
  gyro_z -= gyro_z_cal;                                               

  //Gyro angle calculations
  //0.0000611 = 1 / (250Hz / 65.5)
  angle_pitch += gyro_x * 0.0000611;                                 
  angle_roll += gyro_y * 0.0000611;    

  
  angle_pitch += angle_roll * sin(gyro_z * 0.000001066);               
  angle_roll -= angle_pitch * sin(gyro_z * 0.000001066);               


  acc_total_vector = sqrt((acc_x*acc_x)+(acc_y*acc_y)+(acc_z*acc_z));  
  
  angle_pitch_acc = asin((float)acc_y/acc_total_vector)* 57.296;      
  angle_roll_acc = asin((float)acc_x/acc_total_vector)* -57.296;      

  // acc Output auf gerader Fläche:
  angle_pitch_acc -= 1.1 ;                                             
  angle_roll_acc -= -1,7 ;                                             

  if(set_gyro_angles){                                                 
    angle_pitch = angle_pitch * 0.9996 + angle_pitch_acc * 0.0004;     
    angle_roll = angle_roll * 0.9996 + angle_roll_acc * 0.0004;        
  }
  else{                                                                
    angle_pitch = angle_pitch_acc;                                      
    angle_roll = angle_roll_acc;                                        
    set_gyro_angles = true;                                            
  }
   
  angle_pitch_output = angle_pitch_output * 0.85 + angle_pitch * 0.15; 
  angle_roll_output = angle_roll_output * 0.85 + angle_roll * 0.15;

  Serialprint();
  

}

void read_mpu_6050_data(){                                            
  Wire.beginTransmission(0x68);                                       
  Wire.write(0x3B);                                                   
  Wire.endTransmission();                                             
  Wire.requestFrom(0x68,14);            
  while(Wire.available() < 14);         
  acc_x = Wire.read()<<8|Wire.read();                       
  acc_y = Wire.read()<<8|Wire.read();                       
  acc_z = Wire.read()<<8|Wire.read();                                 
  temperature = Wire.read()<<8|Wire.read();                            
  gyro_x = Wire.read()<<8|Wire.read();                                 
  gyro_y = Wire.read()<<8|Wire.read();                                
  gyro_z = Wire.read()<<8|Wire.read();                               

}



void setup_mpu_6050_registers(){
  //Activate the MPU-6050
  Wire.beginTransmission(0x68);                                       
  Wire.write(0x6B);                                                   
  Wire.write(0x00);                                                     
  Wire.endTransmission();                                             
  //Configure the accelerometer (+/-8g)
  Wire.beginTransmission(0x68);                                      
  Wire.write(0x1C);                                                    
  Wire.write(0x10);                                                 
  Wire.endTransmission();                                     
  //Configure the gyro (500dps full scale)
  Wire.beginTransmission(0x68);                                   
  Wire.write(0x1B);                                              
  Wire.write(0x08);                                          
  Wire.endTransmission();                                   
}


void Serialprint(){
  Serial.print("X:");
  Serial.print(angle_roll_output);
  Serial.print("\t");
  Serial.print("\t");
  Serial.print("Y:");
  Serial.println(angle_pitch_output);

}

void acc_angle_calculations(){
  acc_total_vector = sqrt((acc_x*acc_x)+(acc_y*acc_y)+(acc_z*acc_z));  
  
  angle_pitch_acc = asin((float)acc_y/acc_total_vector)* 57.296;    
  angle_roll_acc = asin((float)acc_x/acc_total_vector)* -57.296;       
  
}

Here is the Arduino Output(as it should be):

https://ibb.co/wrBfwY3

And here the Redboard Ouput:

https://ibb.co/7zPrBRw

I would really appreciate the help

Thanks

I imagine that the libraries for the MPU-6050 are probably not compatible with the Artemis. You might search around for alternate libraries to see if one of those is better behaved.

I dont use any libraries except the wire library, the communication is working over I2C, which should run on every board. Im confused because sometimes it outputs right data. Do you got any ideas how i could test if the i2c Pins are working fine?

If you’re getting any correct data back at all, the SCL and SDA pins are working.

You might try connecting a logic analyzer to the I2C bus and monitoring traffic both when things are working and when they stop working to see what’s going on. Might be an error in your code, could be a hardware issue with the sensor or possibly something wacky with the core files for the artemis. Once you have a copy of what’s on the bus, you can start narrowing down on what’s causing the issue.

You might also try running your code on a different micro to see if you get the same results or the issue goes away.

So i think it isn’t a hardware issue, because when i run a I2C scanner on the redboard it recognises the port 68, which is the sensor i use. Also i tried my old arduino uno with exactly the same code, and it just worked fine. So the only thing i thought could be the problem is the wire.h library from sprakfun for apollo 3. Does anybody had some issues with it or does it work different as the arduinos wire library?

So I tried to read the raw values of the mpu 6050 and I finnaly got numbers as an ouput, well the problem is, these make absolutely no sense. I really dont know where the problem is but every time i run the sketch on my reboard artemis, the values are weird as hell.

Here is the simplefied code I use:

#include <Wire.h>

int gyro_x, gyro_y, gyro_z;
long acc_x, acc_y, acc_z, acc_total_vector;
int temperature;


void setup() {
  
  Serial.begin(9600);
  Wire.begin();

  //Setting up some registers to turn on the sensor and configuration
  Wire.beginTransmission(0x68);                                       
  Wire.write(0x6B);                                                   
  Wire.write(0x00);                                                     
  Wire.endTransmission();                                             
  //Configure the accelerometer (+/-8g)
  Wire.beginTransmission(0x68);                                      
  Wire.write(0x1C);                                                    
  Wire.write(0x10);                                                 
  Wire.endTransmission();                                     
  //Configure the gyro (500dps full scale)
  Wire.beginTransmission(0x68);                                   
  Wire.write(0x1B);                                              
  Wire.write(0x08);                                          
  Wire.endTransmission();
  
  Serial.print("MPU-6050 IMU");

}

void loop() {
  // read the raw date from the sensor and store it in some variables
  Wire.beginTransmission(0x68);                                       
  Wire.write(0x3B);                                                   
  Wire.endTransmission();                                             
  Wire.requestFrom(0x68,14);            
  while(Wire.available() < 14);         
  acc_x = Wire.read()<<8|Wire.read();                       
  acc_y = Wire.read()<<8|Wire.read();                       
  acc_z = Wire.read()<<8|Wire.read();                                 
  temperature = Wire.read()<<8|Wire.read();                            
  gyro_x = Wire.read()<<8|Wire.read();                                 
  gyro_y = Wire.read()<<8|Wire.read();                                
  gyro_z = Wire.read()<<8|Wire.read(); 

  delay(100);

  
  // print them out
  Serial.print("X:");
  Serial.print(acc_x);
  Serial.print("\t");
  Serial.print("\t");
  Serial.print("Y:");
  Serial.println(gyro_x);

}

it is very simple and I uploaded the sketch to my old arduino:

This is how the uotput should look like:https://ibb.co/9sDZt4W

This is exactly the same code on my Redboard Artemis:

https://ibb.co/Ph5LDmT

As you can see it just jumps to 64000.

I dont know if you have any ideas why it isnt working, I appreciate all the help.

C++ does not guarantee the order of evaluation of expressions like this, so you may be (probably are) reading the bytes in the wrong order.

acc_x = Wire.read()<<8|Wire.read(); 

The safe and sure way of doing this is:

uint16_t tmp=Wire.read(); //read high byte first
uint16_t acc_x = (tmp<<8) | Wire.read();

See https://en.cppreference.com/w/cpp/language/eval_order

thanks for the answer and i think this would work fine, but luckily I found my own solution:

For the arduino uno a int variable is automatically a 16-bit 2’s complement value, but for the Sparkfun, it somehow isnt 16-bit, this is why my values acted so weird.

All I had to do is changing the int variables to int16_t variables.

For everyone who got the same problem: https://youtu.be/ImctYI8hgq4

Watch this video, he explains exactly the problem had and show how to fix it.