1

I am new to this platform, so please if I do something against the regular rules please let me know so I can learn. Now my problem: I have a nodeMCU V3 connected to a MPU6050. Using my Arduino Uno I do get sensible values in the order of 0 degrees when the device is flat. Using the same code and the same setup I get very strange values in the order of 45 degrees when the device is flat. I have tried the following:

  1. Using the I2C scanner I do get a valid address.
  2. Testing with the Arduino Uno the values are correct.
  3. The GY 521 breakout uses 3V3 datalines with 2k2 pull ups. Datalines are short. Eg on the same breadboard.
  4. The GY 521 has a voltage regulator on board for 5V, so I feed the device with 5V in order to overcome a voltage drop problem.
  5. I have tried to stretch the stretchClock function but no luck.

I have read about people with a similar kind of issue, but I could not find a solution. Anyone that can help me? Apoligies. It would be more handy to attach my code: '' /* * I2C example sketch for ESP8266 */

#include <Wire.h>


const int DevID = 0x68;
const int PWR_MGT1_REG = 0x6B;

const int DataReg_AX = 0x3B;
const int DataReg_AY = 0x3D;
const int DataReg_AZ = 0x3F;
const int AccConfigReg = 0x1C;
const int GyrConfigReg = 0x1B;
const int SelfTestReg = 0x0D;

const int TempReg = 0x41;

const int DataReg_GX = 0x43;
const int DataReg_GY = 0x45;
const int DataReg_GZ = 0x47;

const int CalibrationConfigAcc = 0xF0;//set this value for calibration
const int CalibrationConfigGyr = 0xE0;//set this value for calibration
const int NormalConfigAcc = 0x00;//set this value for calibration 2G
const int NormalConfigGyr = 0x00;//set this value for calibration 250dps

/*
  int16_t Acc_X;
  int16_t Acc_Y;
  int16_t Acc_Z;
*/
float Acc_X, accAngleX, accAngleY, Yaw_Angle;
float Acc_Y;
float Acc_Z;

//double Acc_X, accAngleX, accAngleY, Yaw_Angle;
//double Acc_Y;
//double Acc_Z;

int8_t X_selfTest;
int8_t Y_selfTest;
int8_t Z_selfTest;
int8_t Acc_X_Y_Z_selfTest;

int16_t Temp;
/*
  int16_t Gyro_X;
  int16_t Gyro_Y;
  int16_t Gyro_Z;
*/
float Gyro_X;
float Gyro_Y;
float Gyro_Z;

int16_t Gyro_X_selfTest;
int16_t Gyro_Y_selfTest;
int16_t Gyro_Z_selfTest;

//int SDApin = 3;//create I2C pinouts for ESP8266;
//int SCLpin = 4;

unsigned long elapsedTime, previousTime, currentTime;

void setup() {// put your setup code here, to run once:
  Serial.begin(115200);
  Wire.begin ();
 // Wire.setClock(400000);
//  Wire.setClockStretchLimit(40000);
  Wire.beginTransmission(DevID);
  Wire.write(PWR_MGT1_REG);
  Wire.write(0x0);// wake up the sensor
  Wire.endTransmission();
  CalibrationProcedure();// enter calibration procedure
}

void loop() {// put your main code here, to run repeatedly:

previousTime = currentTime;
currentTime = millis();
 elapsedTime = (currentTime - previousTime) / 1000;


  Wire.beginTransmission(DevID);
  Wire.write(DataReg_AX);
  Wire.endTransmission();

  Wire.requestFrom(DevID, 14);
  if (Wire.available() == 14) {
    Acc_X = ((Wire.read() << 8) | (Wire.read())) / 16384.0;// divide by 16384 for 2G setting according to datasheet
    Acc_Y = ((Wire.read() << 8) | (Wire.read())) / 16384.0;
    Acc_Z = ((Wire.read() << 8) | (Wire.read())) / 16384.0;
    Temp = (Wire.read() << 8) | (Wire.read());
    Gyro_X = ((Wire.read() << 8) | (Wire.read()))  / 131.0; // divide by 131.0 according to datasheet for setting 250 dps
    Gyro_Y = ((Wire.read() << 8) | (Wire.read())) / 131.0;
    Gyro_Z = ((Wire.read() << 8) | (Wire.read())) / 131.0;
    delay(500);
  }

  //The formulas below have been extracted from another program and uses mathematical
  //values for calulation of pitch roll and yaw. For the moment only pitch is calibrated
  //The next purpose of this program is follow a calibration procedure to take approx 200 samples
  //and average the total value to correct the pitch roll and yaw value
  accAngleX = (atan(Acc_Y / sqrt(pow(Acc_X, 2) + pow(Acc_Z, 2))) * 180 / PI);
  accAngleY = (atan(-1 * Acc_X / sqrt(pow(Acc_Y, 2) + pow(Acc_Z, 2))) * 180 / PI);
  Yaw_Angle = Yaw_Angle + Gyro_Z * elapsedTime; 

  float Gyro_X_axis = (float)Gyro_X / 131.0;
  float Gyro_Y_axis = (float)Gyro_Y / 131.0;
  float Gyro_Z_axis = (float)Gyro_Z / 131.0;
  float Temperature = (Temp / (340.0)) + 36.53;
  //Serial.print(" Accelero X \t" );
  //Serial.print(Acc_X);
  //Serial.print(" Accelero Y \t" );
  //Serial.print(Acc_Y);
  //Serial.print(" Accelero Z \t");
  //Serial.print(Acc_Z);
  //Serial.println("");
  //Serial.print(" Gyro X \t" );
  //Serial.print(Gyro_X);
  //Serial.print(" Gyro Y \t" );
  //Serial.print(Gyro_Y);
  //Serial.print(" Gyro Z \t");
  //Serial.print(Gyro_Z);
  //Serial.print(" Temperature \t");
  //Serial.println(Temperature);
  //Serial.println(Temp);
  Serial.println ("Angle X");
  Serial.println(accAngleX);
  Serial.println ("Angle Y");
  Serial.println (accAngleY);
  Serial.println("Yaw Angle");
  Serial.println(Yaw_Angle);
  delay(500);
}

void CalibrationProcedure() {
  Serial.println("Keep sensor steady until calibration process is complete!");
  Wire.beginTransmission(DevID);
  Wire.write(AccConfigReg);//8 g
  Wire.write(CalibrationConfigAcc);
  Wire.endTransmission();
  delay(250);
  Wire.beginTransmission(DevID);
  Wire.write(GyrConfigReg);
  Wire.write(CalibrationConfigGyr);//250 deg/s
  Wire.endTransmission();
  delay(500);
  Serial.println("Selftest enabled, reading data...");

  Wire.beginTransmission(DevID);
  Wire.write(SelfTestReg);
  Wire.endTransmission();

  Wire.requestFrom(DevID, 4);
  if (Wire.available() <= 4) {
    X_selfTest = Wire.read();
    Y_selfTest = Wire.read();
    Z_selfTest =  Wire.read();
    Acc_X_Y_Z_selfTest = Wire.read();
    delay(500);
  }

  //extracting factory trim values after self test
  //unsigned integers for accelero variables
  uint8_t XA_selfTest;
  uint8_t YA_selfTest;
  uint8_t ZA_selfTest;
  //unsigned integers for gyro variables
  uint8_t GX_selfTest;
  uint8_t GY_selfTest;
  uint8_t GZ_selfTest;
  //Factory Trim variables
  float FTGX;
  float FTGY;
  float FTGZ;
  float FTAX;
  float FTAY;
  float FTAZ;

  float SelfTestPercentage_GX;
  float SelfTestPercentage_GY;
  float SelfTestPercentage_GZ;
  float SelfTestPercentage_AX;
  float SelfTestPercentage_AY;
  float SelfTestPercentage_AZ;

  GX_selfTest = X_selfTest & 0x1F; // 0x1F is a bit mask to extract the first 5 bits. unsigned format
  GY_selfTest = Y_selfTest & 0x1F;
  GZ_selfTest = Z_selfTest & 0x1F;
  XA_selfTest = (X_selfTest >> 3) | (Acc_X_Y_Z_selfTest & 0x30) >> 4; //shift the first 3 bits and extract bits with a mask depending on the LSB postion in the last received mixed byte
  YA_selfTest = (Y_selfTest >> 3) | (Acc_X_Y_Z_selfTest & 0x0C) >> 2;
  ZA_selfTest = (Z_selfTest >> 3) | (Acc_X_Y_Z_selfTest & 0x03);

  Serial.println ("XA_selfTest");
  Serial.println (X_selfTest, HEX);
  Serial.println("YA_selfTest");
  Serial.println(Y_selfTest, HEX);
  Serial.println("ZA_selfTest");
  Serial.println(Z_selfTest, HEX);
  Serial.println("Acc_X_Y_Z_selfTest");
  Serial.println(Acc_X_Y_Z_selfTest, HEX);

  //calculate the factory trim settings
  FTGX = (25.0 * 131.0) * (pow(1.046, ((float)GX_selfTest - 1.0)));// Factortrim Gyro X
  FTGY = (-25.0 * 131.0) * (pow(1.046, ((float)GY_selfTest - 1.0)));// Factortrim Gyro Y
  FTGZ = (25.0 * 131.0) * (pow(1.046, ((float)GZ_selfTest - 1.0)));// Factortrim Gyro Z
  FTAX = (4096.0 * 0.34) * (pow((0.92 / 0.34), (((float)XA_selfTest - 1.0) / 30.0)));
  FTAY = (4096.0 * 0.34) * (pow((0.92 / 0.34), (((float)YA_selfTest - 1.0) / 30.0)));
  FTAZ = (4096.0 * 0.34) * (pow((0.92 / 0.34), (((float)ZA_selfTest - 1.0) / 30.0)));
  Serial.println("Selftest ended...please copy data");
  Serial.println(" GX trim value\t" );
  Serial.println(FTGX);
  Serial.println(" GY trim value\t" );
  Serial.println(FTGY);
  Serial.println(" GZ trim value\t");
  Serial.println(FTGZ);
  Serial.println(" AX trim value\t" );
  Serial.println(FTAX);
  Serial.println(" AY trim value\t" );
  Serial.println(FTAY);
  Serial.println(" AZ trim value\t");
  Serial.println(FTAZ);
  SelfTestPercentage_GX = 100.0 + 100.0 * ((float)GX_selfTest - FTGX) / FTGX;
  Serial.println("SelfTestPercentage");
  Serial.println(SelfTestPercentage_GX);
  SelfTestPercentage_GY = 100.0 + 100.0 * ((float)GY_selfTest - FTGY) / FTGY;
  Serial.println("SelfTestPercentage");
  Serial.println(SelfTestPercentage_GY);
  SelfTestPercentage_GZ = 100.0 + 100.0 * ((float)GZ_selfTest - FTGZ) / FTGZ;
  Serial.println("SelfTestPercentage");
  Serial.println(SelfTestPercentage_GZ);
  SelfTestPercentage_AX = 100.0 + 100.0 * ((float)XA_selfTest - FTAX) / FTAX;
  Serial.println("SelfTestPercentage Acclero x, y, z");
  Serial.println(SelfTestPercentage_AX);
  SelfTestPercentage_AY = 100.0 + 100.0 * ((float)YA_selfTest - FTAY) / FTAY;
  Serial.println("SelfTestPercentage Acclero x, y, z");
  Serial.println(SelfTestPercentage_AY);
  SelfTestPercentage_AZ = 100.0 + 100.0 * ((float)ZA_selfTest - FTAZ) / FTAZ;
  Serial.println("SelfTestPercentage Acclero x, y, z");
  Serial.println(SelfTestPercentage_AZ);

  // get data outputs with self test enabled
  Wire.beginTransmission(DevID);
  Wire.write(DataReg_AX);
  Wire.endTransmission();

  Wire.requestFrom(DevID, 14);
  if (Wire.available() <= 14) {
    Acc_X = (Wire.read() << 8) | (Wire.read());
    Acc_Y = (Wire.read() << 8) | (Wire.read());
    Acc_Z = (Wire.read() << 8) | (Wire.read());
    Temp = (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(500);
  }
  //print values with self test enabled
  Serial.println("Self test enabled values");
  Serial.println(" Accelero X " );
  Serial.println(Acc_X);
  Serial.println(" Accelero Y " );
  Serial.println(Acc_Y);
  Serial.println(" Accelero Z ");
  Serial.println(Acc_Z);
  Serial.println(" Gyro X " );
  Serial.println(Gyro_X);
  Serial.println(" Gyro Y " );
  Serial.println(Gyro_Y);
  Serial.println(" Gyro Z ");
  Serial.println(Gyro_Z);
  delay(500);

  //setup the device for normal OPS
  Wire.beginTransmission(DevID);
  Wire.write(AccConfigReg);
  Wire.write(NormalConfigAcc);
  Wire.endTransmission();
  delay(50);
  Wire.beginTransmission(DevID);
  Wire.write(GyrConfigReg);
  Wire.write(NormalConfigGyr);
  Wire.endTransmission();
  delay(50);

  //request data with self test not enabled
  Wire.beginTransmission(DevID);
  Wire.write(DataReg_AX);
  Wire.endTransmission();

  Wire.requestFrom(DevID, 14);
  if (Wire.available() <= 14) {
    Acc_X = (Wire.read() << 8) | (Wire.read());
    Acc_Y = (Wire.read() << 8) | (Wire.read());
    Acc_Z = (Wire.read() << 8) | (Wire.read());
    Temp = (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(500);
    //print values with self test not enabled
    Serial.println("Self test not enabled values");
    Serial.println(" Accelero X " );
    Serial.println(Acc_X);
    Serial.println(" Accelero Y " );
    Serial.println(Acc_Y);
    Serial.println(" Accelero Z ");
    Serial.println(Acc_Z);
    Serial.println(" Gyro X " );
    Serial.println(Gyro_X);
    Serial.println(" Gyro Y " );
    Serial.println(Gyro_Y);
    Serial.println(" Gyro Z ");
    Serial.println(Gyro_Z);
    delay(5000);
  }
}
'''
15
  • You said you get good values then you said you get bad values. What changes in between? Do you think posting the code and the wiring would be smart? Or do you think it’s smarter to have us guess at what you did?
    – Delta_G
    May 3 '20 at 13:41
  • Sorry! I attached my code. The only change I basically did was converting the same code from the Uno to a NodeMCU using the standard I2C pins. When the device is flat the Uno reads 0 degrees which is correct. But with the NodeMCU I get values of 45 degrees jumping up and down.
    – sanrays10
    May 3 '20 at 14:07
  • Aha, so there's a NodeMCU involved? Why didn't you mention that in the question? You didn't think that might be important?
    – Delta_G
    May 3 '20 at 14:08
  • I wrote that down in my question right? In case it was not clear, sorry.
    – sanrays10
    May 3 '20 at 14:44
  • I was talking about the "using the same code and same setup" which would imply the same board. That confused me.
    – Delta_G
    May 3 '20 at 14:47
0

I had the same issue sometime back.I was able to get good results using the example given for the ESP8266 in the MPU6050 library itself.You can make the necessary changes starting from that sketch.Hope this helps.

Heres the github link to the library https://github.com/ElectronicCats/mpu6050

5
  • Thank you! My purpose was to write with the Wire.h library. But for reference purposes I will try to use it. I let you know about the result!
    – sanrays10
    May 3 '20 at 14:08
  • It seems to work if I use the very standard output file and implementation of my formulas. But I am really wondering why? Do they use a different I2C library? What am I missing?
    – sanrays10
    May 3 '20 at 15:47
  • see my answer above....Don't know if you had the same issue?
    – sanrays10
    May 3 '20 at 22:44
  • Yeah I had the same issue.What happens when you try to get the readings out of the accelerometer and gyroscope like you have done is that all your reading aren't filtered.So things like gyro drift come into play and have a significant effect on the output.But the library is made so that those raw values you obtain go through a FIFO buffer and also the Digital Motion Processor on your MPU6050. These two will effectively fuse the sensor data and minimize the errors.I found that the best way to get readings is using the library but it has some drawbacks as well.
    – AfiJaabb
    May 4 '20 at 9:32
  • Well in my case the division after reading data and bitshifting was not working. If you comment it out feel free to try. I am not using any FIFO registers etc. I was just playing around with I2C. Thanks for your input!
    – sanrays10
    May 4 '20 at 20:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.