Raspberry Pi

Nodo sensor Raspberry Pi Zero 2 W MQTT: compacto, de bajo consumo y fiable

Construye un nodo sensor pequeño y sin pantalla con una Raspberry Pi Zero 2 W que lee un BME280, publica datos ambientales y de salud por MQTT 5, consume menos y sobrevive a meses de funcionamiento desatendido.

Diminuta Raspberry Pi Zero 2 W con un sensor BME280 en una pequeña caja enviando lecturas a la nube en un nodo sensor Raspberry Pi Zero 2 W MQTT
Pruébalo en tu propio broker MQTTConsigue un broker MQTT privado y gestionado con el plan Free y empieza con ejemplos de código listos para usar.
Pruébalo gratis Ejemplos de código Sin tarjeta

Un nodo Raspberry Pi Zero 2 W MQTT te da un ordenador Linux completo del tamaño de un chicle, lo que lo hace ideal para nodos sensores que necesitan Python, TLS y acceso remoto, pero no una placa de tamaño completo. En esta guía configurarás una Zero 2 W sin pantalla, recortarás su consumo, leerás un sensor ambiental BME280 y publicarás las lecturas y la salud del dispositivo por MQTT 5, con el blindaje necesario para funcionar desatendida durante meses.

Por qué la Zero 2 W es un buen nodo sensor

La Zero 2 W tiene un Arm Cortex-A53 de cuatro núcleos y 64 bits, 512 MB de RAM, Wi-Fi de 2,4 GHz y Bluetooth, y el conector GPIO estándar de 40 pines. Es suficiente para ejecutar Python, paho-mqtt con TLS y un par de sensores con margen de sobra, consumiendo bastante menos que una Pi 4 o una Pi 5.

Sin embargo, no es un microcontrolador. No puede entrar en deep sleep entre lecturas y arranca Linux desde una tarjeta SD. Si tu nodo tiene que funcionar con baterías durante meses, un ESP32 es la mejor herramienta; nuestra comparativa Raspberry Pi vs ESP32 explica las ventajas y desventajas. La Zero 2 W brilla donde hay alimentación de red o USB y valoras las herramientas de Linux, el acceso por SSH y Python por encima del último milivatio.

Lista de componentes

Componente Propósito
Raspberry Pi Zero 2 W El propio nodo
Fuente micro USB de 5 V y 2,5 A de calidad La subtensión es la causa más común de cuelgues
Tarjeta microSD clase A2, de 16 GB o más Sistema operativo y aplicación
Placa BME280 (I2C) Temperatura, humedad, presión
Conector de 40 pines soldado o cables soldados La Zero 2 W viene sin conector

Configuración sin pantalla con Raspberry Pi OS Lite

Usa Raspberry Pi Imager para grabar Raspberry Pi OS Lite (64-bit). En las opciones avanzadas define el hostname, activa SSH con una clave pública, introduce tu red Wi-Fi y el país, y crea tu usuario. La imagen Lite no tiene escritorio, lo que ahorra RAM, escrituras en el almacenamiento y energía. Arranca la Zero, espera un minuto y conéctate:

ssh pi@zero-node-01.local
sudo apt update && sudo apt full-upgrade -y
sudo raspi-config nonint do_i2c 0
sudo apt install -y python3-venv i2c-tools

Recuerda que la Zero 2 W solo admite Wi-Fi de 2,4 GHz. Si nunca aparece en la red, comprueba que tu punto de acceso emite en la banda de 2,4 GHz y que el país del Wi-Fi está bien configurado.

Reducir el consumo y el desgaste de la tarjeta SD

Añade estas líneas a /boot/firmware/config.txt y reinicia:

# Desactiva Bluetooth si no lo necesitas
dtoverlay=disable-bt
# Apaga el LED de actividad
dtparam=act_led_trigger=none

Después mantén el journal del sistema en RAM para que los logs rutinarios no desgasten la tarjeta SD:

sudo mkdir -p /etc/systemd/journald.conf.d
printf "[Journal]\nStorage=volatile\nRuntimeMaxUse=16M\n" | \
  sudo tee /etc/systemd/journald.conf.d/volatile.conf
sudo systemctl restart systemd-journald
sudo systemctl disable --now bluetooth hciuart 2>/dev/null || true

Hay un ajuste de energía que es un compromiso deliberado. El ahorro de energía del Wi-Fi reduce el consumo, pero puede retrasar los paquetes entrantes lo suficiente como para provocar timeouts de keepalive y reconexiones. Si ves desconexiones frecuentes en tus logs, desactívalo con sudo iw wlan0 set power_save off y hazlo permanente mediante NetworkManager. Para un nodo que solo publica, dejar activado el ahorro de energía suele estar bien.

Cableado del BME280

BME280 Zero 2 W
VIN 3,3 V (pin físico 1)
GND GND (pin físico 6)
SCL GPIO3 / SCL (pin físico 5)
SDA GPIO2 / SDA (pin físico 3)

Ejecuta i2cdetect -y 1. Deberías ver el sensor en la dirección 0x76 o 0x77. Anota cuál; el script usa 0x76 por defecto.

Instalación del entorno de Python

mkdir -p ~/node && cd ~/node
python3 -m venv .venv
source .venv/bin/activate
pip install "paho-mqtt>=2.0" adafruit-circuitpython-bme280

El script Raspberry Pi Zero 2 W MQTT

Este script usa MQTT 5 para que cada lectura lleve un intervalo de caducidad del mensaje: si un suscriptor con sesión persistente está desconectado más de cinco minutos, las lecturas obsoletas se descartan en lugar de entregarse tarde. También publica un mensaje de salud con la temperatura de la CPU, la señal Wi-Fi y el tiempo en marcha, algo de un valor incalculable cuando el nodo está escondido en un armario. Guárdalo como node.py:

#!/usr/bin/env python3
"""Pi Zero 2 W sensor node: BME280 + health metrics over MQTT 5."""
import json
import os
import time
import uuid

import board
import paho.mqtt.client as mqtt
from adafruit_bme280 import basic as adafruit_bme280
from paho.mqtt.packettypes import PacketTypes
from paho.mqtt.properties import Properties

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"zero2w-{uuid.uuid4().hex[:8]}")
PREFIX = os.getenv("MQTT_PREFIX", "connectmq/demo/4b9e27/zero-node-01")
INTERVAL = int(os.getenv("PUBLISH_INTERVAL", "60"))
BME_ADDRESS = int(os.getenv("BME280_ADDRESS", "0x76"), 16)

i2c = board.I2C()
bme = adafruit_bme280.Adafruit_BME280_I2C(i2c, address=BME_ADDRESS)

expiry = Properties(PacketTypes.PUBLISH)
expiry.MessageExpiryInterval = 300


def cpu_temp():
    with open("/sys/class/thermal/thermal_zone0/temp") as f:
        return round(int(f.read()) / 1000, 1)


def wifi_rssi():
    try:
        with open("/proc/net/wireless") as f:
            for line in f:
                if line.strip().startswith("wlan0:"):
                    return float(line.split()[3].rstrip("."))
    except (OSError, ValueError, IndexError):
        pass
    return None


def uptime_s():
    with open("/proc/uptime") as f:
        return int(float(f.read().split()[0]))


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,
    protocol=mqtt.MQTTv5,
)
client.on_connect = on_connect
client.will_set(f"{PREFIX}/status", "offline", qos=1, retain=True)
client.reconnect_delay_set(min_delay=2, max_delay=120)
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:
        now = int(time.time())
        reading = {
            "temperature": round(bme.temperature, 2),
            "humidity": round(bme.relative_humidity, 1),
            "pressure": round(bme.pressure, 1),
            "ts": now,
        }
        health = {
            "cpu_temp": cpu_temp(),
            "rssi": wifi_rssi(),
            "uptime": uptime_s(),
            "ts": now,
        }
        client.publish(f"{PREFIX}/env", json.dumps(reading), qos=1, properties=expiry)
        client.publish(f"{PREFIX}/health", json.dumps(health), qos=0, properties=expiry)
        print(reading, health)
        time.sleep(INTERVAL)
except KeyboardInterrupt:
    pass
finally:
    client.publish(f"{PREFIX}/status", "offline", qos=1, retain=True).wait_for_publish(2)
    client.loop_stop()
    client.disconnect()

Pruébalo en primer plano con python node.py y observa desde otro equipo:

mosquitto_sub -h broker.connectmq.com -p 1883 -i watch-4b9e27 -V mqttv5 \
  -t 'connectmq/demo/4b9e27/#' -v

El servidor MQTT público gratuito admite MQTT 5 y sirve para esta comprobación, pero todo lo que hay en él es legible públicamente, así que usa un prefijo aleatorio como 4b9e27 y no lo uses con datos de producción.

Funcionamiento desatendido

Un nodo sensor solo es útil si se recupera solo tras un corte de luz o un fallo. Crea /etc/systemd/system/sensor-node.service:

[Unit]
Description=Zero 2 W MQTT sensor node
After=network-online.target
Wants=network-online.target

[Service]
User=pi
WorkingDirectory=/home/pi/node
EnvironmentFile=/home/pi/node/node.env
ExecStart=/home/pi/node/.venv/bin/python node.py
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

Pon tu configuración de conexión en /home/pi/node/node.env y restríngela con chmod 600:

MQTT_HOST=broker.connectmq.com
MQTT_PORT=8883
MQTT_USERNAME=YOUR_USERNAME
MQTT_PASSWORD=YOUR_PASSWORD
MQTT_CLIENT_ID=YOUR_CLIENT_ID
MQTT_PREFIX=site1/office/zero-node-01

Actívalo con sudo systemctl enable --now sensor-node. Para saber más sobre archivos de servicio y logs, consulta ejecutar un script MQTT de Python al arrancar.

Actualizar nodos en campo

Aunque el nodo esté montado en una pared, seguirás queriendo cambiar su código. Mantén la aplicación en un repositorio git y actualiza con git pull seguido de sudo systemctl restart sensor-node por SSH. Como la configuración de conexión vive en node.env y no en el script, el mismo código se ejecuta en todos los nodos y solo cambia el archivo de entorno. Antes de desplegar un cambio en todos los nodos, pruébalo en uno y vigila sus topics health y status durante un día. Un nodo que deja de publicar mensajes de salud pero sigue mostrando online suele estar atascado en una lectura del sensor, lo que es una pista para añadir timeouts al acceso al hardware.

Lista de blindaje

  1. Usa una fuente oficial o de alta calidad; ejecuta vcgencmd get_throttled y espera throttled=0x0.
  2. Mantén el journal en RAM y evita escribir archivos en el bucle de publicación.
  3. Activa el watchdog de hardware con RuntimeWatchdogSec=15 en /etc/systemd/system.conf para que un kernel congelado se reinicie.
  4. Monta el BME280 con un cable corto, alejado de la placa; la Zero calienta el aire a su alrededor.
  5. Publica datos de salud y define el last will para que el topic de estado muestre offline cuando el nodo desaparezca.
  6. Usa TLS y credenciales por dispositivo antes de que el nodo salga de tu mesa.

Escalar a muchos nodos

Una Zero 2 W es un proyecto; veinte son una flota. Da a cada nodo sus propias credenciales y su client ID, un topic predecible como site1/<room>/<node>/env y la misma imagen. Un broker MQTT gestionado elimina la necesidad de ejecutar y proteger tu propio servidor. Con ConnectMQ, el client ID de cada nodo está vinculado a sus credenciales, la vista de dispositivos del portal lista los nodos según su jerarquía de topics y una regla de alerta por umbral puede avisarte cuando una sala tiene demasiada humedad. El plan gratuito Serverless permite hasta 25 conexiones, lo que cubre una flota pequeña más un dashboard.

Si prefieres sensores más sencillos, la guía de Raspberry Pi con DS18B20 y MQTT funciona sin cambios en la Zero 2 W, y el tutorial de MQTT con Raspberry Pi cubre los fundamentos de publicación y suscripción en los que se basa este nodo.

Empieza con ConnectMQ

Pon tus nodos Zero 2 W en un broker MQTT en la nube al que puedan llegar desde cualquier red. Regístrate gratis en ConnectMQ, sin tarjeta de crédito, crea un broker y pega el nombre de usuario, la contraseña y el client ID generados en node.env. Tu nodo se conecta por TLS en el puerto 8883 con MQTT 5, y cada lectura aparece en el explorador de topics en vivo.

Preguntas frecuentes

¿Puede una Raspberry Pi Zero 2 W funcionar con baterías?

Solo durante periodos cortos, porque no puede entrar en deep sleep y consume energía continuamente. Para una batería de larga duración usa un microcontrolador como el ESP32 y reserva la Zero 2 W para ubicaciones con alimentación.

¿Bastan 512 MB de RAM para un nodo sensor MQTT?

Sí. Un script de Python con paho-mqtt, TLS y una librería de sensor usa una pequeña fracción en Raspberry Pi OS Lite, y deja espacio para un segundo servicio.

¿Por qué mi Zero 2 W se desconecta continuamente de MQTT?

Las causas habituales son una fuente de alimentación débil, una señal de 2,4 GHz pobre o un ahorro de energía del Wi-Fi demasiado agresivo. Revisa vcgencmd get_throttled, el RSSI del mensaje de salud y prueba a desactivar el ahorro de energía.

¿La Zero 2 W admite MQTT 5?

Sí. MQTT 5 es una función de la librería cliente, y paho-mqtt 2.x lo admite por completo, incluidas la caducidad de mensajes y las user properties.

Artículos relacionados

Fiabilidad de la Raspberry Pi: cómo usar una Pi 24/7 como gateway IoT

Una guía práctica para mantener un gateway MQTT con Raspberry Pi funcionando durante meses: desgaste del almacenamiento, sistemas de archivos de solo lectura, alimentación, refrigeración, watchdogs de hardware y software y monitorización remota de la salud.

9 min de lectura

Pico W vs Pico 2 W para MQTT: rendimiento, memoria y TLS de RP2040 frente a RP2350

La Pico 2 W mantiene el formato y el chip Wi-Fi de la Pico W, pero sustituye el RP2040 por el RP2350, más rápido. Esta comparativa analiza qué significa para los dispositivos MQTT: CPU, memoria, TLS, funciones de seguridad, soporte de software y qué placa comprar para cada proyecto.

9 min de lectura

Registro de accesos Raspberry Pi RFID MQTT con el lector RC522

Conecta un lector RFID RC522 a una Raspberry Pi, lee etiquetas en Python, compáralas con una lista blanca local y publica cada intento de acceso como un evento MQTT que pueden consumir registradores, dashboards y herramientas de alertas.

8 min de lectura

Todos los artículos →

Tu broker MQTT privado, a unos pocos clics

Crea una cuenta, obtén las credenciales de tu broker y conecta tu primer dispositivo, sin servidores que instalar, parchear ni escalar.