The Arduino BMP390 pressure sensor from Bosch Sensortec represents a significant leap over older BMP280/BMP388 devices, offering lower noise, a built-in FIFO buffer, and an interrupt engine that makes ultra-low-power altitude logging possible. Whether you are building a weather station, an altimeter for a high-power rocket, or a pressure-compensated diving computer, this guide covers the BMP390 from first connection all the way to advanced FIFO streaming and weather trend detection — all on Arduino.
Table of Contents
- BMP390 Overview and Improvements Over BMP280
- Wiring BMP390 to Arduino
- First Sketch: Pressure and Temperature
- Altitude Calculation and Sea-Level Calibration
- FIFO Buffer and Interrupt-Driven Logging
- Weather Trend Detection Algorithm
- Low-Power Sleep Modes
- Frequently Asked Questions
BMP390 Overview and Improvements Over BMP280
Bosch released the BMP390 as a drop-in performance upgrade over the BMP388, with the same footprint but a 60% lower noise floor. The key specifications:
- Pressure range: 300–1250 hPa
- Pressure noise: 0.02 Pa RMS (equivalent to 1.7 cm altitude resolution)
- Temperature range: −40°C to +85°C
- Interfaces: I2C (up to 3.4 MHz) and SPI (up to 10 MHz)
- FIFO: 512-byte buffer, up to 200 frames
- Current draw: 3.4 µA at 1 Hz normal mode, 2 µA in forced mode
- Supply voltage: 1.65–3.6 V (use a level shifter or 3.3 V module with Arduino 5 V)
Compared to the BMP280, the BMP390 adds a hardware FIFO, a watermark interrupt, and improved temperature compensation — making it dramatically better for battery-powered applications where you want the MCU to sleep while the sensor collects data.
Wiring BMP390 to Arduino
Most BMP390 breakout boards operate at 3.3 V. Use the I2C interface for simplicity:
| BMP390 Pin | Arduino Uno | Arduino Nano 33 IoT |
|---|---|---|
| VDD | 3.3 V | 3.3 V |
| GND | GND | GND |
| SCK/SCL | A5 (via 3.3 V divider) | A5 (3.3 V native) |
| SDI/SDA | A4 (via 3.3 V divider) | A4 (3.3 V native) |
| INT | D2 (optional) | D2 (optional) |
Important: The BMP390 is NOT 5 V tolerant on its I/O pins. When using an Arduino Uno, either use a module with an onboard level shifter, or build a simple voltage divider (10 kΩ + 20 kΩ) on SCL and SDA. The Arduino Nano 33 IoT runs at 3.3 V natively and is the preferred pairing.
First Sketch: Pressure and Temperature
Install the Adafruit BMP3XX library from Library Manager (search “BMP390” or “BMP3XX”). It supports both BMP388 and BMP390.
#include <Wire.h>
#include "Adafruit_BMP3XX.h"
#define SEALEVELPRESSURE_HPA 1013.25
Adafruit_BMP3XX bmp;
void setup() {
Serial.begin(115200);
if (!bmp.begin_I2C()) {
Serial.println("BMP390 not found. Check wiring!");
while (1);
}
// Oversample for lower noise
bmp.setTemperatureOversampling(BMP3_OVERSAMPLING_8X);
bmp.setPressureOversampling(BMP3_OVERSAMPLING_4X);
bmp.setIIRFilterCoeff(BMP3_IIR_FILTER_COEFF_3);
bmp.setOutputDataRate(BMP3_ODR_50_HZ);
}
void loop() {
if (!bmp.performReading()) {
Serial.println("Failed to perform reading!");
return;
}
Serial.print("Pressure: "); Serial.print(bmp.pressure / 100.0); Serial.println(" hPa");
Serial.print("Temperature: "); Serial.print(bmp.temperature); Serial.println(" °C");
Serial.print("Altitude: "); Serial.print(bmp.readAltitude(SEALEVELPRESSURE_HPA)); Serial.println(" m");
delay(2000);
}
Altitude Calculation and Sea-Level Calibration
The BMP390 converts pressure to altitude using the International Standard Atmosphere (ISA) model:
Altitude = 44330 × [1 − (P / P₀)^(1/5.255)]
The critical variable is P₀ — the sea-level reference pressure. The ISA default of 1013.25 hPa is only accurate on a standard day. For best results, use the current QNH from a nearby weather station:
- Look up your city’s current QNH on Windy.com or the Indian Meteorological Department website.
- Enter it as
SEALEVELPRESSURE_HPAin your sketch. - Altitude accuracy improves from ±30 m (ISA default) to ±3 m (correct QNH).
For applications like hiking altimeters where you know your starting elevation precisely, use the known-altitude calibration method: measure pressure at a known altitude point, then back-calculate P₀ so the formula returns that altitude. This eliminates weather-related drift entirely for relative altitude measurements (e.g., elevation gain during a trek).
FIFO Buffer and Interrupt-Driven Logging
The BMP390’s 512-byte FIFO is its killer feature for data logging. Instead of waking the MCU every sample, you configure the sensor to collect data autonomously and fire an interrupt when the buffer is half full:
// Enable FIFO — store pressure + temperature frames
bmp.setFIFOEnabled(true);
bmp.setFIFOTemperatureEnabled(true);
bmp.setFIFOPressureEnabled(true);
bmp.setFIFOWatermark(50); // Fire INT when 50 frames collected
// In interrupt handler:
void IRAM_ATTR onFIFOInt() {
fifoReady = true;
}
// Main loop reads burst:
if (fifoReady) {
fifoReady = false;
uint8_t frameCount = bmp.getFIFOFrameCount();
for (uint8_t i = 0; i < frameCount; i++) {
bmp.readFIFOFrame(); // populates bmp.pressure, bmp.temperature
// Write to SD card or Serial
}
}
This approach lets the MCU sleep in deep-sleep between FIFO events. At 1 Hz ODR with a 50-frame watermark, the MCU only wakes up once every 50 seconds — dramatically extending battery life in field loggers.
Weather Trend Detection Algorithm
Barometric pressure trend over 3 hours is the traditional basis of short-term weather forecasting. Here is a simple rule-based algorithm you can implement on Arduino:
- Rising fast (>+2 hPa/3h): Clearing, fair weather incoming.
- Rising slowly (+0.5 to +2 hPa/3h): Settled weather.
- Steady (±0.5 hPa/3h): No significant change.
- Falling slowly (−0.5 to −2 hPa/3h): Clouds, possible rain.
- Falling fast (>−2 hPa/3h): Storm approaching.
Store a circular buffer of 180 pressure readings (one per minute) and compare the most recent reading with the one 180 minutes ago. This gives you a rolling 3-hour trend without needing real-time clock precision beyond ±1 minute.
const int WINDOW = 180; // 3 hours at 1/minute
float pressureLog[WINDOW];
int logIndex = 0;
// Called every minute:
pressureLog[logIndex % WINDOW] = bmp.pressure / 100.0;
float trend = pressureLog[logIndex % WINDOW]
- pressureLog[(logIndex + 1) % WINDOW];
logIndex++;
// Positive trend = rising; negative = falling
Low-Power Sleep Modes
The BMP390’s forced mode is designed for maximum power savings: the sensor takes one measurement, returns to sleep, and waits for the next command. Combine this with Arduino deep sleep:
- Use forced mode (
BMP3_POWERMODE_FORCED) instead of normal mode. - Trigger a measurement every 60 seconds using a WDT or RTC alarm.
- Read the result, then put the MCU back to sleep.
- Total system current in sleep: ~6 µA (BMP390 sleep 2 µA + MCU sleep 4 µA on ATmega328P).
A 1000 mAh LiPo cell can power this combination for over 2 years in the field — sufficient for a standalone weather station on a mountain hike route that uploads data via LoRa once per day.
Frequently Asked Questions
Is the BMP390 better than BMP280 for altitude measurement?
Yes, significantly. The BMP390 has roughly 60% lower noise (0.02 Pa vs 0.05 Pa), which translates to about 3× better altitude resolution — 1.7 cm vs 5 cm. It also has hardware FIFO and interrupts that BMP280 lacks. For serious altimeter builds (rockets, drones, hiking), BMP390 is worth the slightly higher cost.
Can BMP390 measure water depth?
Theoretically yes, since pressure increases by ~1 hPa per cm of water depth. However, the BMP390 is not waterproof. You must encase it in silicone or use a sealed stainless-steel pressure port. For diving applications, a dedicated waterproof pressure transducer rated for the required depth is a safer choice.
What is the difference between BMP388 and BMP390?
The BMP390 is a refined version of BMP388 with 60% lower pressure noise and improved long-term stability. The register map, pinout, and library API are identical. If you have BMP388 code, it works on BMP390 without changes.
How do I use BMP390 over SPI instead of I2C?
Pull the CSB pin low (connect to 3.3 V to enable I2C; connect to a GPIO chip-select pin for SPI). In the Adafruit library, call bmp.begin_SPI(CS_PIN) instead of begin_I2C(). SPI at 10 MHz is faster and noise-immune over longer cable runs compared to I2C.
Why does my altitude reading drift over time?
Ambient temperature changes cause pressure drift of about 0.25 hPa/°C, which translates to roughly 2 m/°C of altitude drift. Always use the IIR filter (BMP3_IIR_FILTER_COEFF_3 or higher) and consider temperature compensation if the sensor is mounted in a location with large temperature swings.
The Arduino BMP390 pressure sensor is the most capable barometric sensor available for maker projects today. Its FIFO engine, ultra-low noise, and flexible power modes make it ideal for everything from indoor weather stations to high-altitude rocket data loggers. Shop our full collection of Arduino sensors and modules at Zbotic to find the right components for your next build.
Add comment