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");
}
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.
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
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
Discard the 3 highest and 3 lowest (will be the 3+3 outer elements of the array)
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.
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.