Smoothing spurious MPU6050 results

Hello

I am using an MPU6050 gyro to move some RGB leds. All works fine.

But, the MPU6050 will once in a moment return a spurious value that triggers part of my code (basically if the X or Y move more than a certain amount of degrees.

It sits there lovely returning 0,0,0,0,0,0,0,0,0,0 and then suddenly it will throw in a random -7 or something.

Power supply is nice and smooth and I think it's just part of the way gyro are.

I wrote some ropey sampling code that kinda works (I'll await the horror gasps because it has a delay(5) in it.... ).
But, it does smooth the results nicely.

Any more sampling than 10 times slows the loop (and therefore the movement) of the RGBs too much (they move left and right with the Gyro).

void getGYRO() {                                                                                                        // Sample the gyro data multiple times

  for (i = 0; i <= 10; i++) {

    mpu.update();
    delay(5);

    angleXsum = angleXsum + mpu.getAngleX();  
    angleYsum = angleYsum + mpu.getAngleY();


    angleX = (angleXsum / 10);
    angleY = (angleYsum / 10);

    if (angleX < -20) {                                                                                                   // Confine the tilt extremes
      angleX = -20;
    }
    if (angleX > 20) {
      angleX = 20;
    }

    if (angleY < -20) {
      angleY = -20;
    }
    if (angleY > 20) {
      angleY = 20;
    }

    angleXsum = 0;
    angleYsum = 0;

    Serial.print("X Sum: "); Serial.println(angleX);
    Serial.print("Y Sum: "); Serial.println(angleY);
  }
}

Also, the Serial prints are usually commented out. So they don't slow the loop.

Any ideas on how to get rid of random values?

My guess is the loop allows x and y to change enough to undo the smoothing. Will a counter work?

int a, aa;

void setup() {
  Serial.begin(115200);
  randomSeed(analogRead(A0));
}

void loop() {
  a++;
  if (a > 10) {
    a = 0;
    Serial.println(aa / 10.0);
    aa = 0;
  }
  aa += random(100);
}

From:

and

it looks like angleX is an integer, and integer math might be acting unexpectedly.

From:

... it looks like it would clear the sums every iteration and essentially be int angleX = mpu.getAngleX()/10

Maybe show the full code?

I fixed it. I sampled 50 times over and removed as much as I could to speed up the loop.
It seems a lot more stable now

Thanks

Hi @baffled2023 ,

if you are interested to keep your loop() free from unnecessary delays here a version that should do it:

/*
  Forum: https://forum.arduino.cc/t/smoothing-spurious-mpu6050-results/1337284
  Wokwi: https://wokwi.com/projects/418886116138416129

  2025/01/01
  ec2021

*/

#include <MPU6050_tockn.h>
#include <Wire.h>

MPU6050 mpu(Wire);

const int minAngleX {-20};
const int maxAngleX { 20};
const int minAngleY {-20};
const int maxAngleY { 20};
const int maxCount {50};
const unsigned long interval {5};

int angleX;
int angleY;
int lastAngleX = minAngleX - 1;
int lastAngleY = minAngleY - 1;
long angleXsum;
long angleYsum;
int count = 0;
unsigned long lastMeasurement = 0;


void setup(void) {
  Serial.begin(115200);
  mpu.begin();
  mpu.calcGyroOffsets();
}

void loop() {
  getGYRO();
}

void getGYRO() {
  if (count < maxCount && millis() - lastMeasurement >= interval) {
    lastMeasurement = millis();
    mpu.update();
    angleXsum = angleXsum + mpu.getAngleX();
    angleYsum = angleYsum + mpu.getAngleY();
    count++;
    if (count >= maxCount) {
      angleX = angleXsum / maxCount;
      angleY = angleYsum / maxCount;
      angleX = constrain(angleX, minAngleX, maxAngleX);
      angleY = constrain(angleY, minAngleY, maxAngleY);
      angleXsum = 0;
      angleYsum = 0;
      count     = 0;
      printData();
    }
  }
}

void printData() {
  if (angleX != lastAngleX || angleY != lastAngleY) {
    Serial.print("X Sum: \t"); Serial.print(angleX);
    Serial.print("\tY Sum: "); Serial.println(angleY);
    lastAngleX = angleX;
    lastAngleY = angleY;
  }
}


  • The sketch makes use of a millis() function that is performed every "interval" ms to get rid of the delay() function.
  • Instead of a for-loop it counts the number of measurements and changes angleX and angleY if maxCount has been reached.
  • To restrict the range the constrain function is used.
  • The data are only printed if there was a change in angleX and/or angleY.
  • All relevant constants are declared as const to avoid "magic numbers".

Feel free to check it out on Wokwi: https://wokwi.com/projects/418886116138416129

Good luck and have fun!
ec2021

Thank you, I will have a go at that later

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.