BME280 weather sensor
The BME280 is Bosch's temperature, humidity and barometric-pressure sensor, sold on a small breakout for $8. It talks I²C at 0x76 or 0x77 and runs happily from 3.3 V, which makes it the easiest way to add a full weather report to a build — and the reason it appears in the LCD weather station. It is a 6-pin part: power, ground, the two I²C lines, a chip-select that must stay high for I²C mode, and an address pin.
Pins
| Pin | What it is | Type |
|---|---|---|
| VIN | Supply 1.8–3.6 V (3.3 V boards) | power |
| GND | Ground | ground |
| SCL | I²C clock (SCK) | io |
| SDA | I²C data (SDI) | io |
| CSB | Chip select: leave high (or open) for I²C | io |
| SDO | Address select: GND 0x76, VIN 0x77 | io |
In circuit.py:
BME280()— BME280 weather sensor — $8- Pins: 6
CSB selects the interface: leave it open (or tie it to VIN, as here) and the chip speaks I²C; pull it low and it becomes an SPI device instead. SDO is the address pin: tied to ground the sensor answers at 0x76, tied to VIN at 0x77 — handy when two sensors share the bus.
Wiring it in circuit.py
from wiring import *
pi = Pi()
weather = BME280()
pi.V3_3 >> weather.vin
weather.gnd >> pi.GND
pi.SDA >> weather.sda
pi.SCL >> weather.scl
weather.sdo >> pi.GND # address 0x76SDA and SCL are GPIO2 and GPIO3, the header's dedicated I²C pins; the board's on-board 1.8 kΩ pull-ups are already there, so no external resistors are needed. CSB is left unconnected in I²C mode. Changing the address is one wire: move weather.sdo from pi.GND to pi.V3_3 and the chip answers at 0x77.
Driving it in main.py
import time
import board
import adafruit_bme280.basic as adafruit_bme280
bme280 = adafruit_bme280.Adafruit_BME280_I2C(board.I2C(), address=0x76)
while True:
print(f"{bme280.temperature:.1f} C {bme280.humidity:.1f} % {bme280.pressure:.1f} hPa")
time.sleep(1)The Adafruit driver handles the compensation formulas for you. If you would rather see the registers, the smbus2 notes show reading raw data, and things like sea_level_pressure on the Adafruit object let you correct pressure to sea level.
Electrical notes
- Supply is 1.8–3.6 V. The breakout expects 3.3 V — do not power it from 5 V, and do not put the I²C lines on a 5 V bus.
- Current is tiny: about 3.6 µA in normal 1 Hz operation and 0.1 µA asleep, so several can hang off the Pi's I²C with ease.
CSBmust be high or floating for I²C; pulling it low switches the chip to SPI. - Accuracy is ±1 °C, ±3 %RH and ±1 hPa; resolution is far finer (0.01 °C, 0.008 %RH, 0.0018 hPa).
- Raw readings are meaningless without the factory trim registers at 0x88–0xA1 and 0xE1–0xE7 — always use a library, not
read_byte_data. - It sleeps after power-on: a driver must write
ctrl_hum(0xF2) thenctrl_meas(0xF4).ctrl_humonly takes effect on the followingctrl_measwrite; that ordering catches hand-rolled drivers. - Its own heat makes it read slightly warm in continuous high-rate normal mode.
Simulator vs real hardware
- The full register map is modelled: chip id 0x60 at 0xD0, the trim values, forced mode (measures once, then sleeps) and normal mode (fresh data latched at each read instant). A skipped measurement reads 0x80000 / 0x8000, as on the chip.
- Values come from the feed for the sensor's zone. The feed's
altitudeMknob lowers the pressure it measures with the barometric formula; the world's weather already varies the temperature and humidity it reports. - The I²C address follows the
SDOnet, so moving that one wire is enough to move the address. - Breakouts labelled BME280 are sometimes BMP280s (no humidity, chip id 0x58). The simulator only has the real BME280 — if a program checks the chip id, it sees 0x60.
Going deeper
- Primer: I²C, SPI, UART and 1-Wire, and the smbus2 notes for raw register work.
- Recipe: the LCD weather station shows DHT22 + BME280 + LCD.
- Same bus, different job: MPU-6050 motion sensor.
Further reading
- BME280 datasheet (Bosch Sensortec BST-BME280-DS002) — register map, trim values and compensation formulas.
- adafruit_bme280 (CircuitPython) documentation — the driver's properties and modes.
- smbus2 documentation —
read_byte_data,read_i2c_block_dataand the rest of the I²C toolkit.