Error using Structures

Hi all,

I’m trying to calculate the errors of my sensors on the MPU-6050, and then feeding this into the loop where it calculates the values in real time. I am using a structure to calculate these errors. However, I am getting errors of the form “error: expected initializer before ‘e’” in my code (attached). I haven’t coded in C++ in 2+ years, so I’m a little rusty, but I can’t seem to find my error here. Please let me know if you see anything! Thank you.

imuTest2.ino (6.45 KB)

#include <Wire.h>
const int MPU = 0x68; // MPU6050 I2C address
float AccX, AccY, AccZ;
float GyroX, GyroY, GyroZ;
float accAngleX, accAngleY, gyroAngleX, gyroAngleY, gyroAngleZ;
float roll, pitch, yaw;
float AccErrorX, AccErrorY, GyroErrorX, GyroErrorY, GyroErrorZ;
float elapsedTime, currentTime, previousTime;
int c = 0;
int count = 0;

struct Errors {
  float gyroXerror;
  float gyroYerror;
  float gyroZerror;
  float accelXerror;
  float accelYerror;
}
Errors e;

void setup() {
  Serial.begin(19200);
  Wire.begin();                      // Initialize comunication
  Wire.beginTransmission(MPU);       // Start communication with MPU6050 // MPU=0x68
  Wire.write(0x6B);                  // Talk to the register 6B
  Wire.write(0x00);                  // Make reset - place a 0 into the 6B register
  Wire.endTransmission(true);        //end the transmission
  /*
  // Configure Accelerometer Sensitivity - Full Scale Range (default +/- 2g)
  Wire.beginTransmission(MPU);
  Wire.write(0x1C);                  //Talk to the ACCEL_CONFIG register (1C hex)
  Wire.write(0x10);                  //Set the register bits as 00010000 (+/- 8g full scale range)
  Wire.endTransmission(true);
  // Configure Gyro Sensitivity - Full Scale Range (default +/- 250deg/s)
  Wire.beginTransmission(MPU);
  Wire.write(0x1B);                   // Talk to the GYRO_CONFIG register (1B hex)
  Wire.write(0x10);                   // Set the register bits as 00010000 (1000deg/s full scale)
  Wire.endTransmission(true);
  delay(20);
  */
  delay(20);
}
void loop() {
  if (count == 0) {
    e = calculate_IMU_error();
  }
  // === Read acceleromter data === //
  Wire.beginTransmission(MPU);
  Wire.write(0x3B); // Start with register 0x3B (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(MPU, 6, true); // Read 6 registers total, each axis value is stored in 2 registers
  //For a range of +-2g, we need to divide the raw values by 16384, according to the datasheet
  AccX = (Wire.read() << 8 | Wire.read()) / 16384.0; // X-axis value
  AccY = (Wire.read() << 8 | Wire.read()) / 16384.0; // Y-axis value
  AccZ = (Wire.read() << 8 | Wire.read()) / 16384.0; // Z-axis value
  // Calculating Roll and Pitch from the accelerometer data
  accAngleX = (atan(AccY / sqrt(pow(AccX, 2) + pow(AccZ, 2))) * 180 / PI) - e.accelXerror; // AccErrorX ~(1.77) See the calculate_IMU_error()custom function for more details
  accAngleY = (atan(-1 * AccX / sqrt(pow(AccY, 2) + pow(AccZ, 2))) * 180 / PI) - e.accelYerror; // AccErrorY ~(-5.53)
  // === Read gyroscope data === //
  previousTime = currentTime;        // Previous time is stored before the actual time read
  currentTime = millis();            // Current time actual time read
  elapsedTime = (currentTime - previousTime) / 1000; // Divide by 1000 to get seconds
  Wire.beginTransmission(MPU);
  Wire.write(0x43); // Gyro data first register address 0x43
  Wire.endTransmission(false);
  Wire.requestFrom(MPU, 6, true); // Read 4 registers total, each axis value is stored in 2 registers
  GyroX = (Wire.read() << 8 | Wire.read()) / 131.0; // For a 250deg/s range we have to divide first the raw value by 131.0, according to the datasheet
  GyroY = (Wire.read() << 8 | Wire.read()) / 131.0;
  GyroZ = (Wire.read() << 8 | Wire.read()) / 131.0;
  // Correct the outputs with the calculated error values
  GyroX = GyroX - e.gyroXerror; // GyroErrorX ~
  GyroY = GyroY - e.gyroYerror; // GyroErrorY ~
  GyroZ = GyroZ - e.gyroZerror; // GyroErrorZ ~ 
  // Currently the raw values are in degrees per seconds, deg/s, so we need to multiply by sendonds (s) to get the angle in degrees
  gyroAngleX = gyroAngleX + GyroX * elapsedTime; // deg/s * s = deg
  gyroAngleY = gyroAngleY + GyroY * elapsedTime;
  yaw =  yaw + GyroZ * elapsedTime;
  // Complementary filter - combine acceleromter and gyro angle values
  roll = 0.99 * gyroAngleX + 0.01 * accAngleX;
  pitch = 0.96 * gyroAngleY + 0.04 * accAngleY;
  
  // Print the values on the serial monitor
  Serial.print(roll);
  Serial.print("/");
  Serial.print(pitch);
  Serial.print("/");
  Serial.println(yaw);
  count++;
}

Errors calculate_IMU_error() {
  // We can call this funtion in the setup section to calculate the accelerometer and gyro data error. From here we will get the error values used in the above equations printed on the Serial Monitor.
  // Note that we should place the IMU flat in order to get the proper values, so that we then can the correct values
  // Read accelerometer values 200 times
  Errors imu_errors;
  
  while (c < 10000) {
    Wire.beginTransmission(MPU);
    Wire.write(0x3B);
    Wire.endTransmission(false);
    Wire.requestFrom(MPU, 6, true);
    AccX = (Wire.read() << 8 | Wire.read()) / 16384.0 ;
    AccY = (Wire.read() << 8 | Wire.read()) / 16384.0 ;
    AccZ = (Wire.read() << 8 | Wire.read()) / 16384.0 ;
    // Sum all readings
    AccErrorX = AccErrorX + ((atan((AccY) / sqrt(pow((AccX), 2) + pow((AccZ), 2))) * 180 / PI));
    AccErrorY = AccErrorY + ((atan(-1 * (AccX) / sqrt(pow((AccY), 2) + pow((AccZ), 2))) * 180 / PI));
    c++;
  }
  //Divide the sum by 200 to get the error value
  AccErrorX = AccErrorX / 10000;
  AccErrorY = AccErrorY / 10000;
  
  c = 0;
  // Read gyro values 200 times
  while (c < 10000) {
    Wire.beginTransmission(MPU);
    Wire.write(0x43);
    Wire.endTransmission(false);
    Wire.requestFrom(MPU, 6, true);
    GyroX = Wire.read() << 8 | Wire.read();
    GyroY = Wire.read() << 8 | Wire.read();
    GyroZ = Wire.read() << 8 | Wire.read();
    // Sum all readings
    GyroErrorX = GyroErrorX + (GyroX / 131.0);
    GyroErrorY = GyroErrorY + (GyroY / 131.0);
    GyroErrorZ = GyroErrorZ + (GyroZ / 131.0);
    c++;
  }
  
  //Divide the sum by 200 to get the error value
  GyroErrorX = GyroErrorX / 10000;
  GyroErrorY = GyroErrorY / 10000;
  GyroErrorZ = GyroErrorZ / 10000;

  imu_errors.gyroXerror = GyroErrorX;
  imu_errors.gyroYerror = GyroErrorY;
  imu_errors.gyroZerror = GyroErrorZ;
  imu_errors.accelXerror = AccErrorX;
  imu_errors.accelYerror = AccErrorY;

  return imu_errors;
  
  // Print the error values on the Serial Monitor
  //Serial.print("AccErrorX: ");
  //Serial.println(AccErrorX);
  //Serial.print("AccErrorY: ");
  //Serial.println(AccErrorY);
  //Serial.print("GyroErrorX: ");
  //Serial.println(GyroErrorX);
  //Serial.print("GyroErrorY: ");
  //Serial.println(GyroErrorY);
  //Serial.print("GyroErrorZ: ");
  //Serial.println(GyroErrorZ);
}

1.) Use useful variable names instead of “e” (curious, is this a nod to Python exceptions?)
2.) You need to move “Errors e” to the setup() function

If I move Errors e to the setup() function, wouldn't the loop() function not know of it when I calculate e in the line e = calculate_IMU_error()? Because it's a local variable in the setup function

josh_pili:
However, I am getting errors of the form "error: expected initializer before 'e'" in my code (attached).

Knowing you are getting "errors of the form" is useless information. If you copied the exact error messages (there's a button in the IDE for that) and post them here, that would be useful information.

Also, post code and error messages using Code Tags.

Power_Broker:
1.) Use useful variable names instead of "e" (curious, is this a nod to Python exceptions?)

Good advice.

2.) You need to move "Errors e" to the setup() function

Ignore that advice.

If you're going to declare the struct and define a variable of that type at the same time, then proper syntax is:

struct Errors {
  float gyroXerror;
  float gyroYerror;
  float gyroZerror;
  float accelXerror;
  float accelYerror;
} e;

gfvalvo, thanks for the third suggestion! It works perfectly now! I'm a bit surprised why it was giving an error when I just did "Errors e" instead of what you suggested though.

josh_pili:
I'm a bit surprised why it was giving an error when I just did "Errors e" instead of what you suggested though.

You left off the ';' at the end of the struct delcaration:

struct Errors {
  float gyroXerror;
  float gyroYerror;
  float gyroZerror;
  float accelXerror;
  float accelYerror;
};

Errors e;

josh_pili:
If I move Errors e to the setup() function, wouldn't the loop() function not know of it when I calculate e in the line e = calculate_IMU_error()? Because it's a local variable in the setup function

Oof, true