Arduino Altimeter - BMP280 inBuilt Noise Filtering Settings

The Rocketry Forum

Help Support The Rocketry Forum:

This site may earn a commission from merchant affiliate links, including eBay, Amazon, and others.

Nikhil Mishra

Member
Joined
Mar 16, 2019
Messages
11
Reaction score
0
Hello!

I am building an Arduino Altimeter with BMP280. Fortunately for BMP280, it has an in Built IIR Filter. But the problem is am not sure how to change the settings for rocket specific application.
bmp280-use-cases.jpg

The Parameters are:
  • Oversampling Setting
  • IIR Filter (Ratio)
  • set standby time
Requirements for Altimeter:
  • Sensitive enough for Apogge Detection
  • what else?
Code

Code:
    bmp280.setPressureOversampleRatio(2);
    bmp280.setTemperatureOversampleRatio(1);
    bmp280.setFilterRatio(4);
    bmp280.setStandby(0);

This article was very helpful in decoding the datasheet. There are some examples too.

The article also states that IIR filter makes BMP280 less sensitive to changes, which obviously is good for apogee detection right? Please clarify
yQiihWQ.png

Lastly,
I am aware Kalman Filter is a better alternative. But I wanted to keep my code light. So are there any appropriate alternatives (Filters) for BMP280?

I am new to building Model Rockets, it's challenging. But that's what I love about it!
Thanks a lot for helping! :D

Code:
#include <Wire.h>
#include "i2c.h"

#include "i2c_BMP280.h"
BMP280 bmp280;

void setup()
{
    Serial.begin(115200);

    Serial.print("Probe BMP280: ");
    if (bmp280.initialize()) Serial.println("Sensor found");
    else
    {
        Serial.println("Sensor missing");
        while (1) {}
    }
    
    //Calibration Settings
    bmp280.setPressureOversampleRatio(2);
    bmp280.setTemperatureOversampleRatio(1);
    bmp280.setFilterRatio(4);
    bmp280.setStandby(0);


    // onetime-measure:
    bmp280.setEnabled(0);
    bmp280.triggerMeasurement();
}

void loop()
{
    bmp280.awaitMeasurement();

    float temperature;
    bmp280.getTemperature(temperature);

    float pascal;
    bmp280.getPressure(pascal);

    static float meters, metersold;
    bmp280.getAltitude(meters);
    metersold = (metersold * 10 + meters)/11;

    bmp280.triggerMeasurement();

    Serial.print(" HeightPT1: ");
    Serial.print(metersold);
    Serial.print(" m; Height: ");
    Serial.print(meters);
    Serial.print(" Pressure: ");
    Serial.print(pascal);
    Serial.print(" Pa; T: ");
    Serial.print(temperature);
    Serial.println(" C");
}
 
Hello!

I am building an Arduino Altimeter with BMP280. Fortunately for BMP280, it has an in Built IIR Filter.

The IIR filter is very handy, because pressure measurement on a rocket is extremely noisy due to turbulance around the rocket are various parts of the flight. The IIR filter can help smooth this out.

The top row of your table looks like it should be a good starting point, possibly with a little less oversampling. You don't actually need the "Ultra High Resolution". I would think about dropping the osrs_p to the 8 to 12 range, but just as stated there maybe a good starting point.

I would say breadboard it and set up a vacuum chamber to test it. In fact initial testing you could probably do with the BMP280 just placed in the hose or coupling of a vacuum cleaner. That is the method I started with to test altimeters. From there I just moved to a small cardboard box and a vacuum cleaner.
 
I've been working on a similar system with the BMP280/BMP388 and a Kalman filter over the last year or so. The sensors are excellent. I would recommend the BMP388 if you can but the 280 will certainly work as well.

One of the harder problems to solve is filtering out spikes from the ejection events. The problem with an IIR filter is the response from an impulse signal (like the ejection) is, well, infinite. When you get a reduced amplitude spike that lasts longer than it should, it is much harder to detect and filter out. A narrow, high amplitude spike is actually easier to deal with. I've gotten the best results with the internal filter turned off. I'm running the 388 at 8x/1x at 50Hz.

For the Kalman filter, if you use a constant time step and don't change your model or noise estimates, the Kalman gains will quickly converge to constant values. The whole thing can be implemented in about 6 lines of code if you pre-calculate the gains. You run the prediction step to advance the model, take a measurement and then correct the state with the constant gains. If you are recording data, you can tune and experiment on something that can run the full version of the filter.

Good luck!
 
The top row of your table looks like it should be a good starting point, possibly with a little less oversampling. You don't actually need the "Ultra High Resolution". I would think about dropping the osrs_p to the 8 to 12 range, but just as stated there maybe a good starting point.

I did try with different osrs_p. Here are the results.
The sensor is stationary.

With Different osrs_p settings (fig 1) y-axis (height in m)
gQJgrbo.png


With Different IIR settings (fig 2)

zMf6VJS.jpg


In fig(1), it's clear that oversampling of 10 or more is helpful. Can you make any other analysis from this?
In Fig(2), IIR (8) is doing some aggressive filtering. But it's still not perfect. Might need to use a filter.

Question: What should be the accuracy required by an altimeter in a Low Powered Model Rocket, that I should aim for?

Also, any idea what this does?

Code:
    bmp280.setStandby(0);

I would say breadboard it and set up a vacuum chamber to test it. In fact initial testing you could probably do with the BMP280 just placed in the hose or coupling of a vacuum cleaner. That is the method I started with to test altimeters. From there I just moved to a small cardboard box and a vacuum cleaner.

Never thought of this. This is a really good idea. Will try it and come back with comments.

Many Thanks!
 
I've been working on a similar system with the BMP280/BMP388 and a Kalman filter over the last year or so. The sensors are excellent. I would recommend the BMP388 if you can but the 280 will certainly work as well.

One of the harder problems to solve is filtering out spikes from the ejection events. The problem with an IIR filter is the response from an impulse signal (like the ejection) is, well, infinite. When you get a reduced amplitude spike that lasts longer than it should, it is much harder to detect and filter out. A narrow, high amplitude spike is actually easier to deal with. I've gotten the best results with the internal filter turned off. I'm running the 388 at 8x/1x at 50Hz.

For the Kalman filter, if you use a constant time step and don't change your model or noise estimates, the Kalman gains will quickly converge to constant values. The whole thing can be implemented in about 6 lines of code if you pre-calculate the gains. You run the prediction step to advance the model, take a measurement and then correct the state with the constant gains. If you are recording data, you can tune and experiment on something that can run the full version of the filter.

Good luck!

I've gotten the best results with the internal filter turned off

This consistent with what other people have said. But your explanation was the one which made sense.


I'm running the 388 at 8x/1x at 50Hz.
I am not aware of this setting.

If you are intending on using altitude as apogee detection it can be risky since this method is inherently feed-forward. Traditionally an accelerometer is used to detect apogee by reading net 0 accel after initial accel (launch) is detected. You can couple altitude into accel as a feed-back system for safety but its time consuming and often not necessary. You will have to clean up the signal (1D low pass filter) or a kalman filter is a good idea. The math for a kalman filter can be intense unless you break down the system as SISO (single input, single output). Doing it like this makes all the matrices 1X1 i.e...a single data point.

Reddit

This changes how I was thinking of the problem. I was hoping to calculate the altitude for apogee detection. But bgr514 is suggesting to use net accel as a condition to actuate pyro channels.

For the Kalman filter,

Kalman filter is neat. I am just worried about the memory space it's going to use. I need to do TVC and Attitude measurement in on arduino NANO.

Do you think it's possible to do all of this at base station (computer) then transmit the data via radio to rocket?
 
bmp280.setStandby(0);

This is used to set the measurement standby delay in normal mode. Setting to zero means no delay. Measuring the temp actually runs current through the thermistor, which can heat it slightly and cause an offset reading. Very minor effect most of the time, but could be more pronounced at high altitude where there is less air conductance. By high latitude, I am talking about 35K MSL and above. Leaving it at 0 should be fine, but it is another parameter to play with if you want. Increment by 10 and see if you can see any change in temperature response. If you have a different type of thermometer to compare to it would help.

As for accuracy, both pressure and temperature the BMP280 is really good. The pressure accuracy, when temperature correct, falls to below the resolution. It reads down to 1nPa, so the reading accuracy is going to be +/- .16hPa, roughly +/- 1 meter at sea level. Temp is +/- .5°C. This is an amazingly accurate sensor, especially for the price.

Overall accuracy of the altimeter depends on several factors and is not that easy to measure. Unless you have access to pressure standards, it is better to measure correlation with another altimeter. Any of the commercial recording altimeters will work, if you have one. I tend to check two or three at a time, and generally get somewhere between 2% an 5% correlation. That is the high and low will be within 2 to 5 percent of each other for apogee reading. Obviously a quick function check and not a serious calibration with NIST traceability.
 
Last edited:
I wouldn’t be too concerned with absolute accuracy. The NAR requirement for altimeters is 2m or 1%.

https://www.nar.org/contest-flying/...ting-code/altitude-competition/altitude-data/

The 8x/1x I mentioned is 8x pressure over sampling and 1x temp. I am running in forced mode and reading every 20ms, 50Hz.

My apogee detection is based on velocity. Positive velocity is going up and negative velocity is going down. The zero crossing is apogee.

I would highly recommend flying whatever you have soon. Even if you are just logging pressure, you will learn a lot from real data.
 
Do you think it's possible to do all of this at base station (computer) then transmit the data via radio to rocket?

Short answer: no

It is "possible", but relying on an air to ground and back datalink for deployment is just too risky. Even simple telecommand systems for deployment tend to be very finicky. You should keep the unit autonomous.
Then you might start looking at telemetry and see what kind of quality you get. You will probably find that getting a real time data stream that allows for calcs on the ground will not be practical.
 
Youre overcomplicating the task. Low pass filter the pressure, when the pressure increases over the noise level apogee has happened.

Fancy filters are one way of many to deal with each effects, a necessary function but not for apogee detection.

As mentioned earlier, a kalman filter is the most elegant way to do this and requires minimal code space. 6 constants and 3 lines of code. Plus you get estimates of v and a for free.
 
Many thanks for the reply!
you will learn a lot from real data.
Speaking of real data. Where can I get some data (open source) just for testing?

My apogee detection is based on velocity
  • Pressure Change
  • Net Accel (zero)
  • Velocity change (zero)
Am experimenting which is the best. Let's see.

I am running in forced mode
Any specific reason?
flying whatever you have soon
Soon, I just wanna get to a fine level. Your help is much appreciated! Thanks!
 
it is better to measure correlation with another altimeter
This is what am missing.. Real sensors to compare my output with.

You will probably find that getting a real time data stream that allows for calcs on the ground will not be practical.
Now that you are saying it makes much more sense. I actually found someone doing this on youtube (can't find the video, sorry.

You should keep the unit autonomous.
That's my plan! ;)

Many thanks for the reply! You have directed me in the right direction!
 
Speaking of real data. Where can I get some data (open source) just for testing?

Take a look at our flight log at https://flightsketch.com/flights

There is a download data link on each flight page.

Forced mode will ensure you are sampling at the desired rate and not the fallout of the measurement time and BMP280 delay.
 
Be careful if you down the path of adding telemetry. Both the BMP280 and BMP388 are extremely RF sensitive. I use low power LoRa modules on 433 MHz and they make the barometric readings unusable. I’ve switched to the MPL

Edit: sorry for the double post. Smart phone, dumb user
 
Last edited:
Be careful if you down the path of adding telemetry. Both the BMP280 and BMP388 are extremely RF sensitive. I use low power LoRa modules on 433 MHz and they make the barometric readings unusable. I’ve switched to the MPL
TIL, Thanks for the info! Noted.
 
Also,
what are your thoughts on the switch to STM32F410 from Arduino Nano, for this particular project(Altimeter+TVC+Pryo)? With existing sensors, because am not sure if all(MPU6050 + BMP280 + SD MODULE) of them are supported with STM32

Switching because I am about to run out of programming space. So I am preparing myself to make the switch.

Sorry, this is off-topic, but it's important.
 
The whole thing can be implemented in about 6 lines of code if you pre-calculate the gains

Have been researching a bit, did find some resources regarding Kalman FIlters. Can you link some other resources/opensource code for Kalman filters, because I have been having a hard time doing it.

Thanks again! :D
 

Attachments

  • digital-detection-of-rocket-apogee-1.1.pdf
    545 KB · Views: 220
https://github.com/barnstar/Open-Altimeter/tree/master/SimpleAltimeter

See filters.cpp

You absolutely need to filter your pressure readings. Spikes due to ejection pressure and other transient changes that have nothing to do with your actual altitude can ruin your day. Adjust the gains to your liking.

The stock sensor libs can suck up a lot of space. Modify them to remove any code you’re not using. Even then, it will take some effort to get all of that into an Arduino Nano. You eventually run into stability problems.

I use ESP8266 or ESP32 modules for anything involving logging or telemetry. They have enough internal flash for decent logging as well as WiFi (and are comparable in size to a Nano. All the usual SPI and i2c libs usually work - as will most of your Arduino code. The ComplexAlitmeter project in that same repo liked above gives you an idea of how nuts you can get with one of those.
 
I use ESP8266 or ESP32 modules for anything involving logging or telemetry. They have enough internal flash for decent logging as well as WiFi (and are comparable in size to a Nano.

Arduino Nano will have to be replaced. I just want the change to be smooth. Because it has taken time to develop this code.

NodeMCU doubts::confused:
  • I guess I have to use level shifters for 5v sensors
  • Do they work well with MOSFETS
  • Does the flash memory decrease in size when one uses Arduino IDE (similar to STM32)
  • Spiffs File System
  • Less no of Pin Outs.
  • Consistency
Also, what are the disadvantages? (NodeMCU) apart from the obvious ones, because I might add more stuff.

You eventually run into stability problems.
Can you please explain briefly (or link).

Adjust the gains to your liking.
From Open-Altimeter:

Code:
void KalmanFilter::reset(double startingValue) {
   configure(1, 1, 0.001);
   this->last_estimate = startingValue;
   for (int i = 0; i < 4; i++) {
    step(startingValue);
  }
}

- configure(1, 1, 0.001);

How do I calculate this?
I did, however, calculate these gain values. (which are 3x3 mat)

Source - Digital Detection of Rocket Apogee
FauIZIg.png


--------------------------------------------------------------------------------------------------------------------------------
Using SimpleKalmanFilter
This is my output, as you can see, the filter doesn't react quickly to rapid changes. This is not good.
AUZehZK.png


Million thanks for the kind help! :)
The open source nature of the internet is so welcoming! ;)
 
My personal favorites are references 2 and 3 in that document. Both available to NAR members at the NAR web site. Harder to find elsewhere since Earthlink terminated their web service but the Wayback Machine remembers all.
 
This is my output, as you can see, the filter doesn't react quickly to rapid changes. This is not good.

That's maybe because your sensor input is not consistent with the system model used to derive your filter.

The way to test your filter is to apply to actual pressure data recorded in a flight OR create a simulation of a flight and the ideal sensor response, overlay random noise to that signal and see how the filter responds.
 
Am sorry, but I don't follow.

The system model is configured with gain values. Maybe I need to figure them out?

The Kalman filter has an underlying physical model of the process built into it. In this application it would be Newton's laws of motion:
s = So + vt + 0.5at^2
v = Vo + at
a = constant (or other custom model for this you may choose).

If your sensor signal implies a motion that is impossible or otherwise seriously deviates from the underlying physics defined by your model, it will filter that response out. In your example you have a step change up and down in altitude and are complaining your filter doesn't follow that. Well that motion cannot happen in a ballistic trajectory.
 
In case it helps, I can pitch in some advice:

1. Never, ever use floating point numbers in your code (just use integers for everything)
2. Disable internal chip filters, and do it yourself in software (easier to understand and tweak, and allows more nuanced control over filtering)
3. Never use an accelerometer for altitude, but they are super handy to identify events (launch, thrust, burnout, ejection, landing)
4. Save as much math as possible for after the end of flight (increase your sleep time, avoid unnecessary intermediate math during data collection)

The data which comes from modern sensors arrives as an integer. Keep it in that form always. There are tricks to doing this, and I'm happy to share them.

You'll notice that Jolly Logic products can display measurements in tenths (e.g. Apogee to Eject 1.7 seconds) or hundredths (e.g. Burn Time 1.45 seconds). However, there are no floating point variables ever in any Jolly Logic software.

The reason? Floating point takes more memory for each number, uses a fair chunk of program memory for floating point libraries, and wastes a ton of cycles on each calculation—even simple divides and multiplies. And is no more accurate.

You can stick with integer storage and calculations and still have all of the precision that you need. Just decide how much precision you need for each number, then use an integer to represent it.

For instance, let's say your program has a time tick registered every 0.01 seconds, and you want to measure pressure every 0.1 seconds. For timekeeping, you would just store the time as ticks, and you would measure pressure every 10 ticks. In this case, ticks = 1054 represents 10.54 seconds. Timekeeping with 0.01 seconds precision becomes easy to do, just keep a count of ticks. If apogee is detected at 5.34 seconds, just store 534 as Apogee Time.

When it comes time to display the numbers (if you have a display, or if you are creating a file to store them), you just use a routine to produce a string with the decimal point in the proper place.

Example: Printing 1054 as 10.54
time = 1054
WholePart = time / 100 = 10 [Note: integer math truncates, not rounds]
DecimalPart = time - WholePart*100 = 1054 - 1000 = 54

[Then use itoa to get a string for each part and and strcat them together with a '.' character between them. You now have the string "
10.54" that you can display or save to a file.]

The only hazard in doing this is to watch out for overflows. Make sure your integers have enough space for the representations you choose and the math you do on them (especially multiplies). And if you have a number (like time) that will always be positive, you can use an unsigned integer to double the highest value you can store.

A clever person can create a routine which converts an integer pressure value to an integer altitude (representing tenths of feet if that accuracy is required) using the Standard Atmospheric model without ever using floating point numbers, calculations or exponents, and is accurate to within one foot up to 29,500 feet. Such a routine can be blazing fast and take very little resources.
 
i don't have time to read through this whole thread but here's something i noticed the other day. The Bosch pressure sensors like the 280 and 388 have an operation range of 300 hpa to 1250 hpa.
https://www.bosch-sensortec.com/pro...pressure-sensors/pressure-sensors-bmp388.html

300hpa is the pressure at about 30k feet. If you're planning on producing an altimeter that works for high altitude flights the Bosch sensors aren't going to work.

The AltusMetrum EasyMega uses a MS6507 pressure sensor which has an operational range 10mbar to 1200mbar
https://altusmetrum.org/EasyMega/
https://www.digikey.com/en/product-highlight/m/measurement-specialties/ms5607-pressure-sensor
 
i don't have time to read through this whole thread but here's something i noticed the other day. The Bosch pressure sensors like the 280 and 388 have an operation range of 300 hpa to 1250 hpa.
https://www.bosch-sensortec.com/pro...pressure-sensors/pressure-sensors-bmp388.html

300hpa is the pressure at about 30k feet. If you're planning on producing an altimeter that works for high altitude flights the Bosch sensors aren't going to work.

The AltusMetrum EasyMega uses a MS6507 pressure sensor which has an operational range 10mbar to 1200mbar

Kind of.

It's important to realize that the Bosch range is more accurately described as its certified range, the range over which they specify accuracy. Bosch tends to quote this range.

While the Measurement Specialties' declared accuracy uses the same roughly 300-1100 mbar range, they tend to quote a wider, less well-characterized range in their summary of the operating range.

Also be aware that the atmosphere acts much less civilized out of the troposphere above 11K meters. You actually need to switch pressure conversion equations as you ascend.
 
1. Never, ever use floating point numbers in your code (just use integers for everything)

Guilty... I can remember back in the day with extensive hand optimization to get code to run in 256 bytes of ram and an 8 bit core. Now with 32 bit processors 100x+ ram and hardware floating point units I’ve started using floats. It makes the code much easier to read and saves (me) a lot of time developing. It also makes filters from multiple data sources much easier to integrate with “real” units. Most of that is pretty trivial if you work through it but the hardware is only going to keep getting better. It will be hard to justify at all when more advanced instruction sets continue to get passed down.


300hpa is the pressure at about 30k feet. If you're planning on producing an altimeter that works for high altitude flights the Bosch sensors aren't going to work.

As John noted, that’s for rated accuracy. They will continue to report data but above 30k you are better off with other sensor types. Tripoli even requires GPS for records over 30k.
 
Back
Top