MS5611 pressure problem

Hello everyone,

I am developing an altimeter for hiking. I have this code to calculate the altitude:

#include <Wire.h>
#include <MS561101BA.h>


#define MOVAVG_SIZE 32

MS561101BA baro = MS561101BA();

float movavg_buff[MOVAVG_SIZE];
int movavg_i=0;

const float sea_press = 1013.25;
float press, temperature;

void setup() {
  Wire.begin();
  Serial.begin(9600);
  delay(1000);

  //On connecte le CSB à la masse
  baro.init(MS561101BA_ADDR_CSB_LOW); 
  delay(100);
  
  // on remplit le buffer avant de commencer le loop
  for(int i=0; i<MOVAVG_SIZE; i++) {
    movavg_buff[i] = baro.getPressure(MS561101BA_OSR_4096);
  }
}

void loop() {
  Serial.print(" temp: ");
  temperature = baro.getTemperature(MS561101BA_OSR_4096);
  Serial.print(" degC pression: ");
  
  press = baro.getPressure(MS561101BA_OSR_4096);
  pushAvg(press);
  press = getAvg(movavg_buff, MOVAVG_SIZE);
  Serial.print(press);
  Serial.print(" mbar altitude: ");
  Serial.print(getAltitude(press, temperature));
  Serial.println(" m");
}

float getAltitude(float press, float temp) {
  //return (1.0f - pow(press/101325.0f, 0.190295f)) * 4433000.0f;
  return ((pow((sea_press / press), 1/5.257) - 1.0) * (temp + 273.15)) / 0.0065;
}

void pushAvg(float val) {
  movavg_buff[movavg_i] = val;
  movavg_i = (movavg_i + 1) % MOVAVG_SIZE;
}

float getAvg(float * buff, int size) {
  float sum = 0.0;
  for(int i=0; i<size; i++) {
    sum += buff[i];
  }
  return sum / size;
}

My problem is that my first values ​​are absurd and I wish to remove them because I also take the max and min altitude. In my opinion it's a buffer problem but I do not know how to fix it. Thank you :slight_smile:

Note that it’s NOT a 5V sensor, so depending on your board you need to ensure you don’t abuse the hardware... which sensor do you have?

When you say the first values are absurd - how many of those and for how long? Do things work o after a while?

The MS5611-01BA Has a pretty high resolution and is optimized for altimeters and variometers with an altitude resolution of 10 cm andmhas factory calibrated coefficients for the built in ADC.

The code you have fills in a buffer (super rapidely) in the setup - so very likely with very similar values - and then the loop() is using that buffer to calculate an averaged altitude using a circular buffer technique (overwrite the oldest value in the buffer and calculate the average of what remains there, so at the speed of your loop, the average of the 32 read from the last few milliseconds (takes less than 10ms for a read))

Hello,
Thank you for your reply.
I use an arduino uno for realizing my tests and my VCC is equal to 3.3V. I bought this sensor:

There are approximately 50 absurd values in a second in the opening of the serial port. The sensor returns a roughly correct value of my altitude but this value drifts over time. The amount can range from 2m to a minute.

if this is transient then maybe the library does not handle properly the values returned by the chip at boot time (no error management)...

try adding a delay(2000); in the set-up to wait for 2 seconds before filling in your buffer and see what it does...

also print the values read in the setup to fill in your buffer and see if they make sense

Thank you for your reply.
First of all, the values ​​given to me at the opening of the serial monitor are below. There is about two seconds before I get a valid altitude at about 157m.

temp: 0.00 degC pres: 0.00 mbar altitude: inf m
 temp: 0.00 degC pres: 0.00 mbar altitude: inf m
 temp: 0.00 degC pres: 0.00 mbar altitude: inf m
 temp: 0.00 degC pres: 31.10 mbar altitude: 39502.00 m
 temp: 24.62 degC pres: 62.20 mbar altitude: 32083.99 m
 temp: 24.62 degC pres: 93.29 mbar altitude: 26302.11 m
 temp: 24.61 degC pres: 124.39 mbar altitude: 22461.05 m
 temp: 24.62 degC pres: 155.49 mbar altitude: 19624.43 m
 temp: 24.63 degC pres: 186.59 mbar altitude: 17394.47 m
 temp: 24.63 degC pres: 217.69 mbar altitude: 15567.98 m
 temp: 24.62 degC pres: 248.79 mbar altitude: 14028.02 m
 temp: 24.63 degC pres: 279.88 mbar altitude: 12702.63 m
 temp: 24.63 degC pres: 310.98 mbar altitude: 11541.52 m
 temp: 24.64 degC pres: 342.08 mbar altitude: 10511.38 m
 temp: 24.64 degC pres: 373.18 mbar altitude: 9586.79 m
 temp: 24.62 degC pres: 404.28 mbar altitude: 8749.04 m
 temp: 24.64 degC pres: 435.38 mbar altitude: 7985.83 m
 temp: 24.64 degC pres: 466.48 mbar altitude: 7284.35 m
 temp: 24.64 degC pres: 497.58 mbar altitude: 6636.46 m
 temp: 24.63 degC pres: 528.68 mbar altitude: 6034.87 m
 temp: 24.63 degC pres: 559.78 mbar altitude: 5474.18 m
 temp: 24.64 degC pres: 590.88 mbar altitude: 4949.56 m
 temp: 24.65 degC pres: 621.98 mbar altitude: 4456.79 m
 temp: 24.65 degC pres: 653.07 mbar altitude: 3992.37 m
 temp: 24.63 degC pres: 684.17 mbar altitude: 3553.30 m
 temp: 24.65 degC pres: 715.27 mbar altitude: 3137.84 m
 temp: 24.65 degC pres: 746.37 mbar altitude: 2743.11 m
 temp: 24.65 degC pres: 777.47 mbar altitude: 2367.49 m
 temp: 24.64 degC pres: 808.57 mbar altitude: 2009.29 m
 temp: 24.63 degC pres: 839.67 mbar altitude: 1667.13 m
 temp: 24.65 degC pres: 870.77 mbar altitude: 1339.88 m
 temp: 24.65 degC pres: 901.87 mbar altitude: 1026.15 m
 temp: 24.65 degC pres: 932.97 mbar altitude: 725.05 m
 temp: 24.64 degC pres: 964.07 mbar altitude: 435.63 m
 temp: 24.65 degC pres: 995.17 mbar altitude: 157.15 m
 temp: 24.65 degC pres: 995.18 mbar altitude: 157.14 m
 temp: 24.65 degC pres: 995.18 mbar altitude: 157.11 m
 temp: 24.65 degC pres: 995.18 mbar altitude: 157.09 m
 temp: 24.64 degC pres: 995.18 mbar altitude: 157.07 m
 temp: 24.65 degC pres: 995.18 mbar altitude: 157.05 m
 temp: 24.65 degC pres: 995.19 mbar altitude: 157.04 m
 temp: 24.65 degC pres: 995.19 mbar altitude: 157.02 m
 temp: 24.64 degC pres: 995.19 mbar altitude: 157.01 m
 temp: 24.64 degC pres: 995.19 mbar altitude: 157.00 m

After that I tried to wait two seconds before filling the buffer and then displayed the values ​​in the serial monitor like below :

delay(2000);  
  // populate movavg_buff before starting loop
  for(int i=0; i<MOVAVG_SIZE; i++) {
    movavg_buff[i] = baro.getPressure(MS561101BA_OSR_4096);
    Serial.println(movavg_buff[i]);
  }
The values in my buffer : 
0.00
0.00
0.00
0.00
0.00
0.00
0.00
0.00
0.00
0.00
0.00
0.00
0.00
0.00
0.00
994.95
994.95
994.95
4356.34
995.03
995.12
995.12
995.12
4356.69
995.06
995.13
995.13
995.13
4356.99
995.07
995.13
995.13

I meant what do you see if you run something like this: (put serial monitor at 115200 bauds)

#include <Wire.h>
#include <MS561101BA.h>

MS561101BA baro = MS561101BA();

const float sea_press = 1013.25;
float press, temperature;

void setup() {
  Wire.begin();
  Serial.begin(115200); // ATTENTION SERIAL MONITEUR A 115200 BAUDS
  baro.init(MS561101BA_ADDR_CSB_LOW);
  delay(2000);
}

void loop() {

  temperature = baro.getTemperature(MS561101BA_OSR_4096);
  press = baro.getPressure(MS561101BA_OSR_4096);
  Serial.print(F("pression: "));
  Serial.print(press);
  Serial.print(F(" mbar altitude: "));
  Serial.print(getAltitude(press, temperature));
  Serial.println(F(" m"));
  delay(100);
}

float getAltitude(float press, float temp) {
  return ((pow((sea_press / press), 1.0 / 5.257) - 1.0) * (temp + 273.15)) / 0.0065;
}

(untested, typed here)

note that there are other libraries you could explore, may be the one you have is not great... for example found that one that one

Hello JML,
Thank you for your help. I tried with 115200 bauds and with your program. I get the values below.

pression: 0.00 mbar altitude: inf m
pression: 0.00 mbar altitude: inf m
pression: 0.00 mbar altitude: inf m
pression: 989.12 mbar altitude: 211.16 m
pression: 989.16 mbar altitude: 210.82 m
pression: 0.00 mbar altitude: inf m
pression: 989.15 mbar altitude: 210.91 m
pression: 989.21 mbar altitude: 210.40 m
pression: 0.00 mbar altitude: inf m
pression: 989.20 mbar altitude: 210.49 m
pression: 989.21 mbar altitude: 210.40 m
pression: 0.00 mbar altitude: inf m
pression: 989.18 mbar altitude: 210.67 m
pression: 989.19 mbar altitude: 210.58 m

I tried to use the libraries in your link. I make this program and finally my values are more constant :

#include <MS5611.h>

MS5611 baro;
int32_t pressure;
const float sea_press = 1013.25;
float temperature;

void setup() {
  // Start barometer
  baro = MS5611();
  baro.begin();
  // Start serial (UART)
  Serial.begin(9600);
  delay(2);
}

void loop() {
  // Read pressure (mbar)
  pressure = (baro.getPressure())*0.01;
  // Read temperature (°C)
  temperature = (baro.getTemperature())*0.01;

  //Serial.println(pressure);
  //Serial.println(temperature);
  Serial.println(getAltitude(pressure,temperature));
}
float getAltitude(float press, float temp) {
  //return (1.0f - pow(press/101325.0f, 0.190295f)) * 4433000.0f;
  return ((pow((sea_press / press), 1/5.257) - 1.0) * (temp + 273.15)) / 0.0065;
}
MY VALUES :
221.51
221.52
221.52
221.53
221.53
221.53
221.54
221.55
221.55
221.55
221.55
221.56
221.56
221.57
221.58
221.58
221.58
221.58
221.59
221.58
221.59
221.59
221.60
221.59

I will try to calculate the averaged altitude with the circular buffer technique.
I come back to you to give you my results. Thanks again!

So seems the first library fails from time to time which means it returns "crap" (0) into your circular buffer and averaging crap with good data gives you crap :slight_smile:

sounds like the second library is more robust

averaging crap with good data gives you crap :slight_smile:

Ahah exactly :slight_smile:
I tried the code I posted previously (with the good library) at 115200 and I get the values below. It drifts a little in time. I post my first values when i open the serial monitor.

230.65
230.66
230.67
230.68
230.67
230.67
230.68
230.68
230.68
230.69
230.70
230.70
230.71
230.71
230.71
230.71
230.71
230.73
230.74
230.74
230.74
230.75
230.75
230.76
230.76
230.77
230.77
230.77
230.78
230.78
230.78
230.77
230.76
230.76
230.77
230.76
230.77
230.77
230.77

So I did with the circular buffer technical still 115200 and I get these values. Values are more stable and do not drift over time. I tried to let the code run for a few minutes and I get the same pressure so it's great. By cons I have again this problem of the first absurd values that appears and i don't know how remove these and where do it come from...

-26587.86
-26464.59
-26334.36
-26198.54
-26057.53
-25909.14
-25753.65
-25590.37
-25418.49
-25237.96
-25045.41
-24842.06
-24626.60
-24395.86
-24148.63
-23881.07
-23593.63
-23282.02
-22940.39
-22563.92
-22145.02
-21677.09
-21143.56
-20527.66
-19802.48
-18925.69
-17827.16
-16375.15
-14277.92
-10677.14
230.92
230.91
230.90
230.90
230.91
230.91
230.91
230.92
230.92
230.92
...

Hum - negative values might come from variable overflow - are you using float or int ?

Are you filling in the whole buffer initially ?

First of all, I understand better why I obtained a constant result. I took int32_t pressure which gives me a pressure in mbar with no decimal point. I put all int32_t and pressure in Pascal and I get the result below.
I no longer have the problem of bad values ​​at launch :). On the other hand it is said in the datasheet that the sensor has an accuracy of + -10cm and I have the impression that I have slightly larger variations. Does it come from my code or sensor limits? thank you for everything

#include <MS5611.h>

#define MOVAVG_SIZE 32

MS5611 baro;
int32_t pressure; // in Pascal
const float sea_press = 101325; // in Pascal
int32_t temperature;
float movavg_buff[MOVAVG_SIZE];
int movavg_i=0;


void setup() {
  // Start barometer
  baro = MS5611();
  baro.begin();
//   populate movavg_buff before starting loop
  for(int i=0; i<MOVAVG_SIZE; i++) {
    movavg_buff[i] = baro.getPressure();
  }
  // Start serial (UART)
  Serial.begin(115200);
  delay(2);
}

void loop() {
  // Read pressure (mbar)
  pressure = (baro.getPressure());
  pushAvg(pressure);
  pressure=getAvg(movavg_buff, MOVAVG_SIZE);
  // Read temperature (°C)
  temperature = (baro.getTemperature());

  //Serial.println(pressure);
  //Serial.println(temperature);
  Serial.println(getAltitude(pressure,temperature));
}
float getAltitude(float press, float temp) {
  //return (1.0f - pow(press/101325.0f, 0.190295f)) * 4433000.0f;
  return ((pow((sea_press / press), 1/5.257) - 1.0) * (temp*0.01 + 273.15)) / 0.0065;
}

void pushAvg(float val) {
  movavg_buff[movavg_i] = val;
  movavg_i = (movavg_i + 1) % MOVAVG_SIZE;
}

float getAvg(float * buff, int size) {
  float sum = 0.0;
  for(int i=0; i<size; i++) {
    sum += buff[i];
  }
  return sum / size;
}
MY VALUES : 
164.38
164.38
164.38
164.39
164.39
164.39
164.39
164.39
164.39
164.39
164.39
164.31
164.31
164.31
164.31
164.30
164.30
164.30
164.21
164.21
164.21
164.21
164.21
164.21
164.21
164.21
164.21
164.13
164.13
164.04
164.04
163.96
163.87
163.87
163.88
163.78
163.78
163.79
163.79
163.79
163.79
163.87
163.96
164.04
164.04
164.13
164.22
164.22
164.22
164.22
164.22
164.22
164.22
164.23
164.22
164.13
164.14
164.05
163.96
163.96
163.97
163.97
163.88
163.88
163.88
163.88
163.88
163.96
163.96
164.05
164.13
164.22
164.22
164.31