Two barometers on an ESP32-C3
A BME280 and a BMP280 on one I2C bus, told apart by their address straps and their chip ids. Raw counts, a factory calibration, and the datasheet sums in integers. The whole build, an ESP32-C3 and 2 more parts, runs here in your browser on the firmware below; open it in the editor to change the wiring or the code and run it again.
IntermediateRuns in your browser. Free, and no account needed.
The code
The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.
// Two pressure sensors on one I2C bus: a BME280 at 0x76 and a BMP280 at 0x77,
// on the ESP32-C3's own I2C pins, GPIO 8 (SDA) and GPIO 9 (SCL).
//
// The two chips are the same die, less the humidity sensor on the BMP280, and
// on their purple boards they look identical. The address strap is what lets
// both share one bus, and the chip-id register, 0x60 or 0x58, is how the
// sketch tells which is which.
//
// Neither reports degrees or pascals. Each reports raw counts and carries its
// own factory calibration, and the datasheet's integer formulas turn one into
// the other: mokxi_bme280.h is those formulas. The temperature is always
// worked first, because the pressure and humidity formulas need a by-product
// of it. The altitude is the barometric formula against 1013.25 hPa, worked in
// integers too.
//
// Drag the pressure sliders: every 12 hPa or so is a hundred metres.
#include <Wire.h>
#include "mokxi_bme280.h"
MokxiBme280 sensor[2];
const uint8_t ADDRESS[2] = {0x76, 0x77};
// A whole number of hundredths (or tenths) printed with its decimal point.
void printFixed(long value, long scale) {
if (value < 0) {
Serial.print('-');
value = -value;
}
Serial.print(value / scale);
Serial.print('.');
long rest = value % scale;
for (long digit = scale / 10; digit > 1 && rest < digit; digit /= 10) Serial.print('0');
Serial.print(rest);
}
void setup() {
Serial.begin(9600);
Wire.begin();
for (int i = 0; i < 2; i++) {
Serial.print("0x");
Serial.print(ADDRESS[i], HEX);
if (!sensor[i].begin(&Wire, ADDRESS[i])) {
Serial.println(": nothing there");
continue;
}
Serial.println(sensor[i].humid() ? ": BME280, id 0x60" : ": BMP280, id 0x58");
// Normal mode, 2x temperature, 16x pressure, 1x humidity, filter 4.
sensor[i].configure(0x01, (0x02 << 5) | (0x05 << 2) | 0x03, 0x02 << 2);
}
}
void loop() {
delay(1000);
for (int i = 0; i < 2; i++) {
if (sensor[i].id() == 0) continue;
int32_t t, p, h;
if (!sensor[i].readRaw(t, p, h)) continue;
long hundredths = sensor[i].temperature100(t); // first: it sets t_fine
long pascals = (long)sensor[i].pressurePa(p);
Serial.print(sensor[i].humid() ? "BME280 " : "BMP280 ");
printFixed(hundredths, 100);
Serial.print(" C ");
printFixed(pascals, 100);
Serial.print(" hPa ");
printFixed(mokxi_altitude_cm((uint32_t)pascals, 101325u) / 10, 10);
Serial.print(" m");
if (sensor[i].humid()) {
Serial.print(" ");
printFixed((long)sensor[i].humidity1024(h) * 10 / 1024, 10);
Serial.print(" %RH");
}
Serial.println();
}
}
Parts list
4 parts, plus the jumper wires. Every one is in the editor's parts bin.
How it is wired
4 connections, pin by pin, read from the circuit itself. Each line is one set of pins joined together, by a jumper wire or a breadboard strip.
- ESP32-C3-DevKitM-1 pin 3V3; Pressure, humidity and temperature, BME280 pin VIN; Pressure and temperature, BMP280 pin VIN
- Ground: ESP32-C3-DevKitM-1 pin GND; Pressure, humidity and temperature, BME280 pin GND; Pressure and temperature, BMP280 pin GND
- ESP32-C3-DevKitM-1 pin 8; Pressure, humidity and temperature, BME280 pin SDA; Pressure and temperature, BMP280 pin SDA
- ESP32-C3-DevKitM-1 pin 9; Pressure, humidity and temperature, BME280 pin SCL; Pressure and temperature, BMP280 pin SCL
Change it and keep it
Open it in the editor, change the circuit or the code, and keep your version in a free account.