Introduction: Standalone Arduino Altimeter

Here is a standalone altimeter working with Arduino that you can use in RC project, hiking, cars... where you want :)

It shows on first screen the altittude, the temperature & the air pressure, and in the second, the minimum / maximum altitude reached.

Parts needed: (~12$)

  • An arduino board like a nano, pro mini or even AtTiny85 (depends on what you want, pro mini is lighter than nano and can works with an input voltage of 3.3v to 12v, perfect for light weight RC) 3.29$ on ebay
  • BMP280 chip temperature & barometric pressure sensor 1.84$ on ebay
  • An OLED display (0.96" I2C IIC Série 128X64) 5.32$ on ebay
  • Iron solder, tin and wires
  • A plastic case to put all in 1.50$ on ebay

Step 1: The Wiring

The wiring is simple, the most "complicated" is to find the SCL and SDA pin on your arduino.

On the nano as on the photo, pin A4 is SDA and pin A5 is SCL.

On the Pro Mini, take a look at the picture, SDA is upside right to pin A2, and SCL upside right to pin A3.

Once your wiring is done, lets upload the sketch to the Arduino !

Step 2: The Program

Code explanations (full code below):

#include "U8glib.h"
#include "BMP280.h"

They are the 2 libraries you have to put inside Documents\Arduino\libraries\

#define P0 1021.97

This is where you calibrate the altimeter, changing this value. Once it's done, it's pretty accurate !

(by default it was 1013.25, i had to up it to 1021.97 to have the right altitude in my town)

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NO_ACK);

Here you define the Oled screen type (128x64 etc...)

  u8g.drawStr( 5, 10, "Temp: ");
u8g.drawStr( 5, 30, "Bar : "); u8g.drawStr( 5, 50, "Alt : "); u8g.drawStr( 50, 10, sT); u8g.drawStr( 50, 30, sP); u8g.drawStr( 50, 50, sA);

Here the informations you want to display on first screen and their position ( Y, X, VALUE)

  dtostrf(A_MIN, 4, 2, sA_MIN);
dtostrf(A_MAX, 4, 2, sA_MAX); u8g.drawStr( 5, 20, "A Min: "); u8g.drawStr( 60, 20, sA_MIN); u8g.drawStr( 5, 45, "A Max: "); u8g.drawStr( 60, 45, sA_MAX);

Same for second screen

      if ( A > A_MAX) {
A_MAX = A; }
      if ( A < A_MIN || A_MIN == 0) {
        A_MIN = A;
      }

Here we update the minimum and maximun altitude stored

      do {
draw(T, P, A); } while ( u8g.nextPage() ); u8g.firstPage(); delay(1000);

Here, with the delay value (1000 in this case), you will stay 1 second on the first screen before switching to the second one. So change that if you want to customize display time :)

      do {
draw2(A_MIN, A_MAX); } while ( u8g.nextPage() ); u8g.firstPage(); delay(1000);

Same for second screen !

Hope it's clear, feel free to post a question in comments if needed !

Here is the full code:

#include "U8glib.h"
#include "BMP280.h" #include "Wire.h" #define P0 1021.97 //1013.25 BMP280 bmp; // OLED Type U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NO_ACK); char sT[20]; char sP[9]; char sA[9]; char sA_MIN[9]; char sA_MAX[9]; double A_MIN = 0; double A_MAX = 0; void draw(double T, double P, double A) { u8g.setFont(u8g_font_unifont); dtostrf(T, 4, 2, sT); dtostrf(P, 4, 2, sP); dtostrf(A, 4, 2, sA); u8g.drawStr( 5, 10, "Temp: "); u8g.drawStr( 5, 30, "Bar : "); u8g.drawStr( 5, 50, "Alt : "); u8g.drawStr( 50, 10, sT); u8g.drawStr( 50, 30, sP); u8g.drawStr( 50, 50, sA); } void draw2(double A_MIN, double A_MAX) { u8g.setFont(u8g_font_unifont); dtostrf(A_MIN, 4, 2, sA_MIN); dtostrf(A_MAX, 4, 2, sA_MAX); u8g.drawStr( 5, 20, "A Min: "); u8g.drawStr( 60, 20, sA_MIN); u8g.drawStr( 5, 45, "A Max: "); u8g.drawStr( 60, 45, sA_MAX); } void setup() { Serial.begin(9600); if (!bmp.begin()) { Serial.println("BMP init failed!"); while (1); } else Serial.println("BMP init success!"); bmp.setOversampling(4); u8g.setColorIndex(1); u8g.setFont(u8g_font_unifont); } void loop(void) { double T, P; char result = bmp.startMeasurment(); if (result != 0) { delay(result); result = bmp.getTemperatureAndPressure(T, P); if (result != 0) { double A = bmp.altitude(P, P0); if ( A > A_MAX) { A_MAX = A; } if ( A < A_MIN || A_MIN == 0) { A_MIN = A; } // Serial.print("T = \t"); Serial.print(T, 2); Serial.print(" degC\t"); // Serial.print("P = \t"); Serial.print(P, 2); Serial.print(" mBar\t"); // Serial.print("A = \t"); Serial.print(A, 2); Serial.println(" m"); u8g.firstPage(); do { draw(T, P, A); } while ( u8g.nextPage() ); u8g.firstPage(); delay(1000); do { draw2(A_MIN, A_MAX); } while ( u8g.nextPage() ); u8g.firstPage(); delay(1000); } else { Serial.println("Error."); } } else { Serial.println("Error."); } delay(100); }

Step 3: Now It's Up to You !

You can move form the breadboard to the plastic case with soldering all.

Then, put it on RC plane, RC quadcopter, RC helicopter..... or a water rocket !

Hope it was helpful and that you will send me a pic once it's done =)

Comments

author
TimP172 made it! (author)2017-09-16

Thanks - awesome project. Tweaked P0 to 1024.22 to get my actual height of 16-ish meters above sea level

bmp280.jpg
author
PaulSkydive (author)2017-02-19

Hi everyone, I'm trying to run this but I can't even get past the verification of the code. I'm very new to this and I must be doing something stupid, any ideas?

The error is

error: 'bmp' was not declared in this scope

if (!bmp.begin()) {

^

The first occurrence of the error is at line 4: BMP280 bmp;

but it continues anywhere "bmp" is mentioned.

Many thanks in advance, Paul

author
Shoyun (author)PaulSkydive2017-02-19

Hi Paul, you have this error because there is a problem with the "BMP280.h" library, verify that you have put the 2 libraries inside Documents\Arduino\libraries\ as in the Step 2: The program

author
PaulSkydive (author)Shoyun2017-02-19

Thank you so much Shoyun! :-)

I was being stupid!

Thanks again

author
Shoyun (author)PaulSkydive2017-02-19

You are welcome ! Glad to help you :)

author
alainn (author)2016-11-17

Hi

how to set the QNH?

author
Shoyun (author)alainn2016-11-17

Hi alainn, to calibrate the altimeter (if i understand you well) you have to play with the P0 value in the begining of the code: #define P0 1021.97

Change the 1021.97 value to match your real altitude, then it's calibrated and acurate :)

author
alainn (author)Shoyun2016-11-18

Hi Shoyun
you need a computer to do that
not very convenient
this one use a tactil switch
http://electro.olganet.com/2014/03/29/tiny-altimeter-oled/
but not convenient also
an encoder should be nice to set the QNH or QNE
so you should use your device as a true altimeter in a plane

author
Shoyun (author)alainn2016-11-18

Hi ! You are right, you need a computer but once the setting is done if you stay at the same place it will be ok :)

For my purposes it was enough, maybe you need the ability to set up on the go, it may be possible to add it.

author
tmercados (author)2016-07-21

Nice project

How could I change the delay to put a button?

author
Shoyun (author)tmercados2016-07-23

Hi, i don't undersand what you really want to do, sorry.

author
tmercados (author)Shoyun2016-07-26

there is a delay to change the screen (one second)
I want to put a button instead of the Delay to change the screens
How can I do it?

author
amitye1234 (author)2016-07-23

Hello! Is there an option to see the history of the altitude using that method?

Thanks

author
Shoyun (author)amitye12342016-07-23

Hi !

The screen auto switch from current data and min / max altitude every second. No history but min and max altitude values.

It could be done writing on a sd card current data every x seconds :)

author
tmercados (author)2016-07-21

Nice project

How could I change the delay to put a button?

author
ab6ui (author)2016-07-20

One other minor detail was that I had to put both CSD and SDO (on the BMP280) to +3.3 to get it to work. In your diagram you showed SDO going to GND when I did that it did not work... Now to get it packaged up and on top of a water rocket!

author
Shoyun (author)ab6ui2016-07-20

Oh ok, maybe something different in our chips. Nice that you found the solution, it can help others :)

When you will finish your water rocket send a picture ! =)

author
ab6ui made it! (author)2016-07-20

Got it working! The problem was in the BMP280.h file. The I2C address was 0x76 and my BMP280 was on 0x77. Once I ran the I2C scanner I was able to correct the BMP280.h lib file with the correct address and then it worked fine!

100_1258.JPG100_1259.JPG
author
Shoyun (author)ab6ui2016-07-20

Glad to read that :))) Nice !

author
ab6ui (author)2016-07-20

I am having problems. I tested the display and the BMP280 separately and they work fine. (Note: using a different library for the 280 Adafruit_BMP280.h) But when I try and run your script all I see is a bunch of small pixels on the screen.

Please advise... Thanks Bill

author
Shoyun (author)ab6ui2016-07-20

Hi Bill.

If you changed the library used, u maybe have to adapt my code, why don't you use the library i mentioned ? Not compatible ?

Hope you will managed to make it work.

author
ab6ui (author)Shoyun2016-07-20

Hopefully you saw that I did get it working.. But yes there was a problem with the original library with the I2C address. I was able to correct it and now it's working... I did not even try and get it working with the Adafruit_BMP280.h it is very different.

author
seamster (author)2016-06-01

This is a pretty cool idea. For practical purposes for RC or rockets, how small of a bundle do you think you could fit all of these components into?

author
Shoyun (author)seamster2016-06-01

Thanks :)

It can be really small and light weight with an Attiny85 or nano. I can't tell u exactly but i'm sure that it will be small enough !