Become a subscriber (Free)

Join 29,000 other subscribers to receive subscriber sale discounts and other free resources.
:
:
Don't worry -- your e-mail address is totally secure. I promise to use it only to send you MicroZine.

How to use the BMP280 Barometric Pressure Chip

The BMP280 is an insanely small SMD device (2.0mm x 2.5mm) so you'll need to get hold of a breakout board to use it on the bench. It is a small enough that it can be used within a mobile phone. That may seem a bit unusual as you would probably think of this device used only in a weather station environment until you realise that pressure can be used to measure altitude.

In fact the applications that are suggested by Bosch Sensortech (manufactures the BMP280) are:

  • Enhancement of GPS navigation (e.g. time-to-first-fix improvement, dead-reckoning, slope detection)
  • Indoor navigation (floor detection, elevator detection)
  • Outdoor navigation, leisure and sports applications
  • Weather forecast
  • Health care applications (e.g. spirometry)
  • Vertical velocity indication (e.g. rise/sink speed)

It is also ideally suited and for use as a highly accurate Arduino barometric pressure sensor since it employs an SPI interface.

[Source: https://www.bosch-sensortec.com/bst/products/all_products/bmp280]


bmp280 pressure sensor block diagram

Source: datasheet Figure 1

Initially it would seem that measuring height using a BMP280 chip is a little redundant since a GPS system is far more accurate and also gives you height information as well. Now, I did a little research on Google and that last statement may not be so accurate!

We all tend to assume that any system we have is absolutely accurate and I thought GPS was in that category (based on the fact that my satnav shows me exactly where I am - but how accurate is that?). It turns out to be about ±10m!

Despite the fact that GPS satellites have atomic clocks on board and even after adjustment for relativistic changes due to speed of travel and distance above the earth - there are other factors that influence GPS accuracy including the atmosphere, satellite position inaccuracy and other factors as well - and these can add up to quite a large error.

Garmin GPS receivers are typically accurate to 10m [horizontal measurement]
[Source: Garmin.com/aboutGPS].

Did you know that the military did not believe that Einstein's theory of relativity would apply and built in a software switch to inside the satellite code to stop adjustment for that science (they had to turn it on when they found Enistein's relativity theorem did apply even to their satellites!).

Why a GPS height Measurement is not that accurate

Another website (see link below|) discusses the problem more fully. In summary, it is a comparison of GPS vs Barometric Pressure measurement. In that article it discusses how hang gliders and paragliders must fly within a specific defined volumetric space so that they are not eliminated from the competition. To do that it is important that they can measure height accurately using their own instruments and you would have thought that the GPS system is ideal for that; Maybe not!

The thing about GPS is that the GPS receiver knows where the satellites are so it knows its position relative to 4 or more satellites with extreme accuracy (more satellites give increasing positional accuracy). The problem is that the orbit of the satellites does not mean that the satellite or GPS receiver knows where the ground is located!

""Your GPS unit has multiple models (datums) of the Earth in its memory."

[source http://www.xcmag.com/2011/07/gps-versus-barometric-altitude-the-definitive-answer/]

In fact, each GPS unit has multiple models of the earth's surface e.g. WGS 84 (World Geodetic System - created in 1984). Other datums can be more accurate for specific countries e.g. in the UK OSGB36 (ordinance survey data). There are quite a few other datum sets but WGS 84 is commonly used for GPS systems.

The WGS 84 system defines an oblate spheroid that approximates the shape of the Earth and this is where errors can occur depending on where you are located. In the UK you would be 70m above the true height, and in India 100m below! (See the link above for a heatmap of height variation around the globe). Depending on your GPS the error may be calculated and compensated out (geoid correction).

Additionally there are other horizontal error sources due to:

  • Ionospheric effect (±5m)
  • Satellite position error (±2.5)
  • Satellite clock error (±2m)
  • Multipath interference (±1m)
  • Tropospheric effect (±0.5m)
  • Maths and rounding errors (±1m)

Total horizontal error: ±15m. It is estimated that the vertical error is 3 times this: ±45m.

Another error source is from averaging the information over time e.g. over a few seconds so there will be a delay in output reading while climbing or falling.

The section above is a summary from this link:

http://www.xcmag.com/2011/07/gps-versus-barometric-altitude-the-definitive-answer/

Using Barometric Pressure for Height Measurement

In fact all aviation uses a Barometric pressure measurement converted to show a height measurement, since pressure decreases with height. Factors that affect the reading are temperature and so altimeters are temperature compensated. Another factor is the ground level pressure measurement (defines zero height) which varies with the weather so altimeters allow setting of the ground level pressure reading (obtained from weather services for aviation) to eliminate local pressure changes. lookup QNH and QNE

With the Bosch 280 chip the pressure range is from 300 to 1100 hPa which means height can be measured from +9000m to -500m. It also has an relative accuracy of ±0.12 hPa. This equates to a relative accuracy of ±1m.

Note: This is probably the maximum inaccuracy - see later for actual measurements that show the sensor (the specific one I am using) is far more sensitive to relative height change.

Even if this inaccuracy is correct across the range of batches of all BMP280's then it still represents a hugely more accurate reading than using a GPS for height measurement.

The absolute accuracy is ±1hPa equivalent to 11.9m [ 9500.0/(1100-300) ] - this is still quite a bit better than GPS vertical readings. To get a more accurate height reading the unit would have to be calibrated i.e. set the output reading to zero on the ground (or get the current ground level pressure reading for the area from an aviation service and input it to the microcontroller).

The BMP280 (all electronic barometers probably) can react very quickly to pressure changes - there is no waiting around. The datasheet indicates that you can read the device 157 times a second (for the BMP180 it is 120Hz). This means variations in height can be rapidly detected. This is a bit too fast for height measurements - you won't need that many data points - although they can be used when employing the IIR filter i.e. oversampling and then filtering to get a stable output. The rapid measurement rate would be more appropriate for spirometry (measurement of breathing) or for rapid height change measurement such as in a hang glider competition..

Difference between BMP180 and BMP280

The following table shows the difference between the older BMP180 and the replacement part BMP280. Note how the BMP280 has far better specifications and has multiple interfaces including high speed SPI, whereas the BMP180 only has I2C (you could have ordered a separate part with SPI). The other major difference is that the BMP280 has a selectable filter operation with 5 different bandwidths resulting in measurements with higher accuracy.

Comparison of BMP280 and BMP180

Note Temperature accuracy data is (buried in the data sheet):

  • ±0.5°C (at 25°C) and
  • ±1.0°C (over the full temperature range 0°C ~ 65°C).

Pressure Measurement Units

Unit Symbol No Pascals
bar bar 1 x 105 Pa (exactly)
millibar mbar 100 Pa (exactly)
hectopascal hPa 100 Pa (exactly)
conventional millimetre or mercury mmHg 133.322... Pa
convetional inch of mercury inHg 3386.39... Pa
pound-force per square inch lbf/in2 6894.76... Pa

[ Source: http://www.npl.co.uk/reference/faqs/pressure-units ]

Note: hPa is numerically identical to mbar (millibar).

Measuring Altitude

To measure altitude you have to know the pressure reading at sea level. The commonly used value is 101325 Pa or 1013.25mb - this was intended to represent the mean atmospheric pressure at sea level. Unfortunately the value is not representative of the pressure at sea level in many different countries.

Really, the only way for accurate height measurement, is to obtain the pressure value for sea level on the day from a reliable forecast.

Note Even the ground level value will change through out the day anyway, so you really need a radio link transmitting the current pressure on the ground to your measuring device. This would make the altitude measurement as accurate as possible even with local pressure variations.

Schematic diagram

Note Use the level translator parts if your breakout doesn't have them on-board (some boards come with level translator components). If it does have them then connect from the (5V) uno to the breakout board directly. Alternatively use a 3V3 arduino for direct connection.

Arduino Uno BMP280 wiring

bmp280 schematic

Note: The I2C connections are the two top left ones on an Arduino Uno if the usb connector is at the left of the board. They are not marked. The left one is SCL and the right one is SDA. They are the two shielded pins opposite the 6 pin connector the next labelled pin is AREF.

Typical pressure Results through the day

These reading are taken from the serial monitor output from the Arduino serial port for both Adafruti BMP280 library and I2C library (I2C library 1st). Height is not calibrated = wrong (except where noted).

10.15 3/8/17 avg 3-4th aug 1007mbar sea level pressure forecast
Probe BMP280: Sensor found
 HeightPT1: 7.41 m; Height: 81.49 Pressure: 100350.00 Pa; T: 22.97 C
 HeightPT1: 14.10 m; Height: 80.99 Pressure: 100356.00 Pa; T: 23.03 C
 HeightPT1: 80.79 m; Height: 80.74 Pressure: 100359.00 Pa; T: 23.14 C

16:37 3/8/17
Probe BMP280: Sensor found
 HeightPT1: 6.81 m; Height: 74.95 Pressure: 100428.00 Pa; T: 23.43 C
 HeightPT1: 13.01 m; Height: 74.95 Pressure: 100428.00 Pa; T: 23.50 C
 HeightPT1: 18.62 m; Height: 74.78 Pressure: 100430.00 Pa; T: 23.55 C

17.06 3/8/17
 HeightPT1: 73.82 m; Height: 73.61 Pressure: 100444.00 Pa; T: 24.29 C
 HeightPT1: 73.82 m; Height: 73.86 Pressure: 100441.00 Pa; T: 24.29 C
 HeightPT1: 73.80 m; Height: 73.61 Pressure: 100444.00 Pa; T: 24.29 C

17:13 3/8/17
 HeightPT1: 72.57 m; Height: 72.77 Pressure: 100454.00 Pa; T: 24.50 C
 HeightPT1: 72.60 m; Height: 72.94 Pressure: 100452.00 Pa; T: 24.50 C
 HeightPT1: 72.63 m; Height: 72.85 Pressure: 100453.00 Pa; T: 24.50 C
 HeightPT1: 72.65 m; Height: 72.85 Pressure: 100453.00 Pa; T: 24.51 C

22:18 3/8/17
Probe BMP280: Sensor found
 HeightPT1:  5.31 m; Height: 58.44 Pressure: 100625.00 Pa; T: 27.80 C
 HeightPT1: 10.11 m; Height: 58.11 Pressure: 100629.00 Pa; T: 27.85 C
 HeightPT1: 14.51 m; Height: 58.53 Pressure: 100624.00 Pa; T: 27.89 C


MP280 test 17.06 3/8/17 Adafruit library output (when SDO pulled to 3V3)
Temperature = 24.61 *C
Pressure = 100444.17 Pa
Approx altitude = 73.60 m

3/8/17 Adafruit library output (when SDO pulled to 3V3)
Temperature = 24.99 *C
Pressure = 100462.96 Pa
Approx altitude = 72.02 m

3/8/17 Adafruit library output (when SDO pulled to 3V3)
Temperature = 25.03 *C
Pressure = 100458.71 Pa
Approx altitude = 72.38 m

07:09 4/8/17 forecast pressure 1009mbar avg sea level pressure
Probe BMP280: Sensor found
 HeightPT1: 5.08 m; Height: 55.85 Pressure: 100656.00 Pa; T: 21.30 C
 HeightPT1: 9.68 m; Height: 55.68 Pressure: 100658.00 Pa; T: 21.36 C
 HeightPT1: 13.87 m; Height: 55.85 Pressure: 100656.00 Pa; T: 21.42 C

09:04 4/8/17
 HeightPT1: 49.79 m; Height: 49.57 Pressure: 100731.00 Pa; T: 22.46 C
 HeightPT1: 49.79 m; Height: 49.74 Pressure: 100729.00 Pa; T: 22.46 C
 HeightPT1: 49.80 m; Height: 49.91 Pressure: 100727.00 Pa; T: 22.45 C
 HeightPT1: 49.80 m; Height: 49.82 Pressure: 100728.00 Pa; T: 22.44 C

Different libraries give the same result

Here the adafruit library was given the actual forecast sea level pressure to get an altitude. I don't think it is too accurate because you have to have the actual ground level pressure value at your location. where I am is about 23m above sea level not 2m see the readings below!

The I2C Sensor library does not let you change the default value of 1013.25mb so you would need to go and write some code to allow accurate height measurement adjustment.

Different libraries Adafruit and I2C library (same result)

07:41 13/8/17 forecast pressure 1020mbar avg sea level pressure
I2C Sensor LIB: Probe BMP280: Sensor found
 HeightPT1: 1.82 m; Height: 20.03 Pressure: 101758.00 Pa; T: 23.27 C
 HeightPT1: 3.50 m; Height: 20.28 Pressure: 101755.00 Pa; T: 23.34 C
 HeightPT1: 5.01 m; Height: 20.12 Pressure: 101757.00 Pa; T: 23.33 C

07:42 13/8/17 Adafruit library  forecast pressure 1020mbar
Temperature = 23.70 *C
Pressure = 101755.11 Pa
Approx altitude = 20.27 m

Note: The I2C sensor library code averages the 1st 10 readings (see example 2 below) so the left hand values are not stable (until 10 values are gathered) the next measurement is the unaveraged height reading (20.03).

Interestingly there is a difference in temperature readings; Maybe one of the library code implementations is not right.

Warning: Getting a calibrated height using a predicted forecast pressure reading is not accurate as it will be slightly different at your location, so it is best to design code to store the value (when you are at ground level - by pressing a dedicated button, or gather the data on power up). Then use this value as the calibration value for measuring relative height from ground level.

Why your BMP280 won't start

If you're like me, and you have a breakout board without level shifters, and you create some using a few components (see the schematic on this page), to get I2C mode going, and then burn the example code into the Arduino uno r3. You then wonder why it's doing absolutely nothing!

As a typical engineer you give it a go and then - it's time to read the manual! - this is always a last resort unless there is a danger of blowing up a $800 component! In which case read the manual first.

It turns out that the communication mode of the BMP280 is set on power up by the state of various control inputs.

One "gotcha" is that an OUTPUT in SPI mode turns into an INPUT in I2C mode!

SPI mode uses more pins to define its interface and one of these unused the outputs (in SPI mode) is used as an input in I2C mode!. If you have a breakout board then these control inputs are left floating, meaning its just not going to work unless you set them before power up.

Warning: Holding any interface pin high while VDDIO is switched off will damage the chip due to current flow through protection diode. This could happen if you are designing a complex power management system where control pins are connected to the processor and power to the chip is controlled separately.

Conversely, if VDD is off and VDDIO is supplied, control pins at the chip are held at high-z (inactive).

IC2 Mode Selection

To get I2C mode going the Chip Select pin (CS) must be held at the VDDIO level as the BMP280 powers up.

If CS is held low during power up SPI mode is active.

I2C Address Selection

In addition to that the SDO pin (used as an output in SPI mode) is used as an input that selects one of two I2C addresses. This pin must be held low to get the lower address.

If you don't want to continuously change from high to low on SDO when changing which library you use just go into the Adafruit library (or I2C Sensor library) and change the BMP280_address from 0x77 to 0x76 (Adafruit library). The file is at:

C:\Users\<user name>\Documents\Arduino\libraries\Adafruit_BMP280_Library\Adafruit_BMP280.h

I2C pullups

SDI is a bi directional open drain pin and must have a pullup attached.

There is no need for a pullup on SCK as it is input; In I2C mode the device is only ever a slave and does not do clock stretching. I tested this using a resistor drop down (5V to 3V) using 1k connected to a 1k5 then to ground. With the SCK input connected to the top of the 1k5 - it works fine.

Note You can only do this if you use the BMP280 on its own since I2C requires pullups so that the bus can be released for other devices.

Note: The SDI and SCK pins are not true open drain pins and only SDI and SDO are implemented as bi-directional.

Table 29 in the datasheet (Pin description) shows what is going on:

bmp280 pins

Adafruit Library just won't go

I found that the ADAFruit BMP280 Library would just not work - the reason was that the SDO pin (used as an input in I2c mode) has been defaulted to 0x77 in software - that means the SDO pin needs to be pulled high (3V3 high) to work with this library (or change the default address in the library to 0x76).

I2C Address : For the BMP280

The device can be set to one of two I2C addresses, so you can have two separate pressure sensors on one I2C bus. The selection is made using the SDO pin as an input, and when low selects address 0x76, and when high selects address 0x77.

BMP280 Datasheet

Click here to download the datasheet

Software Library and versions

Arduino IDE Version

Version : 1.6.4

Bosch BMP280 sensor Libraries:

The libraries used are:

  • Adafruit BMP280 Library 1.0.2
  • I2C-Sensor-Lib Ver 0.8.2

...both can easily installed from the Arduino IDE.

If you do not see the library as an entry when you click the menus:

Sketch-->Include Library

Then select manage libraries :

Sketch-->Include Library -->Manage Libraries...

Search for and install <lib name> using the "Filter Your Search" form.

Code size results from libraries used:

For the simple example code used there is a large difference in code use as shown below.

The Adafruit BMP280 uses 1334 bytes more than I2C Sensor Lib - this is something to note if you are running out of code space.

Code use I2C-Sensor-Lib Lbrary:
Sketch uses 8,830 bytes (27%) of program storage space. Maximum is 32,256 bytes.
Global variables use 563 bytes (27%) of dynamic memory, leaving 1,485 bytes for local variables.

Code use Adafruit BMP280 Lbrary:
Sketch uses 10,164 bytes (31%) of program storage space. Maximum is 32,256 bytes.
Global variables use 563 bytes (27%) of dynamic memory, leaving 1,485 bytes for local variable

Differences between the libraries

The adafruit BMP280 library comes with a member function (or method) that allows entry of the sea level altitude and returns the altitude based on this value and your current barometric reading (See example 1 below). This is a sparse library and does not give any other methods to control the register settings within the device.

On the other hand I2C Sensor lib does have methods to set the internal parameters of the device but does not have a sea level altitude correction function. You really need a corrector adjustment to get more accurate altitude. The code below shows you how to udate the library to allow entry of the sea level pressure reading.

Adding a method to the I2C Sensor lib

This requires a simple addition to the library file:

  • C:\Users\<username>\Documents\Arduino\libraries\I2C-Sensor-Lib_iLib\src\i2c_BMP280.h

Find the top method     

"voidgetAltitude(float&meter)"

...and add in the one shown below:

"voidgetAltitude(float&meter,floatseaLevelmbar)"

/**<  gives the number of meters above sea level */
    void getAltitude(float& meter)
    {
        uint32_t iPascal;
        getPressure(iPascal);

        meter = 44330.0*(1-pow(float(iPascal)/101325.0,1.0/5.255));

    };

    /**<  gives the number of meters above sea level. JFM parameterised sea level*/
    void getAltitude(float& meter,float seaLevelmbar)
    {
        uint32_t iPascal;
        getPressure(iPascal);

        meter = 44330.0*(1-pow(float(iPascal)/(seaLevelmbar*100),1.0/5.255));

    };

This just adds a public method that allows the sea level pressure (forecast) to be entered instead of the default 1013.25mbar value which gives a more accurate height reading.

Example 1 Adafruit Library : BMP280

The 1st arduino example sketch. This example uses the "Adafruit BMP280" Library.

Click in the code below to copy it to theclipboard.

/***************************************************************************
  This is a library for the BMP280 humidity, temperature & pressure sensor

  Designed specifically to work with the Adafruit BMEP280 Breakout
  ----> http://www.adafruit.com/products/2651

  These sensors use I2C or SPI to communicate, 2 or 4 pins are required
  to interface.

  Adafruit invests time and resources providing this open source code,
  please support Adafruit andopen-source hardware by purchasing products
  from Adafruit!

  Written by Limor Fried & Kevin Townsend for Adafruit Industries.
  BSD license, all text above must be included in any redistribution
 ***************************************************************************/

#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP280.h>

#define BMP_SCK 13
#define BMP_MISO 12
#define BMP_MOSI 11
#define BMP_CS 10

Adafruit_BMP280 bme; // I2C
//Adafruit_BMP280 bme(BMP_CS); // hardware SPI
//Adafruit_BMP280 bme(BMP_CS, BMP_MOSI, BMP_MISO,  BMP_SCK);

void setup() {
  Serial.begin(9600);
  Serial.println(F("BMP280 test"));

  if (!bme.begin()) {
    Serial.println("Could not find a valid BMP280 sensor, check wiring!");
    while (1);
  }
}

void loop() {
    Serial.print("Temperature = ");
    Serial.print(bme.readTemperature());
    Serial.println(" *C");

    Serial.print("Pressure = ");
    Serial.print(bme.readPressure());
    Serial.println(" Pa");

    Serial.print("Approx altitude = ");
    Serial.print(bme.readAltitude(1018.00)); // this should be adjusted to your local forcast
    Serial.println(" m");

    Serial.println();
    delay(2000);
}

Example 2 - I2C Lib : BMP280

The 2nd arduino example sketch. This exampe uses the "I2C-Sensor-Lib" library.

Note this example requires the additional method shown above for accurate altitude which is not included in the original bmp280 arduino library (instructions for adding it are here):

voidgetAltitude(float&meter,floatseaLevelmbar).

#include <Wire.h>
#include "i2c.h"

#include "i2c_BMP280.h"
BMP280 bmp280;

void setup()
{
    Serial.begin(9600);

    Serial.print("I2C Sensor LIB: Probe BMP280: ");
    if (bmp280.initialize()) Serial.println("Sensor found");
    else
    {
        Serial.println("Sensor missing");
        while (1) {}
    }

    // onetime-measure:
    bmp280.setEnabled(0);
    bmp280.triggerMeasurement();
}

void loop()
{
    bmp280.awaitMeasurement();

    float temperature;
    bmp280.getTemperature(temperature);

    float pascal;
    bmp280.getPressure(pascal);

    static float meters, metersold;
//    bmp280.getAltitude(meters);
    bmp280.getAltitude(meters,1018.00); // Allow entry of forecast sea level pressure JFM
    metersold = (metersold * 10 + meters)/11;

    bmp280.triggerMeasurement();

    Serial.print(" HeightPT1: ");
    Serial.print(metersold);
    Serial.print(" m; Height: ");
    Serial.print(meters);
    Serial.print(" Pressure: ");
    Serial.print(pascal);
    Serial.print(" Pa; T: ");
    Serial.print(temperature);
    Serial.println(" C");

    delay(120);

}



Ideas for using Altitude Sensors

A table in the datasheet repeated below gives an indication of how to setup the device for different applications which range from indoor navigation (can't use the GPS here as there is no signal indoors- it would also require accelerometer and perhaps a gyroscope chip, for dead reckoning movement detection). Other usage ideas are: Drop detection. Elevator floor change detection, Weather monitoring (e.g. Arduino barometric pressure monitor : lowest power setting), Use in a mobile phone.

bmp280 interesting use cases

Source: Datasheet Table 7: Recommends filter settings based on use cases.

Note ODR is Typical Output Data Rate i.e. the maximum you can read the device for the given settings.

What's the IIR filter for?

The BMP280 chip has a built in Infinite Impulse Response filter (which is a type of DSP filter) that is useful for improving the output result from the sensor (or ignoring short term changes). For instance if using the sensor indoors, the sensor is so fast and sensitive that any small pressure change will be recorded e.g. the slamming of a door.

Using the IIR is a trade off between sensor response time and the need to ignore short term changes in pressure - outside you would not need to use the IIR filter since there won't be any doors slamming to cause sudden pressure changes (see Weather monitoring/Indoor Navigation in the table above (IIR=0)). For drop detection the situation is the opposite to indoor navigation use - you want to detect sudden pressure changes for instant height change detection.

For indoor navigation use you can setup the BMP280 so that small changes are ignored by setting appropriate values for the IIR filter - that would be the maximum value i.e. 16 - see table above (Indoor Navigation and hand held dynamic device).

Update rate vs oversampling

Oversampling is simply how many times the device reads a sensor and averages out the result and then allows you to read it. The more oversampling that you set up the more time it takes for a reading to become available.

The table below (table 14 - again from the datasheet) shows the relationship between a specific standby time (that you can control: t_sb) versus the oversampling setting (ovsr_p and ovsr_t). For the above settings table 7 shows that the oversampling setting is "Standard resolution" so you can set t_sb to 0.5 and read the device at 83.33Hz i.e. the table below tells you the maximum achievable output rate for the given settings.

BMP280 sample rate vs oversampling setting

Example 3 Height Change Code

I have this odd idea that I want to find out the speed of the lift in the local sports center, and this device is the ideal tool to measure height changes and rate of height change. To do this you need to setup the BMP280 for elevator floor detection (see table 7 above) - actually drop detection provides more data and an ODF of 125Hz - you can average out the data by processing..

Library code that can be found at:

  • C:\Users\<username>\Documents\Arduino\libraries\Adafruit_BMP280_Library
  • C:\Users\<username>\Documents\Arduino\libraries\I2C-Sensor-Lib_iLib

Currently in the Adaftuit Library software the Control register that sets the mode is fixed with no provision for re-programming it (within method: begin. Its value is set to 3F). For that reason the following code uses the I2C Sensor library as this has a few more functions that allow changing the mode of the BMP280 (see i2c_BMP280.h).

For elevator movement detection you need the following setup:

Drop detection
Description parameter Value I2C library method
Pressure oversampling osrs_p x2 setPressureOversampleRatio
Temperatuure oversampling osrs_t x1 setTemperatureOversampleRatio
IIR IIR 0 setFilterRatio
Standby time t_sb 0 = 0.5ms setStandby

I selected a standby time as '0' for a fast update rate form the sensor. It may need to be adjusted for your code i.e. increase standby to reduce power consumption.

#include <Wire.h>
#include "i2c.h"

#include "i2c_BMP280.h"
BMP280 bmp280;

void setup()
{
    Serial.begin(115200);
    Serial.println("BMP280 elevator");
    Serial.print("Probe BMP280: ");
    if (bmp280.initialize()) Serial.println("Sensor found");
    else
    {
        Serial.println("Sensor missing");
        while (1) {}
    }

    // Setup for elevator floor change measurement.
    bmp280.setPressureOversampleRatio(2);
    bmp280.setTemperatureOversampleRatio(1);
    bmp280.setFilterRatio(0);
    bmp280.setStandby(0);

    // onetime-measure:
    bmp280.setEnabled(0);
    bmp280.triggerMeasurement();
}

float get_altitude() {
   float meters;
   bmp280.getTemperature(meters);  // throw away - needed for alt.
   bmp280.getPressure(meters);     // throw away - needed for alt.
   bmp280.getAltitude(meters);
   return meters;
}

void loop()
{
    float distance,velocity;
    static uint32_t time_now, time_was=millis(),dt;
    static float alt_was=get_altitude();
    static uint32_t sample_time_was=millis();
    static uint32_t readings=0;
    static float values=0,avg_alt=0;
    static float meters;

    if ( (millis()-sample_time_was) >2) { // read at a specific rate.

       if(!bmp280.awaitMeasurement()) Serial.println("MEASURE FAILED");

       meters = get_altitude();
       readings++;
       values += meters;

       bmp280.triggerMeasurement();

       sample_time_was = millis();
    }

//     // Serial plotter
//     Serial.print(meters);
//     Serial.print(" ");
//     Serial.println(metersoldn);

    time_now = millis();
    dt = time_now - time_was;
    if (dt>=1000) {

       avg_alt = values/readings;
       distance = avg_alt - alt_was;
       velocity = (distance/((float)dt/1000.0));
       alt_was  = avg_alt;
       time_was = time_now;

//    Serial.print("AVG: ");
//    Serial.print(avg_alt);
//    Serial.print(" m/s ; dist: ");
//    Serial.print(distance);

    if (fabs(velocity)>0.2) {
       Serial.print("Velocity: ");
       Serial.print(velocity);
       Serial.print(" m/s ;");
    }
    Serial.print("debug: ");
    Serial.println(readings);


    values=0;
    readings=0;
    }

}



Now you can use the BMP280 for more than just weather monitoring!

This is the typical output you get when lifting or lowering the sensor (using the serial monitor in the IDE).

Note the 76 value is as fast as you can go round the loop. In theory the sample rate should be set to 8 since the max you should go at is 125Hz so the sample rate should be 1/125=8ms. Then the repeat data rate in 1 sec would be 125 but the code is only capable of going at 76 in a sec. This will be due to using floats and serial output - think about using fixed point and it will go faster. The question is do you need it to go faster = design decision (the library would have to be re-written as well!).

You can see that increases in height result in positive values while decreases in height result in negative values and anything below 0.2m is ignored. The output below is obtained just from moving the sensor ~30cm up and down at a desk so it is very sensitive and ideal for height change detection (building navigation).

BMP280 elevator
Probe BMP280: Sensor found
Velocity: -3812.96 m/s ;debug: 73
Velocity: -0.31 m/s ;debug: 76
debug: 76
debug: 76
debug: 76
debug: 76
Velocity: 0.32 m/s ;debug: 76
Velocity: 0.24 m/s ;debug: 76
debug: 76
debug: 76
debug: 76
debug: 76
Velocity: 0.54 m/s ;debug: 76
debug: 76
Velocity: -0.47 m/s ;debug: 76
debug: 76
debug: 76
Velocity: 0.35 m/s ;debug: 76
debug: 76
Velocity: -0.20 m/s ;debug: 76
Velocity: -0.28 m/s ;debug: 76
Velocity: 0.27 m/s ;debug: 76
debug: 76
debug: 76
Velocity: -0.45 m/s ;debug: 76
debug: 76
debug: 76
debug: 76

The above code is only a first go at obtaining velocity. You should change it to get a reading every second using either "indoor navigation" or "handheld device" BMP280 modes and stop using the complete data set for averaging i.e. rely on the internal modes of the BMP280. Then display velocity based on height changes from one sample to the next at 1 sec intervals. In a handheld device you would want to save power and also do other tasks! Probably you would need a sample rate greater than 1 second so as not to miss slow changes;.

Other ideas for use of Altitude Sensors : BMP280

The BMP280 could be used in a drone for measuring height e.g. for building mapping (or just to figure out how high something is - given that the device seems fairly accurate (approx. 30cm). The stated relative accuracy seems a bit pessimistic at ±0.12hPa ( ±0.12mbar) for a ±1m resolution and in practice seems a lot better than this (although where you need to claim accuracy you would have to state that the measurement is ±1m).

The results in the Serial Monitor output (above) show that the device is capable of detecting a 30cm change in height (for this specific device).

New! Comments

Have your say about what you just read! Leave me a comment in the box below.




Privacy Policy | Contact | About Me

Site Map | Terms of Use



Visit our Facebook Page:

   Click Here



Recent Articles

  1. Arduino Battery Charger: How to save the planet one battery at a time; Recycle and re-use Alkaline battries

    Arduino Battery Charger: A very useful project that lets you charge 'un-rechargeable' alkaline batteries!

    Read more

  2. [Arduino Tutorial] : How to use the 74HC595 shift register.

    The Essential Guide to the 74HC595; What it is and how you can easily use one in any of your projects.

    Read more

  3. How to use the MCP23017 I/O Expander on the Arduino

    How to use the MCP23017 to increase your I/O by 16 pins (or more) and use its interrupt system.

    Read more

Sign up for MicroZine
''The'' Microcontroller Newsletter

Enter your first Name and primary email address in the form below:


And receive absolutely FREE a full project for:

"Measuring Analogue Voltages
Without An ADC"

(Using only one pin).

Instant Download:
You Can
Get It Right Now

Warning: This project could be  Removed 
at any time.  

It will  NOT be 
available indefinitely SO
To avoid 
disappointment  get it:

Now



:
:
Don't worry -- your e-mail address is totally secure. I promise to use it only to send you MicroZine
Remember this is a project with full description and fully debugged C Source code - and it's not available from the main website.

You can only get it through this newsletter.

To get exclusive access Enter your first name Name and primary email address Now in the form above.:



But wait !

There's more...

You'll receive more
free and exclusive reports as well as site information and site product updates


Scroll up to the form above and sign up NOW. Don't forget it's FREE and if you don't like it, you can unsubscribe at any time.

Click Here Now to use the form above to get your Valuable information absolutely free.



Readers Comments

"I wanted to thank
you so so so much
for all the information
you have provided in
your site it's

SUPERB and FANTASTIC."

- Ranish Pottath

"This site really is
the best and my favorite.
I find here many useful
projects and tips."

- Milan

bursach<at>gmail.com<

"Awesome site,
very, very easy and nice
to navigate!"


- Matt
matt_tr<at>
wolf359.cjb.net


Learn Microcontrollers

"Interested in
Microcontrollers?"

Sign up for The
Free 7 day guide:

FREE GUIDE : CLICK HERE


"I am a newbie to PIC
and I wanted to say
 how great your
site has been for me."


- Dave

de_scott<at>bellsouth.net

"Your site is a great
and perfect work.
congratulations."


- Suresh

integratredinfosys<at>
yahoo.com

"I couldn't find the correct
words to define
yourweb site.

Very useful, uncovered,
honest and clear.

Thanks so much for
your time and works.
Regards."


- Anon

Back to Top