Saltar al contenido
GEEKnodes

Raspberry Pi

Sensor BME280 con Raspberry Pi y Python: temperatura y humedad

Conecta un BME280 a la Raspberry Pi por I2C, actívalo con raspi-config, detéctalo con i2cdetect y lee temperatura, humedad y presión en Python con venv.

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 1 debe 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 BME280Pin físico de la PiSeñal
VCC / VIN13,3 V
GND6Masa
SDA3GPIO 2 (I2C SDA)
SCL5GPIO 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:

  1. Abre la herramienta de configuración:
sudo raspi-config
  1. Entra en Interface Options y luego en I2C.
  2. Responde Yes a la pregunta de activar el interfaz.
  3. 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
Rejilla de i2cdetect con el sensor detectado en la dirección 0x76, y el pin SDO que elige entre 0x76 y 0x77
El sensor aparece en 0x76 o 0x77; el pin SDO decide cuál

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 devueltoChip
0x60BME280 (temperatura, humedad y presión)
0x58BMP280 (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:

  1. Crea el entorno en tu carpeta personal:
Pip instala librerías dentro de un entorno virtual aislado en lugar de mezclarlas con los paquetes del sistema
En Bookworm, las librerías van dentro de un venv, separadas del Python del sistema
python3 -m venv ~/bme280-env
  1. Actívalo:
source ~/bme280-env/bin/activate
  1. Instala la librería RPi.bme280, que usa smbus2 para 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

BME280BMP280DHT22 (AM2302)
TemperaturaSíSíSí
HumedadSíNoSí
PresiónSíSíNo
BusI2C o SPII2C o SPIProtocolo propio de un hilo
Varios en el mismo bus2 (0x76 y 0x77)2 (0x76 y 0x77)Uno por GPIO
Ritmo de lecturaRápidoRápidoUna lectura cada 2 s como mucho
Fiabilidad en la PiAlta: I2C lo gestiona el hardwareAltaMedia: 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

  • i2cdetect no 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. Cambia DIRECCION.
  • 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 el python3 del sistema en vez del del entorno virtual. Activa el venv o usa la ruta completa de su python.
  • Lecturas erráticas con cables largos. I2C está pensado para distancias cortas. Por encima de un metro, usa cable trenzado o acerca el sensor.

Relacionados

Preferencias de accesibilidad

Perfiles rápidos

Texto y lectura

Tamaño del texto
Por defecto
Altura de línea
Por defecto
Espaciado entre letras
Por defecto
Espaciado entre palabras
Por defecto

Color

Movimiento y orientación

Cursor