🛠 Brancher un capteur BME280 sur l'I2C1 du carrier (GPIOX_17/18)
Objectives
Mount a BME280 temperature/humidity/pressure sensor on the carrier's I2C1 bus, wired to GPIOX_17 (SDA, pin 3) and GPIOX_18 (SCL, pin 5) according to the BPI-CM4IO pinout table. You will enable the controller (overlays tutorial), resolve the actual bus number (the mainline &i2c2 controller has no alias), scan the bus, verify the chip ID (0x60), and then read the raw temperature in Python via i2c-dev — the method is identical on BSP 4.9 and on Armbian.
Hardware
- BPI-CM4 + carrier running Armbian (bus enabled, see the overlays tutorial) or vendor image with overlays="i2c2"
- BME280 module in I2C mode (default address 0x76, 0x77 if the ADDR pin is high)
- 4 male-female Dupont wires; power the module with 3.3 V
Complete code
sudo apt install -y i2c-tools
# Résoudre le numéro du bus du header (contrôleur &i2c2, non aliasé)
for d in /sys/class/i2c-dev/i2c-*; do
echo "$(basename $d) -> $(cat $d/of_node/name 2>/dev/null)"
done
i2cdetect -y 2 # adapter N ; la case 76 doit apparaître
#!/usr/bin/env python3
"""bme280_cm4.py — lecture BME280 sur le BPI-CM4 (BUS = numéro trouvé plus haut)."""
import fcntl, time
BUS, ADDR = 2, 0x76 # à ajuster selon i2cdetect -l
I2C_SLAVE = 0x0703
def read_regs(reg, n=1):
with open(f"/dev/i2c-{BUS}", "rb+", buffering=0) as f:
fcntl.ioctl(f, I2C_SLAVE, ADDR)
f.write(bytes([reg]))
return f.read(n)
chip_id = read_regs(0xD0)[0]
print(f"chip ID 0x{chip_id:02X} (attendu 0x60 pour un BME280)")
# Reset doux puis mesure forcée T+x1, P+x1
with open(f"/dev/i2c-{BUS}", "wb+", buffering=0) as f:
fcntl.ioctl(f, I2C_SLAVE, ADDR)
f.write(bytes([0xE0, 0xB6])); time.sleep(0.05)
f.write(bytes([0xF4, 0x27]))
time.sleep(0.1)
raw = read_regs(0xFA, 3) # MSB..XLSB température (20 bits)
temp = ((raw[0] << 16) | (raw[1] << 8) | raw[2]) >> 4
print(f"température brute (registre 20 bits) : {temp}")
Expected verification
i2cdetect displays 76 on the header bus; the script prints chip ID 0x60; when blowing on the sensor, the raw value of the 20-bit register decreases regularly. For a complete physical value, read the calibration coefficients (blocks 0x88-0xA1 and 0xE1-0xE7) and apply the compensation from the Bosch datasheet, or use an existing BME280 library.
Common errors
- Using /dev/i2c-2 "because it is i2c2": on mainline, the enumeration number does not necessarily correspond to the header controller — check via /sys/class/i2c-dev/.
- Forgetting the overlay: i2cdetect -l then shows no header controller.
- Module at 0x77 (ADDR wired high) while the script reads 0x76.
- Powering with 5 V a module whose logic level follows the GPIOX bank (1.8/3.3 V): prefer 3.3 V.
- Confusing it with the camera bus (carrier alias i2c0): the scan there will be empty.
Other tutorials for this board
- Monter le module BPI-CM4 sur son carrier et réussir le premier boot
- Apprivoiser les LED et la touche ADC du carrier CM4IO
- Mesurer le stockage du BPI-CM4 : eMMC, microSD et le palier NVMe
- Activer I2C, SPI et UART sur le BPI-CM4 : env.txt ou armbianEnv.txt
- Déplacer le rootfs sur un SSD NVMe via le port mini-PCIe
- Exploiter le NPU 5 TOPS de l'A311D pour l'inférence embarquée
Code examples for this board
clignotante.pyPythonbouton-gpio.pyPythoncapteur-i2c.shBashsurveillance-temperature.shBashcapteur-dht11.pyPythonservo-pwm-sysfs.shBash