Un montaje Raspberry Pi DS18B20 MQTT es la forma más robusta de medir temperaturas en varios puntos a la vez: congelador y refrigerador, tuberías de ida y retorno, un acuario, un fermentador o un rack de servidores. En este tutorial activarás el bus 1-Wire, conectarás varias sondas sumergibles a un único pin GPIO, las leerás desde Python usando solo el driver del kernel y publicarás lecturas validadas y con nombre por MQTT.
Por qué el DS18B20 es una gran opción
El DS18B20 es un sensor digital, así que la longitud del cable y el ruido eléctrico le afectan mucho menos que a los sensores analógicos. Cada sonda tiene un número de serie único de 64 bits grabado en fábrica, lo que permite que muchas sondas compartan un solo cable de datos. Las versiones sumergibles vienen en una funda de acero inoxidable con un cable largo, listas para líquidos o uso en exteriores. La precisión ronda el medio grado en el rango normal, y la resolución puede configurarse hasta 0,0625 °C.
Lo mejor de todo es que Raspberry Pi OS incluye un driver del kernel para él. No necesitas ninguna biblioteca de Python para leer los sensores: aparecen como archivos.
Cablear una o varias sondas
Todas las sondas se conectan en paralelo a los mismos tres cables:
| Cable del DS18B20 (sonda sumergible) | Raspberry Pi |
|---|---|
| Rojo: VDD | 3,3 V (pin físico 1) |
| Negro: GND | GND (pin físico 6) |
| Amarillo: DATA | GPIO4 (pin físico 7) |
Añade una resistencia de 4,7 k entre DATA y 3,3 V. Esa única pull-up sirve a todo el bus; no añadas una por sonda. Usa el modo de tres hilos (alimentado), como se muestra, en lugar de la alimentación parásita, que es menos fiable con varias sondas. En tendidos de cable largos, una disposición en estrella con muchas ramas es la topología más difícil para 1-Wire; una sola línea con derivaciones cortas funciona mejor, y una pull-up más baja, como 2,2 k, puede ayudar en buses largos.
Activar 1-Wire
Activa el bus con raspi-config o añade tú mismo el overlay:
sudo raspi-config nonint do_onewire 0
# o, de forma equivalente, añade esta línea a /boot/firmware/config.txt:
# dtoverlay=w1-gpio,gpiopin=4
sudo reboot
Tras el reinicio, enumera las sondas detectadas:
ls /sys/bus/w1/devices/
cat /sys/bus/w1/devices/28-*/w1_slave
Cada sonda aparece como un directorio que empieza por 28-. El archivo w1_slave contiene dos líneas: la primera termina en YES cuando la comprobación CRC ha sido correcta, y la segunda termina con t= seguido de la temperatura en milésimas de grado, por ejemplo t=21375 para 21,375 °C. La documentación de configuración de Raspberry Pi describe las opciones del overlay 1-Wire.
Poner nombre a las sondas
Números de serie como 28-3c01d0752a8b no significan nada en un dashboard. Crea probes.json asignando a cada número de serie un nombre corto que pasará a formar parte del topic MQTT:
{
"28-3c01d0752a8b": "freezer",
"28-3c01d075f1e2": "fridge",
"28-0316a2794bff": "outdoor"
}
Para saber cuál es cada sonda, calienta una con la mano y observa qué lectura sube. Las sondas que no figuren en el archivo se publican igualmente con su número de serie, así que una sonda recién añadida nunca desaparece en silencio.
Estructura de topics
| Topic | Payload | Retenido |
|---|---|---|
connectmq/demo/b81f2d/house/temp/<name> |
{"celsius": 4.2, "ts": ...} |
No |
connectmq/demo/b81f2d/house/temp/all |
Todas las sondas en un solo objeto JSON | No |
connectmq/demo/b81f2d/house/status |
online / offline |
Sí |
Los topics por sonda son adecuados para dashboards y reglas de alerta sobre un único valor; el mensaje combinado resulta cómodo para registradores que escriben una fila por intervalo. Sustituye b81f2d por tu propia cadena aleatoria.
El script Raspberry Pi DS18B20 MQTT
Guárdalo como ds18b20_mqtt.py:
#!/usr/bin/env python3
"""Read all DS18B20 probes on the 1-Wire bus and publish them to MQTT."""
import json
import os
import time
import uuid
from pathlib import Path
import paho.mqtt.client as mqtt
BROKER = os.getenv("MQTT_HOST", "broker.connectmq.com")
PORT = int(os.getenv("MQTT_PORT", "1883"))
USERNAME = os.getenv("MQTT_USERNAME")
PASSWORD = os.getenv("MQTT_PASSWORD")
CLIENT_ID = os.getenv("MQTT_CLIENT_ID", f"ds18b20-{uuid.uuid4().hex[:8]}")
PREFIX = os.getenv("MQTT_PREFIX", "connectmq/demo/b81f2d/house")
INTERVAL = int(os.getenv("PUBLISH_INTERVAL", "60"))
W1_DIR = Path("/sys/bus/w1/devices")
NAMES_FILE = Path(os.getenv("PROBES_FILE", "probes.json"))
def load_names():
try:
return json.loads(NAMES_FILE.read_text())
except (OSError, json.JSONDecodeError):
return {}
def read_probe(device: Path, retries: int = 3):
"""Devuelve grados Celsius, o None si la sonda no da una lectura válida."""
for _ in range(retries):
try:
lines = (device / "w1_slave").read_text().strip().splitlines()
except OSError:
return None # sonda desconectada
if len(lines) == 2 and lines[0].endswith("YES") and "t=" in lines[1]:
millis = int(lines[1].split("t=")[1])
if millis != 85000: # 85,0 °C es el valor de reinicio al encender
celsius = millis / 1000.0
if -55.0 <= celsius <= 125.0:
return celsius
time.sleep(0.2)
return None
def on_connect(client, userdata, flags, reason_code, properties):
if reason_code.is_failure:
print(f"Connection refused: {reason_code}")
return
print(f"Connected as {CLIENT_ID}")
client.publish(f"{PREFIX}/status", "online", qos=1, retain=True)
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=CLIENT_ID)
client.on_connect = on_connect
client.will_set(f"{PREFIX}/status", "offline", qos=1, retain=True)
client.reconnect_delay_set(min_delay=1, max_delay=60)
if USERNAME:
client.username_pw_set(USERNAME, PASSWORD)
if PORT == 8883:
client.tls_set()
client.connect(BROKER, PORT, keepalive=60)
client.loop_start()
try:
while True:
started = time.monotonic()
names = load_names()
now = int(time.time())
combined = {}
for device in sorted(W1_DIR.glob("28-*")):
name = names.get(device.name, device.name)
celsius = read_probe(device)
if celsius is None:
combined[name] = None
print(f"{name}: no valid reading")
continue
combined[name] = round(celsius, 2)
payload = {"celsius": round(celsius, 2), "ts": now}
client.publish(f"{PREFIX}/temp/{name}", json.dumps(payload), qos=1)
client.publish(
f"{PREFIX}/temp/all", json.dumps({"probes": combined, "ts": now}), qos=1
)
print(combined)
time.sleep(max(0, INTERVAL - (time.monotonic() - started)))
except KeyboardInterrupt:
pass
finally:
client.publish(f"{PREFIX}/status", "offline", qos=1, retain=True).wait_for_publish(2)
client.loop_stop()
client.disconnect()
No hace falta ninguna biblioteca de sensores; paho-mqtt es la única dependencia:
mkdir -p ~/ds18b20-mqtt && cd ~/ds18b20-mqtt
python3 -m venv .venv && source .venv/bin/activate
pip install "paho-mqtt>=2.0"
python ds18b20_mqtt.py
El script vuelve a leer probes.json en cada ciclo, así que puedes renombrar una sonda sin reiniciar. Las sondas ausentes o que fallan aparecen como null en el mensaje combinado en lugar de descartarse, lo que hace visible un cable roto en el dashboard.
Los errores clásicos
- Una lectura de exactamente 85,0 °C: la sonda devolvió su valor por defecto de encendido antes de completar una conversión, normalmente por una alimentación débil o por alimentación parásita. El script la descarta.
w1_slavemuestraNOen la primera línea: el CRC falló por ruido o por un cable largo. El script reintenta hasta tres veces.- Las sondas aparecen y desaparecen del directorio: conexiones flojas o un bus sobrecargado; revisa las soldaduras y el valor de la pull-up.
- No hay ningún directorio
28-: 1-Wire no está activado, el cable de datos no está en GPIO4 o falta la pull-up. - Ciclos lentos con muchas sondas: cada conversión de 12 bits tarda hasta unas tres cuartas partes de segundo, y el kernel lee las sondas una tras otra. Diez sondas tardan por tanto varios segundos por ciclo, lo cual está bien con un intervalo de 60 segundos.
Cambiar resolución por velocidad
La mayoría de las aplicaciones no necesitan pasos de 0,0625 °C. Los kernels actuales exponen un archivo resolution para cada sonda, así que puedes reducirla y acortar el tiempo de conversión:
cat /sys/bus/w1/devices/28-3c01d0752a8b/resolution
echo 10 | sudo tee /sys/bus/w1/devices/28-3c01d0752a8b/resolution
A 10 bits el paso es de 0,25 °C y cada conversión termina en una fracción del tiempo de 12 bits, lo que ayuda cuando un bus lleva muchas sondas o quieres actualizaciones más rápidas. El ajuste reside en la memoria volátil de la sonda, así que se pierde tras un corte de alimentación a menos que también lo guardes en la EEPROM de la sonda; consulta la documentación de w1_therm del kernel para tu versión antes de escribir en la EEPROM.
Piensa también en dónde está la sonda y no solo en su precisión. Una sonda pegada a una tubería mide la tubería con más exactitud cuando está bien sujeta con una abrazadera metálica y cubierta con aislante. Una sonda en un congelador debe colgar en el aire, sin tocar un paquete congelado, salvo que lo que quieras conocer sea la temperatura del alimento.
Ver las lecturas
mosquitto_sub -h broker.connectmq.com -p 1883 -i watch-b81f2d \
-t 'connectmq/demo/b81f2d/house/#' -v
Verás un mensaje por sonda y luego el mensaje combinado, cada minuto. En el servidor MQTT público gratuito estos topics son visibles para cualquiera, así que limítate a datos de prueba y a un prefijo aleatorio.
Siguientes pasos
Un bus 1-Wire encaja de forma natural en un nodo compacto; el script funciona sin cambios en un nodo de sensores MQTT con Raspberry Pi Zero 2 W. Si además quieres humedad, combínalo con la guía Raspberry Pi DHT22 MQTT, que usa el mismo estilo de topics. Para gráficos a largo plazo, el stack de Grafana e InfluxDB en Raspberry Pi se suscribe a estos topics mediante Telegraf y conserva meses de historial.
Configuración de producción
Las alarmas de congeladores y el monitoreo de calefacción merecen una conexión privada y cifrada. ConnectMQ es un broker MQTT gestionado: crea un broker en el portal y ejecuta el script con TLS:
export MQTT_PORT=8883
export MQTT_USERNAME=YOUR_USERNAME
export MQTT_PASSWORD=YOUR_PASSWORD
export MQTT_CLIENT_ID=YOUR_CLIENT_ID
export MQTT_PREFIX=home/kitchen
python ds18b20_mqtt.py
En el portal de ConnectMQ, una regla de alerta por umbral sobre home/kitchen/temp/freezer, por ejemplo por encima de -12 °C, registra una alerta que puedes revisar en el registro de alertas. Ejecuta el script como servicio systemd para que se reinicie tras los cortes de luz; el tutorial de MQTT con Raspberry Pi incluye la plantilla.
Empieza con ConnectMQ
Envía tus sondas a un broker MQTT en la nube al que dashboards, registradores y reglas de alerta puedan llegar desde cualquier lugar. Crea un broker gratuito de ConnectMQ en el plan Serverless, sin tarjeta de crédito, pega las credenciales generadas en tu entorno y conéctate por TLS en el puerto 8883.
Preguntas frecuentes
¿Cuántas sondas DS18B20 puedo conectar a un pin de la Raspberry Pi?
Muchas sondas pueden compartir un único bus gracias a sus números de serie únicos. En la práctica, la longitud del cable y la topología te limitan antes que el espacio de direcciones; entre unas pocas y unas cuantas docenas en un bus bien cableado es realista.
¿Por qué mi DS18B20 marca 85 grados?
85,0 °C es el valor que guarda el sensor tras el encendido, antes de su primera conversión. Suele indicar un problema de alimentación o una lectura demasiado temprana; descártala y revisa el cableado.
¿Necesito una biblioteca de Python para leer un DS18B20?
No. Los drivers del kernel w1-gpio y w1-therm exponen cada sonda como un archivo en /sys/bus/w1/devices, que Python puede leer sin más.
¿Puedo usar otro pin GPIO para 1-Wire?
Sí. Define dtoverlay=w1-gpio,gpiopin=17 (u otro pin) en /boot/firmware/config.txt y reinicia.



