# Any good algorithms for normallizing jitter?

I am reading a pressure altitude sensor and trying to create a vertical speed value. Pretty straight forward; read 2 altitude values over a known interval and calculate a vertical speed.
The problem I am having is my altitude as read from the sensor is jumping around a bit even when sitting static. I get readings up to a foot or more different on successive reads. When sampling every 250 mS or so that can equate to VS values up to 240 ft/min or more.
I have tried reading 50 times and calculating an average but that isnât working.
I was wondering if anyone knows of a method for reducing or calculating out this jitter? The sensor is a BME280 BTW.
Thanks

``````void loop() {
float nowElev = 0;
float t = bme.readTemperature();
for (int i = 0; i < 50; i++) {
float e = bme.readAltitude(SEALEVELPRESSURE_HPA) * 3.2808399;
nowElev = nowElev + e;
}
nowElev = nowElev / 50;

gNowTime = millis();
if (gNowTime - gPreviousTime >= gUpdateInterval) {
int elevChange = (nowElev - gPreviousElev) + .5;

Serial.println();
Serial.print(nowElev); Serial.print(" "); Serial.println(gPreviousElev);

int vertSpeed = elevChange * 60000 / gUpdateInterval;
gPreviousTime = gNowTime;
gPreviousElev = nowElev;

Serial.print("El = "); Serial.print(nowElev); Serial.print(" Ft AMSL  ");
Serial.print("VS = "); Serial.print(vertSpeed); Serial.println(" Ft/Min");
}
``````

That should work fine. What do you mean by âisnât workingâ?

Here is an example reading an analog pin. Iâm thinking it would be a simple solution to yours with a few tweaks.

``````# include <runningAvg.h>

runningAvg  smoother(5);   // Our smoother. You can change the number of datapoints it will act on.

// Standard setup stuff..
void setup(void) {

Serial.begin(9600);
}

// Standard loop stuff..
void loop(void) {

int aValue;
float ave;

aValue = analogRead(A0);               // Grab a value from the analog pin.
ave = smoother.addData(aValue);        // Pop this value into our smoother. (Running average object.) Out pops the average.
Serial.println();                      // From here down its just grabing info from the
Serial.print(F("Entered    : "));      // Smoother and displaying it on the serial monitor.
Serial.println(aValue);
Serial.print(F("Average   : "));
Serial.println(ave,4);
delay(1000);                           // Yes delay() sucks but this is just to slow down an example.
}
``````

You will need to grab LC_baseTools fro the library manager to compile this.

Good luck!

-jim lee

After reading 50 times and averaging it still jumps around enough to cause vertSpeed to bounce around.

Thanks. Iâll give that a try.

I wonder if you are averaging at the wrong frequency? Have you tried plotting the raw data?

-jim lee

Well, Doc Brown just basically did what I wanted to say, just simpler using a library. Anyway, if you didnât want to use any external code like that ( I usually donât since it really likes to break my stuff ), the implementation would be as follows:

• Read altitude every 25 milliseconds or so ( you will need to find a healthy balance. If you have too much delay, the value you read will have a lot of influence or the filter will be slow )
• Add that to an array, throwing out the oldest value ( by shifting the entire array)
• Take the average of that array, weighing the oldest value least ( again, thatâs based on trial and error if you donât know how to calculate it )

This will basically âfilterâ the high frequency jitter

EDIT: This is probably way harder than just using the library, but take some suggestions from it:

Read multiple values (you will have to figure out how many - more or longer delay will make the filter slower, fewer or shorter delay will decrease the effectiveness ), feed those into the rolling average ( I doubt 5 will be enough, but youâll figure that one out ) and take the result every x-th cycle. Reading the result every cycle will just result in less amplitude on the jitter

1 Like

I really like that idea of weighting the later values more. I now wonder if I should add that into my stuffâŚ

-jim lee

Isnât that standard practice?

I donnoâ. Its been too many years since school. But it makes a LOT of sense.

-jim lee

Or you can run it through a low-pass filter:

``````  #define SMOOTHING_FACTOR 0.8  //between 0 (no smoothing) and 0.99 (maximum smoothing)

static float smoothedValue = 0;
float unsmoothedValue = 0;

unsmoothedValue = GetTheCurrentDataValue();

smoothedValue = (SMOOTHING_FACTOR * smoothedValue) + ((1 - SMOOTHING_FACTOR) * unsmoothedValue);  //low pass filter
``````

I think this is easier than messing about with arrays and calculating averages. It is mathematically rigorous and widely used.

2 Likes

This appears to take care of both weighing and past value storage in a very elegant way. Itâs always based on a logarithmic curve, but I like the approach. Gonna be using this

1 Like

I made a typo with my variable names - corrected.

I have had good success with the following:

1. Read 20 values into an array
2. Sort the values from high to lowest
3. Discard the 3 highest and 3 lowest (will be the 3+3 outer elements of the array)
4. Average the remaining values (will be the 14 inner elements of the array)

You can adjust the value of 20 and 3 according to the amount of jitter (noise) that you are getting. This is rather easy to implement and it surprisingly effective.

Good Luck!
dan

1 Like

So I have discovered a bit about this sensor. Regardless of how often the code fetches the data, the sensor only updates the data about every 100 mS. I was working under the assumption that it was working in real time.
What I have done is used Steve Thackeryâs smoothing algorithm on the output vertical speed value which seems to give me the best results.
I will have to go for a drive and see what real changing data does but in the interim, thanks for everyoneâs input.

That explains why your attempt to average 50 measurements âdidnât workâ. You were probably averaging only 1 measurement, 50 times.

1 Like

and how is look modified code ?

``````#define SMOOTHING_FACTOR 0.95           //between 0 (no smoothing) and 0.99 (maximum smoothing)

float unsmoothedValue = 0;
static float smoothedValue = 0;

void setup() {
}

void loop() {

gNowTime = millis();
float t = bme.readTemperature();
float nowElev = bme.readAltitude(SEALEVELPRESSURE_HPA) * 3.2808399;

if (gNowTime - gPreviousTime > gUpdateInterval) {
gPreviousTime = gNowTime;

float elevChange = nowElev - gPreviousElev;

float vertSpeed = elevChange * 60000 / gUpdateInterval;
unsmoothedValue = vertSpeed;
smoothedValue = (SMOOTHING_FACTOR * smoothedValue) + ((1 - SMOOTHING_FACTOR) * unsmoothedValue);  //low pass filter
int vSpeed = smoothedValue + .5;

Serial.print("gPreviousElev = "); Serial.print(gPreviousElev); Serial.print(" Ft AMSL  ");
Serial.print("  nowElev = "); Serial.print(nowElev); Serial.print(" Ft AMSL  ");
Serial.print("  elevChange = "); Serial.print(elevChange); Serial.print(" Ft");
Serial.print("  VS = "); Serial.print(vertSpeed); Serial.print(" Ft/Min");
Serial.print("  Smoothed = "); Serial.print(smoothedValue);
Serial.print("  vSpeed = "); Serial.println(vSpeed);
Serial.println();

gPreviousElev = nowElev;
}

}
``````

Thanks