loading

This is really a barometer/altimeter but you will see the reason for the title by looking at the video.

The MS5611 pressure sensor, found on the Arduino GY63 and GY86 breakout boards, delivers amazing performance. On a calm day it will measure your height to within 0.2m. This is effectively measuring the distance from your head to outer space and subtracting it from the distance of your feet to outer space (by measuring pressure – that is the weight of the air above). This spectacular device has a range that will comfortably measure the height of Everest - and can also measure down to a few inches.

This project was aimed as: a schools project, an example of modifying Arduino code and a good starting place to explore using the MS5611 sensor. There are plenty of forum questions from those having difficulties with this sensor. The approach here makes using it very straightforward. After doing this project you will be well equipped to develop other pressure related applications.

Every sensor has its own calibration constants that need to be read and used to correct the data. There is a library available to help drive these. The code shown here uses the library to take readings and then converts them to height and displays them on a LCD Shield.

First we will send the data to the serial monitor on the PC/laptop for initial tests. These show some noise and so we add a filter to smooth them out. Then we will add a LCD display so the unit can run independently and you can try measuring your height – or anything else.

Note the GY63 board just has the MS5611 pressure sensor. The GY86 is called a 10 degrees of freedom board and also includes a 3 axis accelerometer, 3 axis gyro and a 3 axis magnetometer for just a few $ more.

You will need:

1. Arduino UNO (or other with standard pinout) and its USB cable

2. GY63 breakout board or GY86

3. 4 Dupont leads male-female - or connecting wire

4. Arduino LCD keypad shield

5. 9v battery and lead

6. 2.54mm socket strip (optional but recommended)

Preparation

Download the Arduino IDE (integrated development environment) from: https://www.arduino.cc/en/Main/Software

Some technical bits for interest

The MS5611 delivers its great performance by averaging large numbers of measurements. It can make 4096 3 byte (24bit) analogue measurements in just 8ms and give the average value. It has to measure both pressure and temperature so the pressure data can be corrected for internal temperature. Hence it can deliver around 60 pairs of pressure and temperature readings per second.

The data sheet is available at: http://www.te.com/usa-en/plp/ms5611-01ba03/Xoye8B...

Communications is via I2C. So other I2C sensors can share the bus (as is the case on the GY86 10DOF board where all the chips are on I2C).

Step 1: Get a MS5611 Library

Many of the Arduino sensors either use a standard library that is included with the Arduino IDE or are supplied with a zip file with a library that can be easily installed. This tends not to be the case for the MS5611 sensors. However a search found: https://github.com/gronat/MS5611 that has a library for the MS5611, including performing the temperature correction.

Option 1

Go to the website above, click ‘Clone or Download’ and select ‘Download ZIP’. This should deliver MS5611-master.zip to your downloads directory. Now, if you wish, move it to a folder where you can find it in future. I use a directory called ‘data’ added to my Arduino folders.

Unfortunately the downloaded .zip file not does include any example sketches and it would be nice to add the library and examples to the Arduino IDE. There is a minimum example in the README.md file that can be copied and pasted into a sketch and saved. This is one way to get going.

Option 2

To make it easier to run the code in this instructable I have added the minimum example above and the examples shown here to the library and attached a .zip file below that will install into the Arduino IDE.

Download the zip file below. Move this to a better folder if you wish.

Start the Arduino IDE. Click Sketch>Include Library>Add zip file and select the file. Restart the IDE. The IDE will now both have the library installed plus all the examples shown here. Check by clicking File>examples>>MS5611-master. Three sketches should be listed.

Step 2: Connect the Sensor to the Arduino and Test

The GY63/GY86 boards usually come with headers but not soldered. So it is your choice to either solder the headers in place and use male-female Dupont leads, or (as I decided) solder leads directly to the board and add pins to the lead to plug into the Arduino. The latter option is better if you think you might want to solder the board into a project later. The former is better if you want to use the board for experimentation. Unsoldering leads is much easier than a pin header.

The connections required are:

GY63/GY86       Arduino 

VCC         -      5v       Power

GND         -      GND      Ground

SCL         -      A5       I2C clock

>SDA        -      A4       I2C data

Attach the sensor board to the Arduino as above and connect the Arduino to the PC/laptop via its USB lead. Also cover the sensor with some opaque/black material. The sensor is sensitive to light (as is the case for most of this type of sensor).

Start the Arduino IDE. Click:

File>examples>>MS5611-master>MS5611data2serial.

A new instance of the IDE will appear with the sketch. Click the upload button (right arrow).

Next start the serial plotter – click Tools>Serial Plotter and if necessary set the baud to 9600. The data being sent is the pressure in Pascals. After a second or so it will re-scale and raising and lowering the sensor by say 0.3m should show as lowering and raising of the trace (lower height is higher pressure).

The data has some noise. See first plot above. This can be smoothed using a digital filter (a really useful tool).

The filter equation is:

value = value + K(new-value)

where ‘value’ is the filtered data, and ‘new’ is the latest measured. If K=1 there is no filtering. For lower values of K the data is smoothed with a time constant of T/K where T is the time between samples. Here T is around 17ms so a value of 0.1 gives a time constant of 170ms or around 1/6s.

The filter can be added by:

Add a variable for the filtered data before setup():

float filtered = 0;

Then add the filter equation after the pressure = …. line.

filtered = filtered + 0.1*(pressure-filtered);

It is a good idea to initialise the filtered value to the first reading. So add an ‘if’ statement around the the line above that does this so it looks like:

if(filtered != 0){ 
filtered = filtered + 0.1*(pressure-filtered);
} 
else { 
filtered = pressure;          // first reading so set filtered to reading 
}

The test ‘!=’ is ‘not equal’. So if ‘filtered’ is not equal to 0 the filter equation is executed but if it is then it is set to the pressure reading.

Lastly we need to change ‘pressure’ to ‘filtered’ in the Serial.println statement so we see the filtered value.

The best learning is achieved by making the changes above manually. However I included these in the example MS5611data2serialWfilter. So if there are problems the example can be loaded.

Now upload the code to the Arduino and see the improvement. See second plot above and note the Y scale is expanded x2.

Try a lower value for the filter constant, say 0.02 instead of 0.1, and see the difference. The data is smoother but with a slower response. This is a compromise that has to be sought when using this simple filter. The characteristic is the same as a RC (resistance and capacitance) filter extensively used in electronic circuits.

Step 3: Make It Standalone

Now we will add a LCD Keypad shield, convert the pressure to height in meters, and show it on the display. We will also add the ability to zero the value by pressing the keypad ‘Select’ button.

With the LCD shield on the Arduino the sensor will have to be connected to the LCD shield. Unfortunately the LCD shields usually come without the appropriate sockets. So the options are to make solder connections or to get some socket strip. Socket strip is available on ebay for not much more than the cost of postage. Do a search on ‘2.54mm socket strip’ and look for ones that are similar to the ones on the Arduino. These usually come in 36 or 40 pin lengths. I would avoid the turned pin ones as they are not deep enough for standard Dupont leads.

The socket strip has to be cut to length and the cut has to be made in the same place as a pin. So for a 6 pin strip – remove the 7th pin with some fine pliers, then cut at that place using a junior hacksaw. I file the ends to make them neat.

Make sure there are no solder bridges when soldering them onto the board.

With the appropriate decision on connecting the sensor plug the LCD shield onto the Arduino and connect the sensor the same pins – but now on the LCD shield.

Also get the battery and lead ready. I made up my lead from parts in my scrap bin but they are also available on ebay – including a nice option that includes a battery box and switch. Search on ‘PP3 2.1mm lead’.

The current consumption is around 80ma. Hence if you want to run for more than a few minutes consider a bigger 9v battery than the PP3.

Step 4: Add Code for Altitude and the LCD

We need to do a little more coding to convert the pressure to height and drive the display.

At the start of the sketch add the display library and tell this what pins are used:

#include <LiquidCrystal.h> 
// initialize the library with the numbers of the interface pins 
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

Next we need some variables and a function to read the keypad buttons. These are all connected to analogue input A0. Each button gives a different voltage to A0. A search on ‘arduino lcd shield buttons code’ found some good code at:

https://www.dfrobot.com/wiki/index.php/Arduino_LCD_KeyPad_Shield_(SKU:_DFR0009)#Sample_Code

Add this code before setup():

// define some values used by the panel and buttons 
int lcd_key     = 0; 
int adc_key_in  = 0; 
#define btnRIGHT  0 
#define btnUP     1 
#define btnDOWN   2 
#define btnLEFT   3 
#define btnSELECT 4 
#define btnNONE   5 
// read the buttons 
int read_LCD_buttons() 
{ 
 adc_key_in = analogRead(0);      // read the value from the sensor 
 // my buttons when read are centered at these valies: 0, 144, 329, 504, 741 
 // we add approx 50 to those values and check to see if we are close 
 if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result 
 if (adc_key_in < 50)   return btnRIGHT; 
 if (adc_key_in < 250)  return btnUP;  
 if (adc_key_in < 450)  return btnDOWN;  
 if (adc_key_in < 650)  return btnLEFT;  
 if (adc_key_in < 850)  return btnSELECT;  
 return btnNONE;  // when all others fail, return this... 
}

Altitude is usually zeroed at the starting point. So we need variables for both height and reference. Add these before setup() and the function above:

float mtr; 
float ref = 0;

The conversion from pressure in Pascals to meters is almost exactly a division by 12 at sea level. This formula is fine for most ground based measurements. There are more accurate formulae that are more appropriate for conversion at high altitudes. Use these if you are going to use this to record the altitude of a balloon flight.

The reference should be set to the first pressure reading so we start at zero height and when the SELECT button is pressed. Add, after the filter code, and before the Serial.println statement:

  if(ref == 0){  
    ref = filtered/12.0; 
  } 
  if(read_LCD_buttons() == btnSELECT) { 
    ref = filtered/12.0; 
  }

After this add the height calculation:

  mtr = ref - filtered/12.0;

Lastly change the Serial.println statement to send ‘mtr’ instead of ‘filtered’, and add code to send ‘mtr’ to the LCD:

  Serial.println(mtr);   // Send pressure via serial (UART) 
  lcd.setCursor(0,1);         // line 2 
  lcd.print(mtr);

All the changes here are included in the example MS5611data2lcd. Load this as in step 2.

There is one last mod that is helpful. The display is difficult to read when it is being updated 60 times a second. Our filter is smoothing the data with a time constant around 0.8s. So updating the display every 0.3s seems plenty enough.

So add a counter after all the other variable definitions at the start of the sketch (e.g. after float ref=0;):

int i = 0;

Then add code to increment 'i' and an 'if' statement to run when it gets to 20 and then set it back to zero and move the Serial and lcd commands within the 'if' statement so these are only executed every 20th reading:

  i += 1; 
  if(i>=20) { 
  Serial.println(mtr); // Send pressure via serial (UART) 
  lcd.setCursor(0,1);         // line 2 
  lcd.print(mtr); 
  i = 0; 
  }

I did not include an example with this last modification in order to encourage entering the code manually which aids learning.

This project should give a good starting point for example for a digital barometer. For those who might want to consider use in RC models - search for OpenXvario for code that enables an altimeter and variometer for Frsky and Turnigy 9x telemetry systems.

<p>Hello, I am having a bit of a problem trying to get the example code MS5611data2lcd. It is not in the examples after I downloaded the MS5611.h There are threee other examples. Would it be possible for you to send me the sketch or even better the complete sketch of your LCD example that you showed in the video. I need a starting point for a project of my own and this example would be perfect. It is he only one I found on the web. My prject is for a model glider that ends a message to the ground when a certain height is reached with reference to the starting height, this is where I like your button which sets the starting point. Please help me if you can... many thanks in advance.</p><p>Paul</p>
<p>Paul</p><p>If you download the zip file attached to the instructable you will have the examples (except the final additional code that is not vital - and I did not include as I want to encourage those who have not started editing code to do so). Mike</p>
<p>Thank you, it works!!! </p>
<p>Great! It makes it worthwhile writing these up. Note that the sensors are light sensitive, so for best performance use some form of covering without blocking the holes. Mike</p>
<p>Your Project is really great, I have now converted the LCD to OLed because I Need to put this all in a model glider. I have a Problem with the Output which now Shows -8080.56 and the last Digits Change. I don't want to anoy you but could I send the code to you, I have done a way with the select button and want to set the beginning height by just resetting the arduino. When I tried your original code the selct did not seem to have any effect and i got 0 with the reset button. Perhasp you have a Suggestion or could get the correct height calculation going again on my code. The end Project is the set a max height at 500 meters and 800 meters and then send via nrf24L01 to the ground staion where a pizo buzzer either beeps at once per second for 500 meters and then continiously for 800 meters.I think the selction and Transmission I can cope with but the height calculation is a bit much for me, I am getting on a bit now nearly 70!</p><p>I understand Mike if you do not want to get involved that much... Thanks for your help.</p><p>Paul OE8PCK</p>
<p>Paul. As a first step of debugging I would either check the data on the serial monitor and/or temporarily add a line mtr = xxxx; (where xxxx is a number you want to test) before the lcd.print(mtr) statement to check that the new LCD is working OK. When things are not working I do tests on sections of the code to narrow the problem down. Mike</p>
<p>Mike,</p><p>I am really stuck. You wrote that the pressure in Pascal / 12 is the height in meters. This is for height around sea Level. Does this mean that your conversion will not work at 800 meters and is it far off I mean +- 5 meters?</p><p>I have tried attaching my code but I don't really know how. I am getting only -8077.xx where xx is varying on the Monitor and on my OLed.. I think it is something to do with ref and the select button which I cannot incorperate in my Setup.How could I send you my code?</p><p>Paul</p>
<p>Sorry Mike, I meant 150 feet or 250 meters</p>
<p>My sketch has code to read the pressure, filter it and convert to m. It looks like you also need to make sure your new display shows the data you send to it - as I commented above. You could also use any spare pin to operate as an input to zero the reading. If you are new to Arduino then look at the tutorials on the Arduino website or the training here. The MS5611 will work easily to any model height. I used an int32 for the pressure (dictated by the function) and floats for all the calculations so there should be no overflow problems.</p>
<p>Hi Mike,</p><p>All working OK. Thanks for the tip with the button. Now all I have to do is get the ESP24L01 working and the ground Station with a buzzer. Thanks for your Kind help and patience. If you would like the code I could send it when you tell me how. ;-)</p>
<p>Paul, glad you are on your way with your project. The 24L01 looks like a useful device. Might get a couple to have a play (when current list of projects are done). No need to send code - but you could always write an instructable! After I tested the MS5611 I programmed a PIC microcontroller to send altitude and climb rate back to my Frsky Taranis radio. So I have altitude spoken at the flick of a switch and full size glider vario sounds when desired - all on a PCB 11 x 28mm. I also implemented considerably more advanced filtering algorithms that give a faster response without compromising noise reduction.</p>

About This Instructable

2,823views

38favorites

Bio: Engineer, retired. Have always had an interest in electronics, often related to radio control. This evolved into a part time business that I still practice ... More »
More by FlyingDrMike:Micro/Mini Lathe, Three Bearing Live Centre Heating Plate for SMD Soldering – Simple, Small and Low Cost Simple, Low Cost and Accurate Stepper Motor Driver 
Add instructable to: