## MS5611 altitude sensor very sensitive to own working temperature

Wednesday, November 26th, 2014 at 6:43 pm

I was going great guns with my PALvario system, until I came back to looking at the barometer data. I redesigned the Arduino code to be more intelligent than simply waiting 10milliseconds for the reading to become ready from the MS5611 device, and programmed it do go do something else with this otherwise wasted time.

Suddenly all my readings were noise.

I won’t bore you by recounting how I isolated the problem, or how I suffered a delay of 2 hours due to a bug in the Arduino code where calling delayMicroseconds(0) actually delays by 4096 microseconds.

Here is basically the issue (reproduced in this code):

```ReadFromBarometer();
Serial.print(millis());
Serial.print(" ");
Serial.println(approxAlt);

// every alternate 4 seconds spread the readings out by an extra 5ms
if ((millis()/4000)%2 == 0)
delayMicroseconds(5000);
else
delayMicroseconds(5);
```

The result is a sudden step variation by 3 metres (the vertical lines are every 2 seconds).

The MS5611 barometer comes with a set of calibration constants used in a formula for converting its raw pressure reading (which is temperature sensitive) into corrected temperature value using its own temperature reading. You have to code the formula yourself, since the device is too small to do its own arithmetic processing.

Here’s the temperature graphs from the device:

My interpretation was that it’s warming up when I’m asking for a reading every 25ms, and then cooling down to a lower working temperature when I’m asking for a reading every 30ms.

But it’s worse than that.

Suppose I read at a constant frequency of about 30ms (25+5), except for once every 10 seconds insert a delay of an extra 45ms, like so:

```ReadFromBarometer();
PRINT (millis(), " ", TEMP);

static long B = 0;
long m = millis();
if (m/10000 != B/10000)
delay(50);
else
delay(5);
B = m;
```

This gives the lower yellow line in the graph. Most of the time it’s at 35.6 degrees, and when we have that extra delay, it spikes immediately down to 35.35 degrees.

The upper white line is the when I reversed the condition, so the delay(50) happened always, except for every 10 seconds there was a delay(5). Here we were at 36.32degrees with a sudden spike up to 36.45degrees. True, these are small amounts, but they are occurring in the space of 30milliseconds, which is the problem because it means your temperature compensation of the raw pressure reading takes place in the next 10ms is going to be out of date.

If I insert another delay of 150ms into the loop, I don’t get spikes any more, and the average temperature settles in at a hotter 36.83degrees.

There cannot be a physical reason for this, as the device is to small to carry any heating effects, so it must be due to a regulator of some sort.

It’s as if the circuitry dynamically adapts itself to the number of readings you are taking per second. Then if you change the gap between readings for even one instant, it tries to adapt its power handling the new cycle rate and causes a glitch.

This behaviour is not disclosed on the datasheet. What it does say there on page 5 is that:

The best noise performance from the module is obtained when the SPI bus is idle and without communication to other devices during the ADC conversion

But is SPI better than the I2C interface? The statement is ambiguous, so I tried the SPI interface out on Sunday (before all this blew up) and found no difference in noise levels. The problem I have here is not noise, because it’s completely predictable and not coming from any stray hardware electrical signals.

I experimented with lots of different cases.

(By the way, a very useful upgrade to the Serial monitor on the Arduino IDE would be to make it plot points and lines in a window if any output line contains something like the string “P5.1,3.7”. It’s extremely critical, but very tedious, to plot printed data into these graphs, and it would be a major step if this could be done directly out of the Arduino in this debugging tool. This is so important I might try to implement it in their code myself one day.)

This is exceptionally boring. And I’ve missed my lunch again. I had been looking forward to building a set of funky filters to immediately detect altitude changes from very dense data.

So anyway, I got the timing all evened out by inserting a reliable skip delay into the place where it reads pressure every 50milliseconds on the dot:

```static long Sm = 0;
long Dm = millis();
if (Dm/50 != Sm/50) {
PRINT (millis(), " ", TEMP, " ", alt);
Sm = Dm;
}
```

Now the barometer was being reasonably steady.

Then I tried running the vibration motors in the loop, and it went tits up again. Here’s the graph of temperature and altitude when the motors are doing their stuff for 10 seconds, and then are all off for ten seconds:

This is no good.

The only way forward for this is to wire it up to an entirely independent clean microcontroller which reads from it on a regular cycle and doesn’t do anything else except transfer the data to a main board through some mechanism.

There’s a chap in Austrialia making the blueflyvario who’s well ahead with this technology, and sends the readings directly from the MS5611 to an Android App via bluetooth.

I wonder if he has experienced this issue with the MS5611, or avoided it because it wasn’t exposed by his design.