TAQOZ Reloaded v2.8 - Reading the MS5611 barometric pressure sensor
The MS5611 pressure sensor is found on ebay as a low cost breakout board. It is useful for weather stations / altimeter applications. This code demonstrates driving the chip via the i2c bus. Type 5611READALL. to run a demonstration that reads the raw pressure and temperature from the chip and then applies maths ( described in the MS5611 application guide ) to display calibrated temperature and air pressure. Any key press will stop the demo. Before loading this code, load up these 64 bit arithmetic words first. Remember the temperature is that of the chip, which will be slightly warmer than the surrounding air. However, touching the MS5611 can, you should see the temperature rise a bit. Raising and lowering the sensor by the length of it's USB lead should change the pressure by a fraction of a mbar, albeit with some noise. Further averaging would yield a smoother signal.
Any advice on converting pressure to altitude (both QNH and QFE) using integer maths is welcomed. That may be added in a later version if I find a useful algorithm.
Here's the MS5611 driver code - it requires pin PS to be tied to 3.3V to use the i2c interface and CSB wired to 0V to set the chip at address $EE :-
--- MS5611 barometric pressure sensor chip i2c driver ver 3 - Bob Edwards G4BBY Feb 2022
--- For TAQOZ Reloaded v2.8
--- This code requires my Double Arithmetic words ver 3 or higher being loaded prior to this file
--- See forums.parallax.com/discussion/174163/taqoz-reloaded-v2-8-double-arithmetic-64-bit-words
--- Refers to Measurement Specialties doc. DA5611-01BA03_011 000056111624 ECN1742 Oct 26, 2012
IFDEF *MS5611* FORGET *MS5611* }
pub *MS5611* PRINT" MS5611 barometric pressure sensor ver 3" ;
ALIAS I2C.START <I2C --- Matches the stop alias, I2C>
--- create constant to hold current i2c chip address
0 := i2cadr
--- variables - some names are similar to those in the application paper
6 words C --- to hold the six MS5611 calibration words
C := C1
C 2+ := C2
C2 2+ := C3
C3 2+ := C4
C4 2+ := C5
C5 2+ := C6
long RAWTEMP --- referred to as D2 in the application guide
long RAWPRESS --- referred to as D1 in the application guide
long dT
long CALTEMP --- referred to as TEMP in the application guide
long CALPRESS --- referred to as P in the application guide
long T2
long OFF2
long SENS2
double OFFSET --- referred to as OFF in the application guide
double SENS
--- set the i2c address for subsequent i2c transfers ( like PIN does for smartpins )
pub I2CADR ( n -- )
' i2cadr :=!
;
--- comment out the address setup that doesn't apply to your hardware
--- I2C address of the MS5611 with pin CSB connected to 0V
$EE I2CADR
--- I2C address of the MS5611 with pin CSB connected to Vdd
--- $ED I2CADR
--- MS5611 reset sequence
pub 5611RESET ( -- )
i2cadr I2CWR --- send device address to select the MS5611
%00011110 I2C! --- send the reset cmd
I2C.STOP
5 ms
;
--- MS5611 read the prom - promaddr in the range 1 to 7, 1-6 being coefficents, 7 being serial code and CRC
pub 5611PROM ( promaddr -- promdata )
i2cadr I2CWR --- send device address to select the MS5611
2* %10100000 + I2C! --- send the read prom command
I2C.STOP
i2cadr I2CRD
I2C@ 8 << --- read the MS byte of the PROM
nakI2C@ + --- read the LS byte and combine into 16 bits
I2C.STOP
;
--- MS5611 save all 6 PROM coefficients in array C
pub 5611PROMRDALL ( -- )
5611RESET
CRLF
7 1 DO
I 5611PROM
I 1- 2* C + W!
LOOP
;
--- MS5611 display all PROM coefficients
pub 5611PROM. ( -- )
5611PROMRDALL
6 0 DO
." PROM address " I 1+ .
." = "
I 2* C + W@ . CRLF
LOOP
;
--- MS5611 start temperature conversion command, oversampling ratio 4096
pub 5611CONVTEMP ( -- )
i2cadr I2CWR --- send device address to select the MS5611
$58 I2C! --- send the start conversion cmd
I2C.STOP
10 ms --- wait for the converion to complete
;
--- MS5611 start pressure conversion command, oversampling ratio 4096
pub 5611CONVPRESS ( -- )
i2cadr I2CWR --- send device address to select the MS5611
$48 I2C! --- send the start conversion cmd
I2C.STOP
10 ms --- wait for the converion to complete
;
--- MS5611 read back pressure or temperature result
pub 5611READDATA ( -- data )
i2cadr I2CWR --- send device address to select the MS5611
0 I2C! --- send the read data command
I2C.STOP
i2cadr I2CRD --- send the device address for data read
I2C@ 16 << --- read the MS byte of data
I2C@ 8 << + --- read the middle byte of the data
nakI2C@ + --- read the LS byte
I2C.STOP
;
--- MS5611 Read raw pressure data
pub 5611READPRESS ( -- )
5611CONVPRESS
5611READDATA
RAWPRESS !
;
--- MS5611 Read raw temp data
pub 5611READTEMP ( -- )
5611CONVTEMP
5611READDATA
RAWTEMP !
;
--- Convert RAWTEMP to deg C x 100 and save at CALTEMP, so 2001 = 20.01 degC
pub 5611CALTEMP ( -- )
RAWTEMP @
C5 W@ 8<< -
DUP dT !
L->D --- here we have to use doubles as the max
C6 W@ L->D D* 23 D>> --- intermediate value could be up to 41 bits
2000. D+
DROP --- as the result is always less than 32 bits
CALTEMP ! --- we drop the top 32 bits
;
--- Convert RAWPRESS to mbar x 100 and save at CALPRESS, so 100009 = 1000.09 mbar
pub 5611CALPRESS ( -- )
C4 W@ L->D
dT @ L->D D* 7 D>>
C2 W@ L->D 16 D<< D+
OFFSET D! --- save OFF value
dT @ L->D
C3 W@ L->D D* 8 D>>
C1 W@ L->D 15 D<< D+
SENS D! --- save SENS value
RAWPRESS @ L->D
SENS D@ D* 21 D>>
OFFSET D@ D- 15 D>>
DROP CALPRESS ! --- save true pressure in mbar x 100
;
--- n2 = n1*n1
pub SQUARE ( n1 -- n2 )
DUP *
;
--- MS5611 apply second order temperature compensation to increase accuracy below 20C
pub 5611SECORDER ( -- )
CALTEMP @ 2000 <
IF
dT @ L->D DSQR 31 D>>
DROP T2 !
CALTEMP @ 2000 - SQUARE 5 * DUP
2/ OFF2 !
4/ SENS2 !
CALTEMP @ -1500 <
IF
CALTEMP @ 1500 + SQUARE DUP
7 * OFF2 @ + OFF2 !
11 * 2/ SENS2 @ + SENS2 !
THEN
CALTEMP @ T2 @ - CALTEMP !
OFFSET D@ OFF2 @ L->D D- OFFSET D!
SENS D@ SENS2 @ L->D D- SENS D!
THEN
;
--- Display the raw temp and pressure
pub UNCALVAL. ( -- )
." Raw pressure = "
RAWPRESS @ . --- Display raw pressure data
." Raw temp = "
RAWTEMP @ . --- and raw tempdata
;
--- Display the calibrated temp and pressure
pub CALVAL. ( -- )
." Conversion ... "
CALTEMP @
DUP 1000 < IF
.AS" #.## deg C "
ELSE
.AS" ##.## deg C "
THEN --- display temp in deg C
CALPRESS @
DUP 100000 < IF
.AS" ###.## mbar"
ELSE
.AS" ####.## mbar"
THEN
;
--- MS5611 read back raw and corrected data until key press
pub 5611READALL. ( -- )
5611RESET --- Reset the MS5611
5611PROMRDALL --- Read in all the calibration constants
CRLF
BEGIN
5611READPRESS --- Start the pressure A/D conversion and read in the data
150 ms
5611READTEMP --- Start the temp A/D conversion and read in the data
150 ms
5611CALTEMP --- Convert the raw temp data to deg C
5611CALPRESS --- Convert the raw pressure data to mbar = hPa
5611SECORDER --- Apply 2nd order compensation below 20 deg C
UNCALVAL. --- display raw data
CALVAL. --- display calibrated data
CRLF
KEY UNTIL --- repeat until a keystroke
;
{
--- Arithmetic check against example data in the application guide
pub .truefalse ( f -- )
if
." ok"
else
." not ok"
then
;
--- Load up the variables with the example data from the application sheet
40127 C1 W!
36924 C2 W!
23317 C3 W!
23282 C4 W!
33464 C5 W!
28312 C6 W!
9085466 RAWPRESS !
8569150 RAWTEMP !
CRLF
5611CALTEMP
." dT calculation is " dT @ 2366 = .truefalse CRLF
." TEMP calculation is " CALTEMP @ 2007 = .truefalse CRLF
5611CALPRESS
." OFF calculation is " OFFSET D@ 2420281617. D= .truefalse CRLF
." SENS calculation is " SENS D@ 1315097036. D= .truefalse CRLF
." CALPRESS calculation is " CALPRESS @ 100009 = .truefalse CRLF
}


Comments
The 2nd order correction word 5611SECORDER had a bug, so I've up-issued the code to fix that. The demo runs without crashing when the temperature is below 20 C
Hi Bob, many thanks for your MS5611 driver and 64 bit maths code. Well done.
I don't have a MS5611 module but a I do have a couple of MS5803-02BA pressure sensor modules which have very similar data conversion functionality.
I'll try your code with the MS5803-02BA - thanks for publishing it. Cheers Pete.