El BME280 es uno de los sensores más cómodos para una estación meteorológica casera: mide temperatura, humedad y presión con solo cuatro cables. En esta guía lo conectas a la Raspberry Pi por I2C, compruebas que el sistema lo ve y guardas lecturas en un CSV con Python, sorteando la restricción de pip en Bookworm.
En resumen
- Se conecta a 3V3, GND, SDA (GPIO 2) y SCL (GPIO 3); no necesita resistencias externas en los módulos habituales.
- Tras activar I2C en
raspi-config,i2cdetect -y 1debe mostrarlo en 0x76 o 0x77.- En Raspberry Pi OS Bookworm las librerías se instalan dentro de un entorno virtual de Python.
Qué necesitas
- Una Raspberry Pi con conector de 40 pines (Pi 5, Pi 4, Pi 3 o Zero 2 W) y Raspberry Pi OS Bookworm.
- Un módulo BME280 en placa, con pines VCC (o VIN), GND, SCL y SDA. Algunos traen también CSB y SDO.
- Cuatro cables dupont hembra-hembra.
Conexión a los pines
| Pin del BME280 | Pin físico de la Pi | Señal |
|---|---|---|
| VCC / VIN | 1 | 3,3 V |
| GND | 6 | Masa |
| SDA | 3 | GPIO 2 (I2C SDA) |
| SCL | 5 | GPIO 3 (I2C SCL) |
Tres detalles que evitan disgustos:
- Alimenta con 3,3 V, no con 5 V. Hay módulos con regulador que aceptan 5 V, pero los GPIO de la Pi trabajan a 3,3 V y no toleran 5 V en SDA y SCL. Con 3V3 no te equivocas.
- La Pi ya tiene resistencias pull-up en GPIO 2 y GPIO 3, y la mayoría de módulos traen las suyas. No añadas más.
- Haz las conexiones con la Pi apagada.
Si tu módulo tiene pin SDO, ese pin decide la dirección: a GND da 0x76 y a VCC da 0x77. Si no lo conectas, manda lo que haya decidido el fabricante en la placa.
Activar I2C
I2C viene desactivado de serie. Para activarlo:
- Abre la herramienta de configuración:
sudo raspi-config
- Entra en Interface Options y luego en I2C.
- Responde Yes a la pregunta de activar el interfaz.
- Sal con Finish. Si te pide reiniciar, acepta.
En el escritorio también puedes hacerlo desde Preferencias → Configuración de Raspberry Pi → Interfaces.
Detectar el sensor con i2cdetect
Instala las herramientas de I2C y escanea el bus 1, que es el de los pines 3 y 5:
sudo apt update
sudo apt install -y i2c-tools
i2cdetect -y 1

Verás una rejilla. Si todo va bien, aparece un número en una casilla:
0 1 2 3 4 5 6 7 8 9 a b c d e f
70: -- -- -- -- -- -- 76 --
Apunta esa dirección; la usarás en el código. Si la rejilla sale vacía, revisa el cableado antes de seguir.
Truco: saber si es un BME280 o un BMP280
Muchos módulos baratos se venden como BME280 y llevan un BMP280, que no mide humedad. Ambos parecen iguales a simple vista. El registro 0xD0 del chip devuelve su identificador:
i2cget -y 1 0x76 0xD0
| Valor devuelto | Chip |
|---|---|
0x60 | BME280 (temperatura, humedad y presión) |
0x58 | BMP280 (temperatura y presión, sin humedad) |
Cambia 0x76 por 0x77 si tu sensor está en esa dirección.
Entorno virtual de Python
Desde Bookworm, pip install fuera de un entorno virtual devuelve el error externally-managed-environment. No es un fallo: el sistema protege los paquetes de Python que gestiona apt. Saltártelo con --break-system-packages funciona, pero puede romper herramientas del propio sistema. Lo correcto es un venv:
- Crea el entorno en tu carpeta personal:

python3 -m venv ~/bme280-env
- Actívalo:
source ~/bme280-env/bin/activate
- Instala la librería
RPi.bme280, que usasmbus2para hablar por I2C:
pip install RPi.bme280
El prompt muestra (bme280-env) mientras el entorno está activo. Sales con deactivate.
Primera lectura
Crea ~/bme280/leer.py:
import smbus2
import bme280
PUERTO = 1
DIRECCION = 0x76
bus = smbus2.SMBus(PUERTO)
calibracion = bme280.load_calibration_params(bus, DIRECCION)
datos = bme280.sample(bus, DIRECCION, calibracion)
print(f"Temperatura: {datos.temperature:.1f} °C")
print(f"Humedad: {datos.humidity:.1f} %")
print(f"Presión: {datos.pressure:.1f} hPa")
Ejecútalo con el entorno activo:
python ~/bme280/leer.py
La función load_calibration_params lee los coeficientes que cada chip trae grabados de fábrica. Sin ellos, los valores en bruto no significan nada.
Guardar lecturas en un CSV
Para registrar datos durante días, este script añade una fila cada vez que se ejecuta y escribe la cabecera solo si el archivo es nuevo:
import csv
from datetime import datetime
from pathlib import Path
import smbus2
import bme280
DIRECCION = 0x76
ARCHIVO = Path.home() / "bme280" / "lecturas.csv"
bus = smbus2.SMBus(1)
calibracion = bme280.load_calibration_params(bus, DIRECCION)
datos = bme280.sample(bus, DIRECCION, calibracion)
nuevo = not ARCHIVO.exists()
with ARCHIVO.open("a", newline="") as f:
escritor = csv.writer(f)
if nuevo:
escritor.writerow(["fecha", "temperatura_c", "humedad_pct", "presion_hpa"])
escritor.writerow([
datetime.now().isoformat(timespec="seconds"),
round(datos.temperature, 2),
round(datos.humidity, 2),
round(datos.pressure, 2),
])
Usa una ruta absoluta (aquí, a partir de Path.home()) para que funcione igual desde la terminal que desde una tarea programada. Para lanzarlo cada 10 minutos con cron, llama al Python del entorno virtual directamente:
*/10 * * * * /home/tu-usuario/bme280-env/bin/python /home/tu-usuario/bme280/guardar.py
El CSV se abre sin problema en una hoja de cálculo o con pandas.
BME280, BMP280 y DHT22 frente a frente
| BME280 | BMP280 | DHT22 (AM2302) | |
|---|---|---|---|
| Temperatura | Sí | Sí | Sí |
| Humedad | Sí | No | Sí |
| Presión | Sí | Sí | No |
| Bus | I2C o SPI | I2C o SPI | Protocolo propio de un hilo |
| Varios en el mismo bus | 2 (0x76 y 0x77) | 2 (0x76 y 0x77) | Uno por GPIO |
| Ritmo de lectura | Rápido | Rápido | Una lectura cada 2 s como mucho |
| Fiabilidad en la Pi | Alta: I2C lo gestiona el hardware | Alta | Media: depende de tiempos precisos y a veces falla la lectura |
Según las hojas de datos, la precisión típica del BME280 es de ±1 °C en temperatura, ±3 % de humedad relativa y ±1 hPa de presión. El DHT22 anuncia una precisión de temperatura algo mejor, pero su protocolo de un hilo es delicado en Linux y genera lecturas fallidas que hay que reintentar. Si necesitas humedad, el BME280 es la opción más cómoda; si solo te interesa la presión o la altitud, un BMP280 basta y es más barato.
Problemas frecuentes
i2cdetectno muestra nada. I2C no está activado, SDA y SCL están cruzados o un cable no hace contacto. Revisa también que usas el bus 1.- Aparece en 0x77 y el código usa 0x76 (o al revés). Error típico:
OSError: [Errno 121] Remote I/O error. CambiaDIRECCION. - La humedad no aparece o sale fija. Probablemente es un BMP280. Compruébalo con el registro
0xD0. - La temperatura sale 2–3 °C por encima de la real. El sensor está pegado a la Pi o a su caja y recibe su calor. Sepáralo con cables más largos y no lo encierres con la placa.
ModuleNotFoundError: No module named 'bme280'. Estás ejecutando elpython3del sistema en vez del del entorno virtual. Activa el venv o usa la ruta completa de supython.- Lecturas erráticas con cables largos. I2C está pensado para distancias cortas. Por encima de un metro, usa cable trenzado o acerca el sensor.



