Arduino library 路 Sensors

Adafruit BMP280: pressure and altitude on I2C

The BMP280 is Bosch鈥檚 barometric pressure and temperature sensor, the cheaper sibling of the BME280 without the humidity part. The Adafruit BMP280 library reads it over I2C and turns the chip鈥檚 compensated values into floats: degrees Celsius, pascals, and an altitude worked out from the pressure.

Built in on Mokxi: #include <Adafruit_BMP280.h> and it builds, with nothing to install. Free, and no account needed.

What Adafruit BMP280 Library does

The address catches almost everyone. The library looks at 0x77 unless told otherwise, which is where Adafruit鈥檚 own board sits, while most blue and purple GY-BMP280 modules answer at 0x76. Pass the address to begin() and that problem goes away.

Altitude from a barometer is only as good as the sea-level pressure you compare against. readAltitude(1013.25) uses the standard atmosphere, which can be tens of meters off on a given day; use your local weather report鈥檚 sea-level pressure in hectopascals for a better answer, or track changes in altitude rather than the absolute number.

Library Manager nameAdafruit BMP280 Library
AuthorAdafruit
Include#include <Adafruit_BMP280.h>
Boardsevery board Mokxi compiles for but ATtiny85
In the simulatorSimulated: it runs against the part the way it does on the bench.
Parts it drivesPressure and temperature, BMP280

Install it

It builds on every board Mokxi compiles for but ATtiny85.

In Mokxi it is built in: #include <Adafruit_BMP280.h> and the sketch compiles, with no download, no zip and no Library Manager.

On a real board, install "Adafruit BMP280 Library" by Adafruit from the Arduino IDE鈥檚 Library Manager (Sketch, Include Library, Manage Libraries), or add Adafruit BMP280 Library to lib_deps in PlatformIO. Mokxi follows the calls of release 2.6.8, so a sketch written here builds there too.

What to know in the simulator: The SPI constructors build, and begin() says on Serial that the SPI module is not simulated: Mokxi鈥檚 BMP280 is the I2C module.

ESP32-C3 路 Arduino Uno 路 Arduino Nano 路 Arduino Mega 2560 路 Arduino Leonardo 路 SparkFun Pro Micro 路 Arduino Micro 路 ESP32-C6 路 Raspberry Pi Pico 路 Raspberry Pi Pico W 路 Seeed XIAO SAMD21 路 STM32 路 STM32 Nucleo-F411RE 路 STM32 Blue Pill 路 micro:bit V2 路 Arduino Uno R4 路 ESP32 DevKit 路 ESP32-S3-DevKitC-1 路 ESP8266 NodeMCU 路 Arduino Pro Mini 3.3 V 路 Seeed XIAO ESP32-C3 路 ESP32-C3 SuperMini 路 Seeed XIAO ESP32-C6 路 ESP32-DevKitC V4 路 LOLIN32 Lite 路 Wemos D1 R32 路 Cheap Yellow Display 路 TTGO T-Display 路 Seeed XIAO ESP32-S3 路 Arduino Nano ESP32 路 Arduino Nano RP2040 Connect 路 Seeed XIAO RP2040 路 Waveshare RP2040-Zero 路 Arduino Uno R4 WiFi

The calls you will use

In the order a sketch meets them.

Adafruit_BMP280 bmp

Creates the sensor on the Wire bus.

bmp.begin(0x76)

Starts the sensor at the given address and checks the chip ID. Returns false when nothing suitable answers. Without an argument it tries 0x77.

if (!bmp.begin(0x76)) {
  Serial.println(F("Could not find a valid BMP280 sensor"));
  while (1) delay(10);
}

bmp.readTemperature()

Temperature in degrees Celsius.

bmp.readPressure()

Pressure in pascals. Divide by 100 for hectopascals (millibars).

bmp.readAltitude(1013.25)

Altitude in meters, against the sea-level pressure you pass in hectopascals.

bmp.setSampling(Adafruit_BMP280::MODE_NORMAL, Adafruit_BMP280::SAMPLING_X2, Adafruit_BMP280::SAMPLING_X16, Adafruit_BMP280::FILTER_X16, Adafruit_BMP280::STANDBY_MS_500)

Sets the mode, the temperature and pressure oversampling, the IIR filter and the standby time, as the library鈥檚 example does.

bmp.sensorID()

The chip ID the board reported: 0x58 for a BMP280, 0x60 for a BME280.

Example: Rocket flight computer

On the Arduino Uno R3. It runs in the browser exactly as printed.

sketch.ino 路 Arduino Uno R3
// Model rocket flight computer: altitude, acceleration, a log and a parachute.
//
//   A4, A5       BMP280 at 0x76 and MPU6050 at 0x68, sharing one I2C bus
//   10 11 12 13  microSD module: CS, MOSI, MISO, SCK
//   A0           deploy servo: it holds the parachute door shut until apogee
//   pin 7        active buzzer
//   pin 4        green lamp: ready, and solid while armed
//   pin 5        amber lamp: in flight, flashing once the chute is out
//   pin 6        red lamp: a fault
//   pin 2        ARM button: hold it for a second to arm or disarm
//   pin 3        BENCH button: fly a simulated flight through the same code
//
// # The flight, as a state machine
//
//   IDLE -> ARMED -> BOOST -> COAST -> APOGEE -> DESCENT -> LANDED
//
// Each state looks for exactly one thing. Armed waits for launch, boost waits
// for the motor to burn out, coast waits for the top, and nothing skips ahead.
// That is what keeps a flight computer predictable.
//
// # Launch
//
// The MPU6050 runs on its 16 g range, and launch is three readings in a row
// over 2.5 g. A barometric backup counts too: ten meters above the pad. In
// Mokxi the IMU part reads gravity through its tilt and nothing else, so on
// the canvas it is the pressure slider that flies the rocket.
//
// # Apogee, and why it is filtered
//
// A barometer is noisy, and at the top of a flight the rocket is barely
// moving, so one low reading would look like the way down. The altitude goes
// through an exponential filter, the climb rate is worked out from the
// filtered altitude and filtered again, and apogee needs all three of these:
// a second since launch, the filtered altitude 1.5 m under its highest, and
// the climb rate below zero three samples in a row.
//
// # Whole numbers
//
// An Uno has no floating point hardware, and the SD library alone is a third
// of its flash. So altitude is kept in centimeters, the climb rate in cm/s and
// acceleration in thousandths of a g, all in plain integers.
//
// # Try it
//
// Press Run and watch the self-test. Hold ARM for a second. Then drag the
// BMP280's pressure slider down about 2 hPa (roughly 17 m of climb) and back
// up again. Or press BENCH: a simulated flight, made-up numbers clearly
// marked, flown through exactly the same code. Every sample goes into
// FLIGHT.CSV on the card; click it in the card's file list to download it.
//
// Real rocketry: fly certified motors, follow your national association's
// safety code, and ground test every recovery system before it flies.

#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <Servo.h>
#include <Adafruit_BMP280.h>

const int PIN_ARM = 2;
const int PIN_BENCH = 3;
const int PIN_GREEN = 4;
const int PIN_AMBER = 5;
const int PIN_RED = 6;
const int PIN_BUZZER = 7;
const int PIN_DEPLOY = A0;
const int PIN_CARD = 10;

const uint8_t MPU_ADDRESS = 0x68;
const int LOCKED_DEG = 0;     // the door held shut
const int DEPLOY_DEG = 90;    // the door let go

const unsigned long SAMPLE_MS = 50;       // 20 samples a second
const long LAUNCH_MG = 2500;
const long BACKUP_LAUNCH_CM = 1000;
const long BURNOUT_MG = 1500;
const long APOGEE_DROP_CM = 150;
const unsigned long APOGEE_LOCKOUT_MS = 1000;
const long LANDED_BELOW_CM = 3000;

enum State { IDLE, ARMED, BOOST, COAST, APOGEE, DESCENT, LANDED };
const char *const NAMES[] = {"IDLE", "ARMED", "BOOST", "COAST", "APOGEE", "DESCENT", "LANDED"};

Adafruit_BMP280 baro;
Servo deploy;
File logFile;

bool haveBaro = false;
bool haveImu = false;
bool haveCard = false;

State state = IDLE;
bool bench = false;            // flying the simulated flight
unsigned long stateAt = 0;
unsigned long launchAt = 0;
unsigned long sampleAt = 0;
unsigned long flyAt = 0;           // when fly() last ran, for the climb rate
unsigned long printAt = 0;
unsigned long flushAt = 0;
unsigned long chirpAt = 0;
unsigned long stillSince = 0;
int armHeld = 0;
bool armLatched = false;
bool benchWas = HIGH;

long padCm = 0;                // the pad's altitude above sea level
long altCm = 0;                // filtered height above the pad
long velCms = 0;               // filtered climb rate
long maxCm = 0;
long accelMg = 1000;
long tiltCos = 1000;           // how vertical the board is, 1000 = straight up
int launchCount = 0;
int burnoutCount = 0;
int fallingCount = 0;

// The simulated flight: one second of motor, then gravity, then a chute.
long simCm = 0;
long simCms = 0;
unsigned long simAt = 0;
bool deployed = false;

// --- the buzzer, without blocking ----------------------------------------------

int beepSteps[20];             // ms, alternating on and off
int beepCount = 0;
int beepIndex = 0;
unsigned long beepAt = 0;

void beep(const int *steps, int count) {
  beepCount = count < 20 ? count : 20;
  for (int i = 0; i < beepCount; i++) beepSteps[i] = steps[i];
  beepIndex = 0;
  beepAt = millis();
  digitalWrite(PIN_BUZZER, HIGH);
}

void serviceBuzzer() {
  if (beepIndex >= beepCount) {
    digitalWrite(PIN_BUZZER, LOW);
    return;

The sketch is cut short here; the editor has every line of it.

Open it in the editor, wired and ready to run 路 Rocket flight computer: the project page

Common errors and how to fix them

Could not find a valid BMP280 sensor, check wiring!

Try begin(0x76): most modules are not at the library鈥檚 default 0x77. If the address is right, check SDA and SCL, and print sensorID(), since a board sold as BMP280 may carry a BME280 or another chip.

Altitude is off by tens of meters

readAltitude() needs today鈥檚 sea-level pressure. Replace 1013.25 with the value from a local weather report, in hectopascals, or measure the change from where you started.

Pressure reads about 100000 and you expected about 1000

readPressure() is in pascals. Divide by 100 to get hectopascals or millibars, the unit weather reports use.

Try Adafruit BMP280 Library without installing anything

Open the example, change the sketch, and keep your version in a free account.