ESP32 e Arduino

Tutorial Arduino UNO R4 WiFi MQTT: Publique Dados de Sensores com ArduinoMqttClient

Conecte o Arduino UNO R4 WiFi a um broker MQTT com WiFiS3 e ArduinoMqttClient, publique leituras analógicas, controle a matriz de LEDs a partir do seu notebook e migre para TLS na porta 8883.

Placa Arduino UNO R4 WiFi com a matriz de LEDs acesa, ilustrando uma conexão MQTT do Arduino UNO R4 WiFi com a nuvem
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

O Arduino UNO R4 WiFi traz Wi-Fi para o conhecido formato UNO, o que o torna uma ótima primeira placa para um projeto de Arduino UNO R4 WiFi com MQTT. Neste tutorial, você vai usar a biblioteca WiFiS3 e o ArduinoMqttClient oficial para publicar leituras de um sensor analógico, receber comandos que desenham na matriz de LEDs integrada e depois passar para uma conexão TLS criptografada com suas próprias credenciais.

Como o UNO R4 WiFi Se Comunica com a Rede

O UNO R4 WiFi tem dois chips. O microcontrolador principal é um Renesas RA4M1, que executa o seu sketch. A rede fica a cargo de um módulo ESP32-S3 que funciona como coprocessador Wi-Fi. O seu sketch conversa com ele pela biblioteca WiFiS3, que vem com o pacote "Arduino UNO R4 Boards".

Essa divisão tem duas consequências práticas:

  1. O handshake TLS roda no módulo ESP32-S3, que já vem com um conjunto de certificados raiz comuns. Conexões criptografadas com brokers que usam certificados amplamente confiáveis, como os da Let's Encrypt, geralmente funcionam com WiFiSSLClient sem colar nenhum certificado.
  2. O coprocessador tem seu próprio firmware. Se as conexões se comportarem de forma estranha, atualizar esse firmware é uma das primeiras soluções a tentar.

Para o protocolo MQTT em si, você vai usar o ArduinoMqttClient, a biblioteca oficial mantida pela Arduino. Ela funciona com qualquer objeto Client, incluindo WiFiClient e WiFiSSLClient da WiFiS3.

O Que Você Precisa

Item Observações
Arduino UNO R4 WiFi Não o UNO R4 Minima, que não tem rádio
Arduino IDE 2.x Com "Arduino UNO R4 Boards" instalado pelo Boards Manager
ArduinoMqttClient Instale pelo Gerenciador de Bibliotecas
Um potenciômetro ou qualquer sensor analógico Ligado ao A0 (opcional, o código funciona com o pino flutuando)
Ferramentas de linha de comando do Mosquitto Para testar a partir do seu computador
Uma rede Wi-Fi de 2,4 GHz O módulo não se conecta a redes de 5 GHz

Antes de começar, abra File → Examples → WiFiS3 → CheckFirmwareVersion e faça o upload. Se o monitor serial indicar um firmware desatualizado, atualize-o com o atualizador de firmware da Arduino IDE (Tools → Firmware Updater) ou seguindo as instruções oficiais em docs.arduino.cc.

Passo 1: Publique no Servidor MQTT Público

A primeira versão se conecta sem criptografia ao broker.connectmq.com na porta 1883, o servidor MQTT público (gratuito) oferecido pelo ConnectMQ para testes e protótipos. Conexões anônimas são aceitas desde que o client ID não esteja vazio. Use um prefixo de topic único e não envie dados privados, porque qualquer pessoa pode se inscrever nos topics do servidor MQTT público.

Crie uma segunda aba no sketch chamada arduino_secrets.h:

#define SECRET_SSID "YOUR_WIFI"
#define SECRET_PASS "YOUR_WIFI_PASSWORD"

Depois, o sketch principal:

#include <WiFiS3.h>
#include <ArduinoMqttClient.h>
#include "Arduino_LED_Matrix.h"
#include "arduino_secrets.h"

const char broker[] = "broker.connectmq.com";
const int  port     = 1883;

const char deviceId[]       = "unor4-8d21f0";   // torne-o único
const char topicTelemetry[] = "connectmq/demo/unor4-8d21f0/telemetry";
const char topicCommand[]   = "connectmq/demo/unor4-8d21f0/matrix/set";
const char topicStatus[]    = "connectmq/demo/unor4-8d21f0/status";

WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);
ArduinoLEDMatrix matrix;

unsigned long lastPublish = 0;

// Dois quadros simples para a matriz 12x8
const uint32_t FRAME_ON[]  = { 0xffffffff, 0xffffffff, 0xffffffff };
const uint32_t FRAME_OFF[] = { 0x00000000, 0x00000000, 0x00000000 };

void connectWifi() {
  Serial.print("Connecting to ");
  Serial.println(SECRET_SSID);
  while (WiFi.begin(SECRET_SSID, SECRET_PASS) != WL_CONNECTED) {
    Serial.print(".");
    delay(3000);
  }
  // A WiFiS3 pode informar 0.0.0.0 por um instante; espere um endereço real
  while (WiFi.localIP() == IPAddress(0, 0, 0, 0)) delay(200);
  Serial.print("\nIP address: ");
  Serial.println(WiFi.localIP());
}

void onMqttMessage(int messageSize) {
  String topic = mqttClient.messageTopic();
  String payload;
  while (mqttClient.available()) {
    payload += (char)mqttClient.read();
  }
  Serial.print("Received on ");
  Serial.print(topic);
  Serial.print(": ");
  Serial.println(payload);

  if (payload == "ON")  matrix.loadFrame(FRAME_ON);
  if (payload == "OFF") matrix.loadFrame(FRAME_OFF);
}

bool connectMqtt() {
  mqttClient.setId(deviceId);
  mqttClient.setKeepAliveInterval(30 * 1000L);   // milissegundos

  // O Last Will precisa ser definido antes de connect()
  mqttClient.beginWill(topicStatus, true, 1);
  mqttClient.print("offline");
  mqttClient.endWill();

  Serial.print("Connecting to MQTT broker... ");
  if (!mqttClient.connect(broker, port)) {
    Serial.print("failed, error = ");
    Serial.println(mqttClient.connectError());
    return false;
  }
  Serial.println("connected");

  mqttClient.onMessage(onMqttMessage);
  mqttClient.subscribe(topicCommand, 1);

  mqttClient.beginMessage(topicStatus, true, 1);   // retida, QoS 1
  mqttClient.print("online");
  mqttClient.endMessage();
  return true;
}

void setup() {
  Serial.begin(115200);
  while (!Serial && millis() < 3000) {}
  matrix.begin();
  connectWifi();
  while (!connectMqtt()) delay(5000);
}

void loop() {
  if (WiFi.status() != WL_CONNECTED) connectWifi();
  if (!mqttClient.connected()) {
    delay(5000);
    connectMqtt();
    return;
  }

  mqttClient.poll();   // envia os pings de keep alive e entrega as mensagens

  if (millis() - lastPublish > 5000) {
    lastPublish = millis();
    int raw = analogRead(A0);
    mqttClient.beginMessage(topicTelemetry);
    mqttClient.print("{\"a0\":");
    mqttClient.print(raw);
    mqttClient.print(",\"rssi\":");
    mqttClient.print(WiFi.RSSI());
    mqttClient.print(",\"uptime\":");
    mqttClient.print(millis() / 1000);
    mqttClient.print("}");
    mqttClient.endMessage();
  }
}

Acompanhe as mensagens e desenhe na matriz a partir do seu computador:

mosquitto_sub -h broker.connectmq.com -p 1883 -i pc-8d21f0 -t "connectmq/demo/unor4-8d21f0/#" -v
mosquitto_pub -h broker.connectmq.com -p 1883 -i ctl-8d21f0 -t "connectmq/demo/unor4-8d21f0/matrix/set" -m ON

Gire o potenciômetro, e o valor de a0 deve acompanhar em até cinco segundos.

Em Que o ArduinoMqttClient Difere do PubSubClient

Se você já usou o PubSubClient, três coisas vão parecer diferentes:

  • As mensagens são enviadas em stream. beginMessage(), print() e endMessage() permitem montar um payload parte por parte, sem um grande buffer de string. Isso combina bem com a RAM do UNO R4.
  • As mensagens recebidas são lidas como um stream. O callback onMessage recebe apenas o tamanho; você chama messageTopic() e depois read() até available() retornar zero.
  • Publicação com QoS 1 e 2 é suportada, assim como retained messages e um Last Will montado com beginWill()/endWill().

Você ainda precisa chamar poll() regularmente, assim como chama loop() no PubSubClient. Chamadas longas de delay() em loop() atrasam os pings de keep alive e as mensagens recebidas. Nosso guia da biblioteca ArduinoMqttClient cobre toda a API, incluindo o significado de cada valor de connectError().

Passo 2: Arduino UNO R4 WiFi MQTT sobre TLS

Para qualquer coisa além de experimentos, use um broker privado com credenciais e TLS. Em um broker MQTT gerenciado como o ConnectMQ, você cria um broker no portal e recebe usuário, senha e client ID. Graças ao conjunto de certificados do módulo Wi-Fi, migrar para TLS exige mudar só algumas linhas:

WiFiSSLClient wifiClient;            // antes era WiFiClient
MqttClient mqttClient(wifiClient);

const char broker[] = "broker.connectmq.com";
const int  port     = 8883;          // MQTT sobre TLS

bool connectMqtt() {
  mqttClient.setId("YOUR_CLIENT_ID");
  mqttClient.setUsernamePassword("YOUR_USERNAME", "YOUR_PASSWORD");
  mqttClient.setKeepAliveInterval(30 * 1000L);
  if (!mqttClient.connect(broker, port)) {
    Serial.print("TLS MQTT failed, error = ");
    Serial.println(mqttClient.connectError());
    return false;
  }
  // inscreva-se e publique como antes
  return true;
}

Guarde as credenciais em arduino_secrets.h, e não no sketch principal, para não fazer commit delas por acidente. O ConnectMQ vincula os client IDs às credenciais emitidas, então copie o client ID exatamente. Em um broker privado, você também pode dispensar o prefixo connectmq/demo/ e projetar uma árvore de topics para o seu projeto. O artigo boas práticas de segurança MQTT lista outras medidas de proteção.

Projetando Topics e Payloads Que Escalam

Uma única placa no servidor MQTT público pode usar qualquer estrutura, mas vale a pena projetar os topics como se você fosse ter dez placas no mês que vem, espalhadas por uma fazenda ou por uma planta em Joinville. Uma estrutura previsível permite que dashboards se inscrevam com curingas e mantém os comandos bem separados da telemetria.

Topic Direção QoS Retido Finalidade
<prefix>/<deviceId>/telemetry A placa publica 0 Não Leituras periódicas dos sensores
<prefix>/<deviceId>/status A placa publica, Will 1 Sim Presença online / offline
<prefix>/<deviceId>/matrix/set A placa se inscreve 1 Não Comandos de apps ou scripts
<prefix>/<deviceId>/config A placa se inscreve 1 Sim Configurações aplicadas a cada inicialização

O topic config retido é um truque útil: publique uma vez o intervalo de publicação ou o limite desejado com a flag retain, e toda vez que a placa se reconectar ela recebe as configurações mais recentes na hora, sem nenhuma lógica extra de requisição no firmware.

Mantenha os payloads compactos. O RA4M1 do UNO R4 tem 32 KB de SRAM, o que é generoso em comparação com o UNO clássico, mas ainda é pouco, então evite montar objetos String grandes em sketches que rodam por muito tempo. Enviar em stream com print(), como no exemplo, mantém o uso de memória estável. Para entradas analógicas ruidosas, tire a média de várias amostras de analogRead() antes de publicar e considere publicar apenas quando o valor mudar mais do que um pequeno limite. Menos mensagens, e mais significativas, aliviam a rede e são mais fáceis de ler em um dashboard.

Checklist de Solução de Problemas

  1. connectError() retorna -2 (conexão recusada) ou a chamada de conexão falha na hora: host ou porta errados, ou sem Wi-Fi. Confirme que a placa tem um endereço IP real, e não 0.0.0.0.
  2. A 1883 sem criptografia funciona, mas a 8883 falha: atualize o firmware do módulo Wi-Fi e confirme que usou WiFiSSLClient, e não WiFiClient.
  3. Erro 4 (usuário ou senha incorretos) ou 5 (não autorizado): confira novamente os três valores do portal, incluindo o client ID.
  4. A conexão cai depois de um tempo: uma chamada bloqueante em loop() impediu poll() de rodar, ou outro dispositivo usa o mesmo client ID.
  5. Nenhuma mensagem chega: onMessage() não foi registrado, ou você se inscreveu antes de connect() ter sucesso.
  6. O upload funciona, mas o monitor serial fica vazio: ajuste o monitor para 115200 baud; o R4 usa USB nativo, então abra o monitor depois que o upload terminar.

Próximos Passos

Com uma conexão confiável, adicione um sensor de verdade e monte um dashboard. Se você precisa de mais GPIOs, Bluetooth ou processamento local, um ESP32 pode ser mais adequado; o tutorial IoT com ESP32 mostra um projeto completo. Se você tem outro Arduino, o guia de MQTT com Arduino Nano 33 IoT segue o mesmo padrão de biblioteca com a WiFiNINA.

Coloque Seu UNO R4 Online com o ConnectMQ

O ConnectMQ é um broker MQTT gerenciado, ou seja, um broker MQTT na nuvem com suporte a MQTT 3.1.1 e 5.0, TLS na 8883 e WebSockets para dashboards no navegador. O portal inclui um cliente MQTT no navegador e um explorador de topics ao vivo para você ver as leituras do seu UNO chegando. Crie um broker Serverless gratuito em app.connectmq.com, sem cartão de crédito, e migre seu sketch para TLS hoje mesmo.

Perguntas frequentes

Preciso enviar um certificado raiz para o UNO R4 WiFi?

Normalmente não. O módulo Wi-Fi ESP32-S3 traz um conjunto de certificados raiz comuns, então o WiFiSSLClient consegue verificar brokers que usam autoridades amplamente confiáveis, como a Let's Encrypt. Se a verificação falhar, atualize primeiro o firmware do módulo.

Posso usar o PubSubClient no UNO R4 WiFi?

Sim, o PubSubClient funciona com qualquer Client do Arduino, incluindo os clientes da WiFiS3. O ArduinoMqttClient é a opção com suporte oficial e acrescenta publicação com QoS 1 e 2.

O UNO R4 WiFi suporta MQTT 5?

O ArduinoMqttClient implementa MQTT 3.1.1, que o ConnectMQ suporta totalmente junto com o MQTT 5. Seus dashboards e backends com MQTT 5 podem se inscrever nos mesmos topics.

Por que meu UNO R4 WiFi mostra o IP 0.0.0.0?

A WiFiS3 pode informar que está conectada antes de o DHCP terminar. Espere até WiFi.localIP() retornar um endereço real antes de se conectar ao broker, como faz o exemplo.

Artigos relacionados

Exemplo de MQTT com ESP-IDF: Monte um Cliente esp-mqtt do Zero

Monte um projeto ESP-IDF a partir de uma pasta vazia com o componente esp-mqtt: configuração do Wi-Fi em modo station, o handler de eventos MQTT, publicação e inscrição, propriedades do MQTT 5 e TLS com o bundle de certificados.

8 min de leitura

Usando os Recursos do MQTT 5 do esp-mqtt no ESP32 com ESP-IDF

Um projeto ESP-IDF prático que ativa o MQTT 5.0 no esp-mqtt e usa user properties, expiração de mensagens, topic aliases, expiração de sessão e response topics com um broker MQTT 5 real.

8 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.