Raspberry Pi

Raspberry Pi DS18B20 MQTT: Publique Várias Sondas de Temperatura 1-Wire

Ative o 1-Wire no Raspberry Pi, ligue várias sondas de temperatura DS18B20 a um único pino GPIO, leia todas em Python sem bibliotecas extras e publique leituras nomeadas e validadas via MQTT.

Várias sondas de temperatura DS18B20 à prova d'água ligadas a um Raspberry Pi em um único barramento 1-Wire, enviando leituras para a nuvem em um projeto raspberry pi ds18b20 mqtt
Rode isso no seu próprio broker MQTTTenha um broker MQTT privado e gerenciado no plano Free e comece com exemplos de código prontos.
Teste grátis Exemplos de código Sem cartão de crédito

Uma montagem Raspberry Pi DS18B20 MQTT é a forma mais robusta de medir temperaturas em vários pontos ao mesmo tempo: freezer e geladeira, tubulações de ida e retorno, um aquário, um fermentador, um painel elétrico ou um rack de servidores. Neste tutorial você vai ativar o barramento 1-Wire, ligar várias sondas à prova d'água a um único pino GPIO, lê-las em Python usando apenas o driver do kernel e publicar leituras nomeadas e validadas via MQTT.

Por que o DS18B20 é uma ótima escolha

O DS18B20 é um sensor digital, então o comprimento do cabo e o ruído elétrico o afetam muito menos do que os sensores analógicos. Cada sonda tem um número de série único de 64 bits gravado de fábrica, o que permite que muitas sondas compartilhem o mesmo fio de dados. As versões à prova d'água vêm em uma capa de aço inox com cabo longo, prontas para líquidos ou uso externo. A precisão é de cerca de meio grau na faixa normal, e a resolução pode chegar a 0,0625 °C.

O melhor de tudo: o Raspberry Pi OS já inclui um driver de kernel para ele. Você não precisa de nenhuma biblioteca Python para ler os sensores; eles aparecem como arquivos.

Ligando uma ou várias sondas

Todas as sondas são ligadas em paralelo aos mesmos três fios:

Fio do DS18B20 (sonda à prova d'água) Raspberry Pi
Vermelho: VDD 3,3 V (pino físico 1)
Preto: GND GND (pino físico 6)
Amarelo: DATA GPIO4 (pino físico 7)

Adicione um resistor de 4,7 k entre DATA e 3,3 V. Esse único pull-up atende o barramento inteiro; não coloque um por sonda. Use o modo de três fios (alimentado), como mostrado, em vez da alimentação parasita, que é menos confiável com várias sondas. Em cabos longos, uma topologia em estrela com muitas ramificações é a mais difícil para o 1-Wire; uma linha única com derivações curtas funciona melhor, e um pull-up menor, como 2,2 k, pode ajudar em barramentos longos.

Ativando o 1-Wire

Ative o barramento com o raspi-config ou adicione o overlay manualmente:

sudo raspi-config nonint do_onewire 0
# ou, de forma equivalente, adicione esta linha a /boot/firmware/config.txt:
# dtoverlay=w1-gpio,gpiopin=4
sudo reboot

Depois de reiniciar, liste as sondas detectadas:

ls /sys/bus/w1/devices/
cat /sys/bus/w1/devices/28-*/w1_slave

Cada sonda aparece como um diretório que começa com 28-. O arquivo w1_slave contém duas linhas: a primeira termina em YES quando a verificação de CRC passou, e a segunda termina com t= seguido da temperatura em milésimos de grau, por exemplo t=21375 para 21,375 °C. A documentação de configuração do Raspberry Pi descreve as opções do overlay 1-Wire.

Dando nome às sondas

Números de série como 28-3c01d0752a8b não dizem nada em um dashboard. Crie um probes.json que associe cada número de série a um nome curto, que passará a fazer parte do topic MQTT:

{
  "28-3c01d0752a8b": "freezer",
  "28-3c01d075f1e2": "fridge",
  "28-0316a2794bff": "outdoor"
}

Para descobrir qual sonda é qual, aqueça uma delas na mão e veja qual leitura sobe. Sondas que não estão no arquivo continuam sendo publicadas com o número de série, então uma sonda recém-adicionada nunca some sem aviso.

Estrutura de topics

Topic Payload Retained
connectmq/demo/b81f2d/house/temp/<name> {"celsius": 4.2, "ts": ...} Não
connectmq/demo/b81f2d/house/temp/all Todas as sondas em um único objeto JSON Não
connectmq/demo/b81f2d/house/status online / offline Sim

Os topics por sonda são ideais para dashboards e regras de alerta sobre um único valor; a mensagem combinada é prática para loggers que gravam uma linha por intervalo. Substitua b81f2d por uma string aleatória sua.

O script Raspberry Pi DS18B20 MQTT

Salve 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):
    """Return degrees Celsius, or None if the probe gives no valid reading."""
    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 é o valor de reset ao ligar
                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()

Nenhuma biblioteca de sensor é necessária; a paho-mqtt é a única dependência:

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

O script relê o probes.json a cada ciclo, então você pode renomear uma sonda sem reiniciar. Sondas ausentes ou com falha aparecem como null na mensagem combinada em vez de serem descartadas, o que torna um cabo rompido visível no dashboard.

As armadilhas clássicas

  1. Uma leitura de exatamente 85,0 °C: a sonda devolveu seu valor padrão de inicialização antes de concluir uma conversão, normalmente por alimentação fraca ou alimentação parasita. O script descarta esse valor.
  2. O w1_slave mostra NO na primeira linha: o CRC falhou por causa de ruído ou de um cabo longo. O script tenta de novo até três vezes.
  3. Sondas aparecem e somem do diretório: conexões frouxas ou barramento sobrecarregado; verifique as soldas e o valor do pull-up.
  4. Nenhum diretório 28-: o 1-Wire não está ativado, o fio de dados não está no GPIO4 ou falta o pull-up.
  5. Ciclos lentos com muitas sondas: cada conversão de 12 bits leva até cerca de três quartos de segundo, e o kernel lê as sondas uma após a outra. Dez sondas levam, portanto, vários segundos por ciclo, o que não é problema com um intervalo de 60 segundos.

Trocando resolução por velocidade

A maioria das aplicações não precisa de passos de 0,0625 °C. Os kernels atuais expõem um arquivo resolution para cada sonda, então você pode reduzi-la e encurtar o tempo de conversão:

cat /sys/bus/w1/devices/28-3c01d0752a8b/resolution
echo 10 | sudo tee /sys/bus/w1/devices/28-3c01d0752a8b/resolution

Com 10 bits o passo é de 0,25 °C e cada conversão termina em uma fração do tempo de 12 bits, o que ajuda quando um barramento tem muitas sondas ou você quer atualizações mais rápidas. A configuração fica na memória volátil da sonda, então volta ao padrão após um ciclo de energia, a menos que você também a grave na EEPROM da sonda; consulte a documentação do w1_therm do seu kernel antes de gravar na EEPROM.

Pense também em onde a sonda fica, e não só em quão precisa ela é. Uma sonda presa a um cano mede o cano com mais precisão quando está bem fixada com uma abraçadeira metálica e coberta por isolamento. Uma sonda no freezer deve ficar suspensa no ar, sem encostar em uma embalagem congelada, a menos que você queira saber justamente a temperatura do alimento.

Acompanhando as leituras

mosquitto_sub -h broker.connectmq.com -p 1883 -i watch-b81f2d \
  -t 'connectmq/demo/b81f2d/house/#' -v

Você verá uma mensagem por sonda e depois a mensagem combinada, a cada minuto. No servidor MQTT público esses topics ficam visíveis para todo mundo, então use apenas dados de teste e um prefixo aleatório; ele serve para testes e protótipos, não para dados de produção.

Próximos passos

Um barramento 1-Wire combina muito bem com um nó compacto; o script roda sem alterações em um nó sensor MQTT com Raspberry Pi Zero 2 W. Se você também quiser medir umidade, combine-o com o guia Raspberry Pi DHT22 MQTT, que usa o mesmo estilo de topics. Para gráficos de longo prazo, a stack Raspberry Pi com Grafana e InfluxDB assina esses topics pelo Telegraf e guarda meses de histórico.

Configuração para produção

Alarmes de freezer e monitoramento de aquecimento merecem uma conexão privada e criptografada. O ConnectMQ é um broker MQTT gerenciado: crie um broker no portal e rode o script com 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

No portal do ConnectMQ, uma regra de alerta por limite em home/kitchen/temp/freezer, por exemplo acima de -12 °C, registra um alerta que você pode revisar no log de alertas. Rode o script como serviço do systemd para que ele reinicie depois de quedas de energia; o tutorial MQTT com Raspberry Pi traz o modelo.

Comece com o ConnectMQ

Envie as leituras das suas sondas para um broker MQTT na nuvem que dashboards, loggers e regras de alerta possam acessar de qualquer lugar. Crie um broker ConnectMQ gratuito no plano Serverless, sem cartão de crédito, cole as credenciais geradas no seu ambiente e conecte via TLS na porta 8883.

Perguntas frequentes

Quantas sondas DS18B20 posso ligar a um único pino do Raspberry Pi?

Muitas sondas podem compartilhar um único barramento graças aos seus números de série únicos. Na prática, o comprimento do cabo e a topologia limitam você antes do espaço de endereços; algumas unidades a algumas dezenas em um barramento bem cabeado é algo realista.

Por que meu DS18B20 marca 85 graus?

85,0 °C é o valor que o sensor guarda depois de ligado, antes da primeira conversão. Normalmente indica um problema de alimentação ou uma leitura feita cedo demais; descarte o valor e verifique a ligação.

Preciso de uma biblioteca Python para ler um DS18B20?

Não. Os drivers de kernel w1-gpio e w1-therm expõem cada sonda como um arquivo em /sys/bus/w1/devices, que o Python puro consegue ler.

Posso usar outro pino GPIO para o 1-Wire?

Sim. Defina dtoverlay=w1-gpio,gpiopin=17 (ou outro pino) em /boot/firmware/config.txt e reinicie.

Artigos relacionados

Registro de Acessos Raspberry Pi RFID MQTT com o Leitor RC522

Ligue um leitor RFID RC522 a um Raspberry Pi, leia tags em Python, confira-as em uma lista de permissões local e publique cada tentativa de acesso como um evento MQTT que loggers, dashboards e ferramentas de alerta podem consumir.

8 min de leitura

Confiabilidade do Raspberry Pi: Rodando um Pi 24/7 como Gateway IoT

Um guia prático para manter um gateway MQTT com Raspberry Pi rodando por meses: desgaste do armazenamento, sistemas de arquivos somente leitura, alimentação, refrigeração, watchdogs de hardware e software e monitoramento remoto de saúde.

9 min de leitura

Pico W vs Pico 2 W para MQTT: Desempenho, Memória e TLS do RP2040 vs RP2350

O Pico 2 W mantém o formato e o chip Wi-Fi do Pico W, mas troca o RP2040 pelo RP2350, mais rápido. Esta comparação mostra o que isso significa para dispositivos MQTT: CPU, memória, TLS, recursos de segurança, suporte de software e qual placa comprar para cada projeto.

9 min de leitura

Todos os artigos →

Seu broker MQTT privado está a poucos cliques de distância

Crie uma conta, receba as credenciais do seu broker e conecte seu primeiro dispositivo — sem servidores para instalar, atualizar ou escalar.