| Crates.io | bmp390-rs |
| lib.rs | bmp390-rs |
| version | 0.4.0 |
| created_at | 2025-08-21 08:12:36.711514+00 |
| updated_at | 2025-08-31 08:19:44.397329+00 |
| description | Async driver for the BMP390 pressure sensor that supports both I2C and SPI |
| homepage | |
| repository | https://github.com/EmilNorden/bmp390-rs |
| max_upload_size | |
| id | 1804432 |
| size | 201,439 |
This crate provides a platform-agnostic async driver for the Bosch BMP390 pressure (and temperature!) sensor using the embedded-hal-async traits.
The BMP390 device supports both I2C and SPI communication, and this driver does as well.
Feedback or contributions to this crate is highly welcome.
no_std + embedded-hal-async supportread::<regs::...>() / write::<regs::...>() for those who cant stay away.uom feature.The Bosch BMP390 is a pressure sensor with an accuracy of ±3 Pascal, equivalent to 0.25m altitude.
Add this crate as a dependency in your Cargo.toml:
[dependencies]
bmp390-rs = "0.4"
This driver provides two different interfaces: The core interface and the typestate interface
Direct, typed access to the chip’s registers—plus ergonomic helpers. Great when you want full control.
use bmp390_rs::{Bmp390, config::Configuration, register};
// Connect via SPI. Use Bmp390::new_i2c for I2C.
let mut device = Bmp390::new_spi(spi_device, Configuration::default(), &mut delay).await?
// Read pressure/temperature data
let data = device.read_sensor_data().await?;
info!("Measurement: {:?}", data);
// Read from registers
let osr = device.read::<register::osr::Osr>().await?;
// Write to registers
device.write::<register::odr::Odr>(®ister::odr::OdrCfg {
odr_sel: register::odr::OutputDataRate::R25Hz,
}).await?
Higher-level wrapper that encodes BMP390 modes in the type system.
use bmp390_rs::typestate::Bmp390Builder;
let mut normal_device = Bmp390Builder::new()
.use_spi(device) // Communicate over SPI
.enable_temperature() // Enable both temperature...
.enable_pressure() // ...and pressure
.into_normal() // Put the device into normal mode
.build(delay).await?;
// Reads the next measurement. This will wait for interrupt (if configured) or delay for one measurement cycle.
let measurement = normal_device.read_next_measurement().await?;
info!("{:?}", measurement);
// Read the latest measurement. This does not wait, but will instead read whatever is in the Data register right now.
let measurement = normal_device.read_latest_measurement().await?;
info!("{:?}", measurement);
Here is an example of a Bmp390 device in forced mode and with the on-board FIFO enabled:
use bmp390_rs::typestate::{Bmp390Builder, FifoOutput};
/* Creates a forced mode Bmp390 that uses the FIFO.
This will give you a queue abstraction over the core driver. */
let mut device = Bmp390Builder::new()
.use_irq(irq_pin) // Use interrupts whenever possible to synchronize data output
.use_spi(spi_device) // Communicate over SPI
.enable_pressure() // We are only interested in pressure, so enable that
.into_forced() // Put the device into forced mode
.use_fifo() // And enable FIFO
.build(delay).await?;
// Now you can ask the Bmp390 device to perform measurements and put them in the on-board FIFO..
device.enqueue_measurement().await?
// And read from the FIFO at a later point:
match forced_device.dequeue().await? {
FifoOutput::Measurement(x) => info!("Got measurement: {:?}", x),
FifoOutput::SensorTime(x) => info!("Got sensor time {}", x),
FifoOutput::Empty => {},
}
bmp390-rs has the following Cargo features:
uom -- Enables integration with the uom crate, which allows you call into_uom on any Measurement.
This project is licensed under either of
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.