ITG3205 + ADXL33 Pitch & Roll falls near 90º

Hi,

I’m trying to get roll & pitch from a ITG3205 gyro and ADXL335 accelerometer and put it into a processing box like a lot of videos are around the net.

From one way I read the accel raw values and tranform it to angles by this: (read from forems and datasheet)

void getAccelAnglesData()
{
  //convert read values to degrees -90 to 90 - Needed for atan2
  accelAnglesData[0] = map(accelRawData[0], 385.0f, 585.0f, -90.0f, 90.0f);
  accelAnglesData[1] = map(accelRawData[1], 380.0f, 580.0f, -90.0f, 90.0f);
  accelAnglesData[2] = map(accelRawData[2], 410.0f, 610.0f, -90.0f, 90.0f);

  //Caculate 360deg values like so: atan2(yAng, zAng)
  //atan2 outputs the value of -π to π (radians)
  //Convert it to degrees (* (180 / PI) or * RAD_TO_DEG);
  accelAnglesData[0] = atan2(accelAnglesData[0], accelAnglesData[2]) * RAD_TO_DEG;
  accelAnglesData[1] = atan2(accelAnglesData[1], accelAnglesData[2]) * RAD_TO_DEG;
  accelAnglesData[2] = atan2(accelAnglesData[0], accelAnglesData[1]) * RAD_TO_DEG;  
}

With this code I get in stationary position the reading:

X: 180º
Y: 180º
Z: 135º

If I turn it the PCB up 90º (roll), X goes from 180º to 90º, if I turn down X goes from 180º to -90º
The same on Y axis, If I turn left, Y goes from 180º to -90º, right 180º to 90º

The problem is that observing the values of Y when I turn X (in 180º) close to 90º, Y axis falls to 90º too.
(in short, if I roll PCB 90º I get X: 90º, Y 90º, Z 45º)

In other hand, I get gyro data by this:

//Convert RAW data to DEGREE/SEC
void getGyroDSData()
{ 
  gyroDSData[0] = ((double) gyroRawData[0] - gyroOffX) / 14.375;
  gyroDSData[1] = ((double) gyroRawData[1] - gyroOffY) / 14.375;
  gyroDSData[2] = ((double) gyroRawData[2] - gyroOffZ) / 14.375;
}

After this, I join all with a complementary filter

//Complementary Filter

float ALPHA = 0.98;

void getEstimatedInclination()
{
  
  int currentTime = millis();
  compFilterTimerInterval = currentTime - compFilterTimerLastTime;
  compFilterTimerLastTime = currentTime;

  // Roll
  compAngle[0] = ALPHA * (compAngle[0] + gyroDSData[0] * (compFilterTimerInterval / 1000.0f)) + (1 - ALPHA) * accelAnglesData[0]; 
  
  //Pitch
  compAngle[1] = ALPHA * (compAngle[1] + gyroDSData[1] * (compFilterTimerInterval / 1000.0f)) + (1 - ALPHA) * accelAnglesData[1]; 

  compFilterIntervalLog[compFilterIntervalLogIndex] = compFilterTimerInterval;
  compFilterIntervalLogIndex++;
  if(compFilterIntervalLogIndex > 2) compFilterIntervalLogIndex = 0;
}

And, in order to rotate box I’m using

rotateX(radians(compAngle[0]));
rotateZ(radians(compAngle[1]));

So, when I roll/pitch PCB < 90º, I get a good angle (even both axis), but when I arrive to 90º it turns 90º more.

(I dont talk about yaw because as I read from internet it not possible to get without a magnometer)

Any help will be really appreciate.

The equations you are using for the angles are not completely correct. Here is an excellent reference on obtaining pitch and roll angles from an accelerometer: http://www.freescale.com/files/sensors/doc/app_note/AN3461.pdf

Also, it is a good idea to calibrate the accelerometer, to remove bias and gain errors. See the following (for magnetometers, but works well for accelerometers too) http://sailboatinstruments.blogspot.com/2011/08/improved-magnetometer-calibration.html

I suggest you find a competent seventh-grader and ask them to explain elementary trigonometry to you, because your first program is nonsense.

Several other problems you have.

The roll/pitch paradigm fails when the roll or pitch reaches 90 degrees. It is a fundamental flaw of the way that the roll and pitch are defined. If you plane is flying upside down, is it rolled 180 degrees or pitched 180 degrees ? If your plane is pointed straight up, how much did it roll ?

This doesn’t matter very much if you plan to keep your device nice and level all the time.

The other problem is, using accelerometer for orientation only works when your device has no actual acceleration. There is a reason why most devices keep track of the orientation by integrating thegyro measurements and use the accelerometer reading for bias correction.

Well, I was trying to be kind, but in fact this:

//convert read values to degrees -90 to 90 - Needed for atan2
  accelAnglesData[0] = map(accelRawData[0], 385.0f, 585.0f, -90.0f, 90.0f);
  accelAnglesData[1] = map(accelRawData[1], 380.0f, 580.0f, -90.0f, 90.0f);
  accelAnglesData[2] = map(accelRawData[2], 410.0f, 610.0f, -90.0f, 90.0f);

is utter nonsense – however I’ve actually seen it somewhere before.

Don’t consider even a fraction of the code you download from the web to be of good or even reasonable quality; most of it has serious flaws or is completely wrong, like the above.

Refer to the Freescale application note that I linked for the correct way to go about all this.

jremington: The equations you are using for the angles are not completely correct. Here is an excellent reference on obtaining pitch and roll angles from an accelerometer: http://www.freescale.com/files/sensors/doc/app_note/AN3461.pdf

Also, it is a good idea to calibrate the accelerometer, to remove bias and gain errors. See the following (for magnetometers, but works well for accelerometers too) http://sailboatinstruments.blogspot.com/2011/08/improved-magnetometer-calibration.html

Thank you for link, I see that have a lot of formulas, It will take a while to read and understand all of it :P

I calibrate the accelerometer when I need to get the G force using these functions:

void getAccelGData()
{
  accelGData[0] = ((accelRawData[0] - accelOffX) / 102.3f);
  accelGData[1] = ((accelRawData[1] - accelOffY) / 102.3f);
  accelGData[2] = ((accelRawData[2] - accelOffZ) / 102.3f);
}

where accelOffX/Y/Z get from a loop reading a values in stationary position and take an avg of these values.

So in this link gets the angle by the same way http://tutorial.cytron.com.my/2014/09/15/accelerometer-adxl335-fast-test-and-angle-test/

michinyon: Several other problems you have.

The roll/pitch paradigm fails when the roll or pitch reaches 90 degrees. It is a fundamental flaw of the way that the roll and pitch are defined. If you plane is flying upside down, is it rolled 180 degrees or pitched 180 degrees ? If your plane is pointed straight up, how much did it roll ?

This doesn't matter very much if you plan to keep your device nice and level all the time.

It will not rotate 360º unless you want make a flip :P

michinyon: The other problem is, using accelerometer for orientation only works when your device has no actual acceleration. There is a reason why most devices keep track of the orientation by integrating thegyro measurements and use the accelerometer reading for bias correction.

Yes, is for that that I'm using a complementary filter with gyro.

Other think that I dont unserstand is why MPU6050 (that have a ITG3205 and ADXL345 integrated (I assume ADXL345 is similar to ADXL335)) works in processing with the similar code that I have...

So, in short, I think that all my problem is just how to obtain angles from acceleromters. I must use functions that jremington links me in this: http://www.freescale.com/files/sensors/doc/app_note/AN3461.pdf

Isn it?

Thank you very much.

jremington: The equations you are using for the angles are not completely correct. Here is an excellent reference on obtaining pitch and roll angles from an accelerometer: http://www.freescale.com/files/sensors/doc/app_note/AN3461.pdf

Also, it is a good idea to calibrate the accelerometer, to remove bias and gain errors. See the following (for magnetometers, but works well for accelerometers too) http://sailboatinstruments.blogspot.com/2011/08/improved-magnetometer-calibration.html

I have read the linked document and as far as I understand there is no good solution to take the pitch and roll when the accelerometer is tilted on an axis completely.

There are approaches that have been tested and good, corrects some errors that had but not "the best".

The formulas that are put forth in this link, which are those that have implemented taking the angle from the G-force accelerometer

http://developer.nokia.com/community/wiki/How_to_get_pitch_and_roll_from_accelerometer_data_on_Windows_Phone

I guess an alternative would join 3 accelerometers cube and read each axis separately and then join them

Another possibility is to use the gyroscope, which perhaps might take some filter causing drift.

Any other ideas?