The BMP280 based pressure and temperature sensors have an amazing accuracy for their price point (around 1$USD, 1Euro, 1GBP or cheaper!) and they are incredibly easy to connect up and use. Both I²C or SPI busses are usually supported. Below is the one similar to those that are readily available.
They usually come with header pins that need soldering, although local eBay sellers may offer soldered ones for a premium. For this tutorial I’m going to connect to the I²C bus and use a OLED display for output.
If you want a video guide as well as this page then click below, however this guide has been updated but I’m unable to edit the video below without completely deleting it first. So the video will no not match the guide perfectly. The guide has in fact been simplified.
Connection Diagram
Just connect your device to the hardware I²C of your micro-controller of your choice, here’s my Nano set-up;
For other Arduino’s see this table of connection pins:
BMP280 Connection | Nano Connection | Pro-Micro | Uno | Leonardo |
---|---|---|---|---|
VCC | 5V | 5V | 5V | 5V |
GND | GND | GND | GND | GND |
SCL | A5 | 3 | A5 (*) | #3 |
SDA | A4 | 2 | A4 (*) | 2 |
The code
To make this we need a library. In the Arduino IDE open up the Library Manager (“Tools->Manage Libraries…”). In the search box type in “Adafruit bmp280” and only one result should return (at time of writing). Install this library..
Example Code
From the menu “File->Examples->Adafruit BMP280 Library->bmp280 test”. Compile, upload and then open your serial monitor. if you get the following output:
BMP280 test
Could not find a valid BMP280 sensor, check wiring!
The the most likely culprit (presuming wiring is correct) is that the I²C address of your sensor is different than the one supplied by Adafruit. If you don’t get this issue and have something like this:
BMP280 test
Temperature = 25.60 *C
Pressure = 100585.72 Pa
Approx altitude = 61.73 m
then your sensor is being read fine and you can move onto the Height and Pressure section below.
Trouble-shooting the I²C address
If you have wired everything correctly then the culprit is probably the I²C address of your sensor. Copy this code below (and upload) to scan the I²C addresses of all your devices attached to your Arduino.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
// -------------------------------------- // i2c_scanner // // Version 1 // This program (or code that looks like it) // can be found in many places. // For example on the Arduino.cc forum. // The original author is not know. // Version 2, Juni 2012, Using Arduino 1.0.1 // Adapted to be as simple as possible by Arduino.cc user Krodal // Version 3, Feb 26 2013 // V3 by louarnold // Version 4, March 3, 2013, Using Arduino 1.0.3 // by Arduino.cc user Krodal. // Changes by louarnold removed. // Scanning addresses changed from 0...127 to 1...119, // according to the i2c scanner by Nick Gammon // http://www.gammon.com.au/forum/?id=10896 // Version 5, March 28, 2013 // As version 4, but address scans now to 127. // A sensor seems to use address 120. // Version 6, November 27, 2015. // Added waiting for the Leonardo serial communication. // // // This sketch tests the standard 7-bit addresses // Devices with higher bit address might not be seen properly. // #include <Wire.h> void setup() { Wire.begin(); Serial.begin(9600); while (!Serial); // Leonardo: wait for serial monitor Serial.println("\nI2C Scanner"); } void loop() { byte error, address; int nDevices; Serial.println("Scanning..."); nDevices = 0; for(address = 1; address < 127; address++ ) { // The i2c_scanner uses the return value of // the Write.endTransmisstion to see if // a device did acknowledge to the address. Wire.beginTransmission(address); error = Wire.endTransmission(); if (error == 0) { Serial.print("I2C device found at address 0x"); if (address<16) Serial.print("0"); Serial.print(address,HEX); Serial.println(" !"); nDevices++; } else if (error==4) { Serial.print("Unknown error at address 0x"); if (address<16) Serial.print("0"); Serial.println(address,HEX); } } if (nDevices == 0) Serial.println("No I2C devices found\n"); else Serial.println("done\n"); delay(5000); // wait 5 seconds for next scan } |
This will result in a output on the serial monitor similar to that below:
I2C Scanner
Scanning…
I2C device found at address 0x76 !
done
So the BMP280 is address 0x76. Yours may be different, follow the advice above this scanner code to enter this address into the example code.
Re-compile and upload the BMP280 demo code from above again. Hopefully this time you should have a result like this:
BMP280 test
Temperature = 25.60 *C
Pressure = 100585.72 Pa
Approx altitude = 61.73 m
Height and Pressure
Pressure is returned in Pascals (Pascal is one of the many units of pressure) with the standard pressure being 100,000 Pascals. The altitude is derived by knowing the air pressure at ground level. Air pressure is the result of all the air above it pressing down (just like the deeper you go in the sea the pressure increases due to the weight of water above this depth). The further you go up the less air there is above you. Knowing this a simple calculation can be made to calculate height above sea level based on the pressure measured. However air pressure varies around the world so the routine that calculates the height takes a Barometric Pressure reading for your local area, this is the line:
Serial.print(bmp.readAltitude(1013.25));
Just Google air pressure for where you live.
For an exercise, instead of adding the local area pressure you could pass in the current pressure (will need to convert from raw Pascals) and then it will show 0 meters when switched on and then measure height relative to the devices starting position and not relative to sea level.
Adding the OLED display
See this article on adding a display to an Arduino, once this has been done the following code will display the results on the screen.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
#include <Adafruit_Sensor.h> #include <Adafruit_BMP280.h> #include <Adafruit_SSD1306.h> #define OLED_Address 0x3C Adafruit_BMP280 bmp; // I2C Adafruit_SSD1306 oled(1); void setup() { oled.begin(SSD1306_SWITCHCAPVCC, OLED_Address); oled.clearDisplay(); oled.setTextSize(1); oled.setTextColor(WHITE); if (!bmp.begin()) { oled.setCursor(0,0); oled.print("Could not find a valid BMP280 sensor, check wiring!"); oled.display(); while (1); } } void loop() { oled.clearDisplay(); oled.setCursor(0,0); oled.print("Temp = "); oled.print(bmp.readTemperature()); oled.print(" Celcius"); oled.setCursor(0,16); oled.print("Press. = "); oled.print(bmp.readPressure()); oled.print(" Pa"); oled.setCursor(0,32); oled.print("height = "); oled.print(bmp.readAltitude(1013.25)); oled.print(" m"); oled.display(); delay(2000); } |
For an exercise, instead of adding the local area pressure you could pass in the current pressure (will need to convert from raw Pascals) and then it will show 0 meters when switched on and then measure height relative to the devices starting position and not relative to sea level.
Enjoy and learn 🙂