A automação de estufa mantém a temperatura e a umidade na faixa de que suas plantas precisam, acionando ventiladores, aquecedores e nebulização automaticamente, em vez de depender de alguém para abrir as janelas na hora certa, seja numa estufa de hortaliças ou numa produção de flores no interior paulista. Neste tutorial você vai projetar os tópicos MQTT, escrever um fluxo Node-RED que controla três atuadores com histerese e intertravamentos, adicionar um watchdog para dados desatualizados e tornar os nós de relé seguros por conta própria caso a rede caia.
A arquitetura
O sistema tem três partes que só se comunicam por meio de um broker MQTT:
Climate sensor (ESP32 + SHT31/BME280)
| publishes telemetry every 30 s
v
MQTT broker <----> Node-RED (decision logic)
^ |
| publishes /set |
+---------------------+
|
Relay node (ESP32 + 3 relays): fan, heater, mister
publishes /state after acting
Separar sensoriamento, lógica e atuação traz benefícios reais. Você pode trocar o sensor sem mexer na lógica, alterar setpoints pelo celular sem regravar firmware e, mais tarde, adicionar um painel ou um registrador de dados como mais um assinante. Se precisar relembrar o papel dos brokers, leia antes sobre o que faz um broker MQTT.
Projeto de tópicos para automação de estufa
Use o servidor MQTT público (gratuito) durante o desenvolvimento. Substitua g2w6n3 por uma sequência aleatória sua, pois o servidor MQTT público é compartilhado, pode ser lido por qualquer pessoa e serve apenas para testes e protótipos.
| Tópico | Direção | Payload | Retido |
|---|---|---|---|
connectmq/demo/g2w6n3/greenhouse/climate |
sensor para todos | {"temp":27.4,"hum":58.2} |
sim |
connectmq/demo/g2w6n3/greenhouse/setpoints |
celular/painel para o Node-RED | {"heat_on":12,"vent_on":28,"mist_on":45} |
sim |
connectmq/demo/g2w6n3/greenhouse/fan/set |
Node-RED para o relé | ON / OFF |
não |
connectmq/demo/g2w6n3/greenhouse/heater/set |
Node-RED para o relé | ON / OFF |
não |
connectmq/demo/g2w6n3/greenhouse/mister/set |
Node-RED para o relé | ON / OFF |
não |
connectmq/demo/g2w6n3/greenhouse/<actuator>/state |
relé para todos | ON / OFF |
sim |
connectmq/demo/g2w6n3/greenhouse/alarm |
Node-RED para todos | {"type":"stale_sensor"} |
não |
Os setpoints são retidos para que o Node-RED receba os valores atuais logo após reiniciar. Os comandos não são retidos, para que um relé que reinicia não execute de novo uma instrução antiga.
Construindo o fluxo no Node-RED
Crie o fluxo com estes nós. Se você está começando no Node-RED, o tutorial de Node-RED com MQTT cobre o básico da configuração do broker.
| Nó | Configuração |
|---|---|
config mqtt-broker |
Servidor broker.connectmq.com, porta 1883, client ID nodered-gh-g2w6n3, protocolo MQTT 3.1.1 |
mqtt in "climate" |
Tópico connectmq/demo/g2w6n3/greenhouse/climate, saída "a parsed JSON object" |
mqtt in "setpoints" |
Tópico connectmq/demo/g2w6n3/greenhouse/setpoints, saída "a parsed JSON object" |
function "climate logic" |
Código abaixo, 1 saída, ligado aos dois nós mqtt in |
mqtt out "actuators" |
Tópico vazio (vem de msg.topic), QoS 1, retain false |
inject "watchdog tick" |
Repetir a cada 60 segundos |
function "watchdog" |
Código abaixo, ligado ao mesmo mqtt out |
A função de lógica de clima
const BASE = "connectmq/demo/g2w6n3/greenhouse";
// Valores padrão, substituídos pela mensagem retida de setpoints
const sp = flow.get("sp") || { heat_on: 12, heat_off: 14, vent_on: 28, vent_off: 25, mist_on: 45, mist_off: 55, mist_max_temp: 35 };
if (msg.topic.endsWith("/setpoints")) {
const p = msg.payload || {};
if (p.heat_on !== undefined) { sp.heat_on = p.heat_on; sp.heat_off = p.heat_on + 2; }
if (p.vent_on !== undefined) { sp.vent_on = p.vent_on; sp.vent_off = p.vent_on - 3; }
if (p.mist_on !== undefined) { sp.mist_on = p.mist_on; sp.mist_off = p.mist_on + 10; }
flow.set("sp", sp);
node.status({ fill: "blue", shape: "ring", text: "setpoints " + JSON.stringify(p) });
return null;
}
const t = Number(msg.payload.temp);
const h = Number(msg.payload.hum);
if (!Number.isFinite(t) || !Number.isFinite(h) || t < -20 || t > 60 || h < 0 || h > 100) {
node.warn("Implausible reading ignored: " + JSON.stringify(msg.payload));
return null;
}
flow.set("lastSeen", Date.now());
const st = flow.get("state") || { fan: "OFF", heater: "OFF", mister: "OFF" };
const next = Object.assign({}, st);
// Aquecimento com histerese
if (t <= sp.heat_on) next.heater = "ON";
else if (t >= sp.heat_off) next.heater = "OFF";
// Ventilação com histerese
if (t >= sp.vent_on) next.fan = "ON";
else if (t <= sp.vent_off) next.fan = "OFF";
// Nebulização só quando estiver quente o bastante para evaporar, sem resfriar demais a cultura
if (h <= sp.mist_on && t > 18 && t < sp.mist_max_temp) next.mister = "ON";
else if (h >= sp.mist_off || t <= 18) next.mister = "OFF";
// Intertravamentos: nunca aquecer e ventilar juntos, nunca nebulizar enquanto aquece
if (next.heater === "ON") { next.fan = "OFF"; next.mister = "OFF"; }
flow.set("state", next);
const out = [];
for (const a of ["fan", "heater", "mister"]) {
if (next[a] !== st[a] || msg.forceSend) {
out.push({ topic: `${BASE}/${a}/set`, payload: next[a] });
}
}
node.status({ fill: "green", shape: "dot", text: `${t}°C ${h}% F:${next.fan} H:${next.heater} M:${next.mister}` });
return [out];
Retornar [out] envia cada mensagem do array, uma após a outra, pela única saída até o nó mqtt out. Os comandos só são enviados quando um estado muda, o que mantém o tráfego baixo e os logs do relé legíveis.
A função de watchdog
const BASE = "connectmq/demo/g2w6n3/greenhouse";
const last = flow.get("lastSeen") || 0;
const ageMin = (Date.now() - last) / 60000;
if (last && ageMin > 5 && !flow.get("staleAlarm")) {
flow.set("staleAlarm", true);
flow.set("state", { fan: "OFF", heater: "OFF", mister: "OFF" });
return [[
{ topic: `${BASE}/heater/set`, payload: "OFF" },
{ topic: `${BASE}/mister/set`, payload: "OFF" },
{ topic: `${BASE}/alarm`, payload: JSON.stringify({ type: "stale_sensor", minutes: Math.round(ageMin) }) }
]];
}
if (ageMin <= 5) flow.set("staleAlarm", false);
return null;
Se o sensor parar de enviar dados, o watchdog desliga o aquecedor e a nebulização, porque agir com dados antigos é pior do que não fazer nada. O ventilador não é alterado; sem dados, quem decide é a proteção do próprio relé (veja abaixo).
Testando o fluxo
Simule uma tarde quente e seca e, em seguida, uma noite fria:
mosquitto_pub -h broker.connectmq.com -p 1883 -i sim-g2w6n3 -r \
-t 'connectmq/demo/g2w6n3/greenhouse/climate' -m '{"temp":30.2,"hum":40}'
mosquitto_pub -h broker.connectmq.com -p 1883 -i sim-g2w6n3 -r \
-t 'connectmq/demo/g2w6n3/greenhouse/climate' -m '{"temp":10.5,"hum":80}'
mosquitto_sub -h broker.connectmq.com -p 1883 -i mon-g2w6n3 \
-t 'connectmq/demo/g2w6n3/greenhouse/+/set' -v
A primeira mensagem deve ligar o ventilador e a nebulização; a segunda deve desligar os dois e ligar o aquecedor. Altere os setpoints ao vivo publicando {"vent_on":26} no tópico de setpoints.
Tornando o nó de relé seguro por conta própria
O Node-RED decide, mas o nó de relé nunca deve confiar cegamente na rede. Incorpore estas regras ao firmware:
- Tempo máximo de funcionamento por atuador. A nebulização se desliga sozinha depois de, digamos, cinco minutos, mesmo que nenhum
OFFchegue. Uma válvula travada pode encharcar a cultura. - Corte local por sobretemperatura. Se o nó de relé tiver sua própria sonda de temperatura, ele desliga o aquecedor acima de um limite rígido, independentemente dos comandos.
- Estado seguro na desconexão. Quando o MQTT cair por mais de um minuto, aquecedor e nebulização são desligados. Decida se o ventilador deve ligar ou desligar de acordo com o seu clima; em regiões quentes, ventilar costuma ser o padrão mais seguro.
- Publicar o estado após agir. Os tópicos
/statemostram o que de fato aconteceu, o que permite ao Node-RED e aos painéis detectar um relé que ignora comandos. - Last will. Conecte com uma mensagem will
offlineretida em um tópico de status, para que um relé ausente fique visível imediatamente.
Para a ligação dos relés e um sketch de ESP32 que assina tópicos de comando, veja o tutorial de relé com ESP32 e MQTT. Aquecedores e ventiladores ligados à rede elétrica devem ser acionados por contatores devidamente dimensionados e instalados por um profissional qualificado.
Dicas de ajuste
- Faixas de histerese de 2 a 3 °C evitam ciclos curtos, que desgastam relés e motores.
- A posição do sensor importa mais do que a sua precisão: proteja o sensor do sol direto, instale-o na altura das plantas e garanta circulação de ar.
- Setpoints de dia e de noite são fáceis de adicionar: um nó
injectno nascer e no pôr do sol pode publicar novos setpoints retidos. - Registre tudo. Um fluxo Node-RED ou uma instância do Telegraf assinando
greenhouse/#fornece o histórico para ajustar os setpoints ao longo de uma safra.
Para uma visão mais ampla de sensores, conectividade e projeto de tópicos em uma fazenda inteira, leia o guia de agricultura inteligente com IoT e combine esta estufa com o sistema de irrigação automática para a rega.
Acompanhando a estufa remotamente
A automação só é confiável se você consegue ver o que ela está fazendo. Três visões atendem à maioria das necessidades. Uma página do Node-RED Dashboard com medidores de temperatura e umidade, interruptores que mostram os tópicos /state dos atuadores e controles deslizantes que publicam novos setpoints oferece aos produtores um painel de controle simples no celular. Um historiador, como o Telegraf gravando no InfluxDB, permite comparar as noites desta semana com as da semana passada e identificar um aquecedor que funciona mais tempo do que antes. E uma visualização de tópicos ao vivo no lado do broker mostra cada mensagem de comando e de estado no momento em que acontece. Juntos, estado ao vivo e histórico formam a base de um gêmeo digital simples da estufa.
Quando o broker é a ConnectMQ, o explorador de tópicos ao vivo e o painel do portal oferecem essa última visão sem instalar nada, e o cliente MQTT no navegador é útil para publicar um setpoint de teste a partir de um notebook dentro da estufa. Seja qual for a ferramenta, compare /set com /state regularmente: um comando que nunca é confirmado indica um relé com defeito, um fio solto ou um nó que perdeu o Wi-Fi.
Indo para produção
Quando a lógica estiver funcionando, saia do servidor MQTT público. Crie um broker privado, mude o nó mqtt-broker para a porta 8883 com TLS habilitado e informe o usuário, a senha e o client ID emitidos. Cada dispositivo recebe suas próprias credenciais. Um broker MQTT gerenciado mantém o broker no ar mesmo quando o PC da estufa não está, e permite verificar o clima de qualquer lugar. O guia de automação IoT mostra como esse padrão se estende a casas e edifícios.
Rode sua estufa na ConnectMQ
A ConnectMQ oferece à sua estufa um broker MQTT gerenciado e privado com TLS, um explorador de tópicos ao vivo para acompanhar comandos e estados, e regras de alerta por limite como alarme de reserva para geada ou superaquecimento. Crie um broker Serverless gratuito em app.connectmq.com, sem cartão de crédito, e aponte para ele o Node-RED e seus nós ESP32.
Perguntas frequentes
A automação de estufa funciona sem internet?
Sim, se o broker e o Node-RED estiverem na rede local. Com um broker na nuvem você ganha acesso remoto; por isso, coloque as proteções críticas no firmware do relé para que a estufa continue segura durante uma queda.
Qual sensor de temperatura é o melhor para estufa?
Um SHT31 ou SHT4x lida melhor com umidade alta do que um DHT22. Seja qual for a escolha, proteja-o do sol direto com um abrigo de radiação ventilado.
Por que meu ventilador liga e desliga o tempo todo?
A diferença entre os limites de ligar e desligar é pequena demais, ou o sensor está no fluxo de ar do ventilador. Aumente a histerese e mude o sensor de lugar.
O Node-RED ou o ESP32 deve tomar as decisões de controle?
Use o Node-RED para a lógica flexível e os setpoints, e mantenha limites de segurança simples no ESP32 para que os atuadores entrem em estado seguro se a conexão cair.



