Initialized int variable looses values in void loop. Why ?

Hi guys,

I´m playing around with the gyro sensor MPU6050 a little but got some problems at one point.

I initialized the int variable LSB_divisor = 4096 depending on the sensitivity in my void setup() but later in the void loop() when i want to check the variable in a function it gives back zero in the serial monitor and i don´t know why.

1.png

If I´m declaring LSB_divisor = 4096 in the function directly it works fine.
I´m a little bit frustrated but maybe you guys can tell me why its printing 0 instead of 4096.

the code is here:

// Gyroscop: MPU6050
#include <Wire.h>

#ifndef F_CPU            //If the clock speed is 16MHz include the next code line when compiling
 #define F_CPU 16000000L  //Set ClockSpeed auf 16Mhz -> Zyklus alle 0,0000000625s (0,0625µs)clock frequency, set according to clock used!
#endif                       //End of if statement

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Declaring global variables
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
char charBuffer[100];

int cal_int, timer, error, type , acc_sensitivity, LSB_divisor;
int address;

double acc_axis[2]; //gyro_axis[1]= Roll,gyro_axis[2] = pitch, gyro_axis[3] = yaw


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Setup routine
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void setup(){

 address = 0x68; // MPU6050 I2C address

 Serial.begin(57600);     //Start the serial port.
 Wire.begin();           // Wire.begin(Adresse) initialisiert die Bibliothek und meldet den Arduino mit der angegebenen Adresse am I²C-Bus an. Soll der Arduino als Busmaster angemeldet werden, entfällt die Adresse.

 acc_sensitivity = 8; // Möglichkeiten: +/- 8g, +/- 4g ,+/- 2g, +/- 160g
 type = 1;
 
 
 if(acc_sensitivity == 2)LSB_divisor = 16384.0;  // LSB Sensitivity
 else if(acc_sensitivity == 4)LSB_divisor = 8192;
 else if(acc_sensitivity == 8)LSB_divisor = 4096;
 else if(acc_sensitivity == 16)LSB_divisor = 2048;

  delay(500);

  Serial.println("LSB_divisor:");
  Serial.println(LSB_divisor);

  delay(500);
  set_gyro_registers();

}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programm routine
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void loop(){

 test_acc();
}

//Setup the MPU-6050: Registerübersicht unter C:\Users\James\Desktop\Mikrocontrolling\03_Bauteile und Datenblätter\02_Shields+Modules\Gyrosensor MPU6050
void set_gyro_registers(){

 Serial.println(F(""));
 Serial.println(F("==================================================="));
 Serial.println(F("Set Gyro Registers"));
 Serial.println(F("==================================================="));

    //Setup the MPU-6050
  if(type == 1){
    
   Wire.beginTransmission(address);                             //Start communication with the address found during search.
   Wire.write(0x6B);                                            //We want to write to the PWR_MGMT_1 register (6B hex)
   Wire.write(0x00);                                            //Set the register bits as 00000000 to activate the gyro
   Wire.endTransmission();                                      //End the transmission with the gyro.
  
   Wire.beginTransmission(address);                        //Start communication with the address found during search.
   Wire.write(0x1C);                                            //We want to write to the ACCEL_CONFIG register (1A hex)
   if(acc_sensitivity == 2)Wire.write(0b00000000); //Set the register bits as b00000000 (+/- 2g full scale range)
   else if(acc_sensitivity == 4)Wire.write(0b00001000);             //Set the register bits as b00001000 (+/- 4g full scale range)
   else if(acc_sensitivity == 8)Wire.write(0b00010000); //Set the register bits as b00010000 (+/- 8g full scale range)
   else if(acc_sensitivity == 16)Wire.write(0b00011000);            //Set the register bits as b00011000 (+/- 16g full scale range)    
   Wire.endTransmission();                                      //End the transmission with the gyro
  
   Wire.beginTransmission(address);                        //Start communication with the address found during search
   Wire.write(0x1A);                                            //We want to write to the CONFIG register (1A hex)
   Wire.write(0x03);                                            //Set the register bits as 00000011 (Set Digital Low Pass Filter to ~43Hz)
   Wire.endTransmission();                                      //End the transmission with the gyro    
 }
}

void test_acc(){

      Wire.beginTransmission(address);
      Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H)
      Wire.endTransmission(false);
      Wire.requestFrom(address,6,true); // request a total of 6 registers
  
      acc_axis[0]=(Wire.read()<<8|Wire.read())/LSB_divisor; // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
      acc_axis[1]=(Wire.read()<<8|Wire.read())/LSB_divisor; // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
      acc_axis[2]=(Wire.read()<<8|Wire.read())/LSB_divisor; // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
  
      //Only for checking the values
      Serial.println("");
   Serial.println("LSB_divisor:");
   Serial.println(LSB_divisor);
      Serial.println("AccSensitivity:");
      Serial.println(acc_sensitivity);
}

The strange thing is if I change the datatype of LSB_divisor from int to double it the serial monitor gives back LSB_divisor numbers like 4119.04 or 0.99.

2.png

I´m using a Arduino Nano Board btw.

Thank you so far.

1.png

2.png

That code compiles and runs just fine for me producing 4096 each time through the loop

You define a variable "type" that is not initialized, so will default to a value of zero. Then in your set_gyro_registers() function you only setup the MPU-6050 if type == 1, which will never be true.

david_2018:
You define a variable "type" that is not initialized, so will default to a value of zero. Then in your set_gyro_registers() function you only setup the MPU-6050 if type == 1, which will never be true.

You´re right I made a mistake in my example by forgetting to set the type. I corrected it in my first post.
But I´m still getting 0 values for

   Serial.println("LSB_divisor:");
   Serial.println(LSB_divisor);

blh64:
That code compiles and runs just fine for me producing 4096 each time through the loop

Which type of Arduino are you using ?

Maybe I have a problem with the hardware/software. Ill install the new version of the arduino IDE and will test it with another Arduino type. But thank you for your response :slight_smile:

Vertunis:
Ill install the new version of the arduino IDE and will test it with another Arduino type.

It´s still the same. I tried it with a Arduino Uno and another Nano. Still coming only zeros :frowning:

Are you using the sketch you posted?

Try running the basic_readings example sketch from the Adafruit MPU6050 library to verify your MPU-6050 is working and wired correctly.

Yeah I was using the code I posted (which is just a simple version of my actual code)

My sensor is actually working fine, I just wanted to modify my code so that I could switch the resolution of the accelerometor.

What I try to understand is:

Example 1:

//Set Variables
double acc_axis[0];
int LSB_divisor;
*double LSB_divisor;*
LSB_divisor = 4096;
acc_axis[0]=(Wire.read()<<8|Wire.read())/LSB_divisor;

void setup(){}

void loop(){
Serial.println("");
Serial.print("AcX = "); 
Serial.println(acc_axis[0]);
Serial.println("LSB_divisor:");
Serial.println(LSB_divisor);
}

Serial.println(acc_axis[0]) in Example 1 gives back wrong numbers because the variable
LSB_divisor gives back “0”.

If I declare double LSB_divisor instead of int LSB_divisor LSB_divisor is “4119.04” which is also not true

But if I set LSB_divisor with 4096 directly instead of a variable:

Example 2:

acc_axis[0]=(Wire.read()<<8|Wire.read())/[b]4096;[/b]

Serial.println(acc_axis[0]);

Serial.println(acc_axis[0]) will return what I want because the divisor is not 0 or some nonsense number.

My question is why is the serial printed value of LSB_divisor wrong in Example 1 but not in Example 2. I thought this should be the same because I´m setting the variable on the exact same value.

acc_axis[0]=(Wire.read()<<8|Wire.read())/LSB_divisor
void setup(){}

void loop(){

Please don’t post uncompilable snippets.

I really can't see a problem with the original code you posted, unfortunately I don't have the sensor here to try with the actual hardware. It has the appearance of something overwriting the variable, but your code does not appear to do that.

Neither code snippet in your last posting will compile. Please open the actual test code you are using in the Arduino IDE, then Edit > Select All followed by Edit > Copy for Forum, then paste that into a posting here, to assure that you are not typing something incorrectly.

Vertunis:
Which type of Arduino are you using ?

Maybe I have a problem with the hardware/software. Ill install the new version of the arduino IDE and will test it with another Arduino type. But thank you for your response :slight_smile:

I compiled it on a Uno using the latest IDE. I don't actually have the sensor so nothing connected to the i2c bus, but the code continuously produced 4096.

Did you try the code with the sensor removed?

blh64:
Did you try the code with the sensor removed?

Yeah I tried it without the sensor. The problem is still existing. Its always showing “0”

I think I found a solution for my question.

if I´m using:

acc_axis[0]=(Wire.read()<<8|Wire.read());
acc_axis[0]/= LSB_divisor;

instead of:

acc_axis[0]=(Wire.read()<<8|Wire.read())/LSB_divisor;
acc_axis[0]/= LSB_divisor;

everything works fine.

But

acc_axis[0]=(Wire.read()<<8|Wire.read())/4096;

is also working.

Does anyone has an explantation for this ?

Wire.read() returns an integer, LSB_divisor is an integer, so the division gives you an integer result, which is a whole number only with no decimal places. That number is then converted to a float and stored in acc_axis. That should not affect the value stored in LSB_divisor.

acc_axis[0]=(Wire.read()<<8|Wire.read())/LSB_divisor;

If you cast one of the numbers to a float it will do the math in floating point:

acc_axis[0]=(float)(Wire.read()<<8|Wire.read())/LSB_divisor;

Ah, I finally see your problem, acc_axis only has 2 elements, there is no acc_axis[2], that is what is overwriting LSB_divisor:

double acc_axis[2]; //gyro_axis[1]= Roll,gyro_axis[2] = pitch, gyro_axis[3] = yaw
 acc_axis[0]=(Wire.read()<<8|Wire.read())/LSB_divisor; // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
 acc_axis[1]=(Wire.read()<<8|Wire.read())/LSB_divisor; // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
 acc_axis[2]=(Wire.read()<<8|Wire.read())/LSB_divisor; // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
Odd that the compiler doesn't give a warning about such an obvious error, but it is also odd that the problem even shows up with your posted sketch, because acc_axis is never used except in those three equations, so the compiler removes it completely during optimization. If I add a statement to print acc_axis[2] I still get no warnings from the compiler, but LSB_divisor does get overwritten.

david_2018:

Odd that the compiler doesn’t give a warning about such an obvious error, but it is also odd that the problem even shows up with your posted sketch, because acc_axis is never used except in those three equations, so the compiler removes it completely during optimization. If I add a statement to print acc_axis[2] I still get no warnings from the compiler, but LSB_divisor does get overwritten.

Thank you very much for your explanation :slight_smile: .
I don´t know if i got i right. The reason is the optimization of the code
but is the usage of the array the problem ? And how can I avoid the problem is the future ?

Im a little confused because you say that acc_axis only has 2 elements but I
count three (acc_axis[0], acc_axis[1] and acc_axis[2]. Or am I thinking wrong ?

I
count three (acc_axis only[0], acc_axis only[1] and acc_axis only[0]. Or am I thinking wrong ?

It’s hard to know what to say.

Ok got it.

If I initialize it properly with
double acc_axis[3]={0,0,0};

it works. Forgive me my ignorance ;).

Edit:
What wasn´t clear for me was:

initializing an array works like acc_axis[2] for only 2 elements not 3
but accessing to the element works like acc_axis[2] => access to element nr. 3

This is still not logical for me but at least now I know.

When you declare an array such as acc_axis[2] you are creating a 2-element array, which will be addressed as acc_axis[0] and acc_axis[1]
All arrays start with element 0 and count from there.

Arduino Reference : Array

david_2018:
When you declare an array such as acc_axis[2] you are creating a 2-element array, which will be addressed as acc_axis[0] and acc_axis[1]
All arrays start with element 0 and count from there.

Arduino Reference : Array

Thank you for your support :wink: