Quickstart¶
Read pressure and temperature from your MCU: wire four signals, write a small port class, call four driver functions.
1. Wire it¶
The quickstart uses I2C, the interface the sensor selects after power-up. Hardware has the SPI wiring and the full pin list.
| MCU | BMP581 | Notes |
|---|---|---|
| 3.3 V (or 1.8 V) | VDD (pin 10), VDDIO (pin 1) | 100 nF to ground on each |
| GND | VSS (pins 3, 8, 9) | |
| I2C SCL | SCK (pin 2) | Pull-up to VDDIO; up to 1 MHz, start at 400 kHz |
| I2C SDA | SDI (pin 4) | Pull-up to VDDIO |
| VDDIO or GND | SDO (pin 5) | High: address 0x47; low: 0x46. Do not leave it floating |
| VDDIO | CSB (pin 6) | Keeps the sensor in I2C mode |
Breakout boards such as the SparkFun SEN-20170 (default address 0x47) and the Adafruit 6407 carry the pull-ups; check the board's jumpers for the address.
2. Add the driver¶
Add the repository as a submodule and link the hf::bmp581 CMake target (or add inc/ to your include path and
build with C++17). Installation covers CMake and ESP-IDF.
3. Write the port¶
The port is the only platform code. It writes and reads registers and waits. Replace the three platform_* calls
with your SDK's.
class MyI2c : public bmp581::BusInterface<MyI2c> {
public:
// 7-bit address: 0x46 with SDO low, 0x47 with SDO high.
explicit MyI2c(uint8_t address = bmp581::addr::kSecondary) noexcept : address_(address) {}
// Tells the driver no SPI dummy read is needed and the soft-reset command's missing ACK is expected.
static constexpr bmp581::Interface kInterface = bmp581::Interface::I2c;
// One transaction: [reg, data...]. The chip increments the register address after each byte.
bool WriteRegs(uint8_t reg, const uint8_t* data, std::size_t len) noexcept {
uint8_t frame[16];
if (len + 1 > sizeof(frame)) {
return false;
}
frame[0] = reg;
std::memcpy(frame + 1, data, len);
return platform_i2c_write(address_, frame, len + 1); // report every missing ACK
}
// Write the register address, repeated START, read len bytes (auto-increment).
bool ReadRegs(uint8_t reg, uint8_t* out, std::size_t len) noexcept {
return platform_i2c_write_read(address_, ®, 1, out, len);
}
void DelayUs(uint32_t us) noexcept { platform_delay_us(us); }
// Called before every Init(); bring the bus up here if your SDK needs it.
bool EnsureInitialized() noexcept { return true; }
private:
uint8_t address_;
};
Porting explains each method and shows the SPI variant.
4. Read the sensor¶
#include "bmp581.hpp"
#include <cstdio>
int read_pressure_once(MyI2c& bus) {
bmp581::Driver<MyI2c> dev(bus);
if (const auto r = dev.Init(); !r) { // 1. chip id and NVM ready
std::printf("init: %s\n", bmp581::ToString(r.error).data());
return -1; // wiring, address or supply
}
if (!dev.Configure(bmp581::BarometricReferencePreset())) { // 2. 100 Hz, OSR x8, IIR 3, normal mode
return -1;
}
for (int i = 0; i < 50; ++i) { // 3. wait for the first conversion
const auto ready = dev.DataReady();
if (!ready || ready.value) break;
bus.DelayUs(1000);
}
const auto s = dev.ReadSample(); // 4. pressure (Pa) and temperature (C)
if (!s) return -1;
std::printf("%.1f Pa %.2f C\n", static_cast<double>(s.value.pressure_pa),
static_cast<double>(s.value.temperature_c));
return 0;
}
What each step does:
Init()reads CHIP_ID (0x50) and checks that the NVM has loaded (STATUS.nvm_rdy, nonvm_err). Nothing else is worth calling until it succeeds.Configure()puts the chip in standby, writes oversampling and output data rate, then the IIR filter, then switches to normal mode. The preset samples at 100 Hz with pressure oversampling ×8.DataReady()reads INT_STATUS until the first conversion is done, about 10 ms after the mode change.ReadSample()reads the six data registers in one burst and converts them: pressure / 64 in pascals, temperature / 65536 in degrees Celsius.
This example is built by the host CI, so it compiles against the current headers.
If it does not work¶
| Symptom | First thing to check |
|---|---|
Init() returns Bus |
Address (0x46 or 0x47 from SDO), pull-ups, CSB tied to VDDIO |
Init() returns InvalidChipId |
Another part answers at that address, or SDO floats |
Init() returns NvmNotReady |
Supply ramp or a part still booting: wait 2 ms after power-up and retry |
| Pressure stays at the same value | The chip is still in standby: check the result of Configure() |
Next¶
- API guide: forced mode, the interrupt pin, NVM, errors.
- Configuration: choose oversampling, data rate and filter for your use.
- Examples: ESP32-S3 applications.