ESP32 e Arduino

Arduino Nano 33 IoT MQTT com WiFiNINA: Transmita Dados da IMU via SSL

Publique leituras do acelerômetro e do giroscópio do Arduino Nano 33 IoT em um broker MQTT usando WiFiNINA, WiFiSSLClient e ArduinoMqttClient e depois reforce a segurança com credenciais e um Last Will.

Placa Arduino Nano 33 IoT transmitindo dados do sensor de movimento em uma configuração Arduino Nano 33 IoT MQTT via SSL
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 Nano 33 IoT reúne Wi-Fi, uma IMU de 6 eixos e um elemento de segurança em uma placa minúscula, o que torna os projetos de Arduino Nano 33 IoT com MQTT ideais para monitoramento de movimento. Neste guia, você vai transmitir dados do acelerômetro e do giroscópio por uma conexão SSL criptografada usando WiFiNINA e ArduinoMqttClient. Também vai adicionar um Last Will, manter a taxa de mensagens dentro dos limites do broker e resolver os erros de certificado mais comuns.

A Arquitetura do Nano 33 IoT em Um Minuto

A placa combina três chips que importam para este projeto:

Componente Papel em um projeto MQTT
SAMD21 (Arm Cortex-M0+) Executa o seu sketch
u-blox NINA-W102 Coprocessador Wi-Fi; cuida do TCP e do handshake SSL/TLS
LSM6DS3 Acelerômetro de 3 eixos e giroscópio de 3 eixos
ATECC608A Elemento criptográfico, útil para autenticação avançada baseada em certificados

O seu sketch conversa com o módulo NINA pela biblioteca WiFiNINA. O firmware do NINA armazena uma lista de certificados raiz, então o WiFiSSLClient consegue verificar a maioria das autoridades certificadoras conhecidas sem mudanças no código. Esse é o principal motivo pelo qual esta placa lida com conexões SSL mais facilmente do que um ESP8266: o trabalho pesado acontece no coprocessador.

Pré-requisitos

  1. Arduino IDE 2.x com Arduino SAMD Boards (32-bits ARM Cortex-M0+) instalado pelo Boards Manager.
  2. Bibliotecas do Gerenciador de Bibliotecas: WiFiNINA, ArduinoMqttClient e Arduino_LSM6DS3.
  3. Uma rede Wi-Fi de 2,4 GHz.
  4. Ferramentas de linha de comando do Mosquitto no seu computador, para testes.
  5. Firmware do NINA atualizado. Faça o upload de File → Examples → WiFiNINA → Tools → CheckWiFiNINAFirmware e atualize com Tools → WiFi101 / WiFiNINA Firmware Updater se necessário. Firmware antigo é a principal causa de falhas de SSL.

Passo 1: Leia a IMU

Antes de adicionar a rede, confirme que o sensor funciona:

#include <Arduino_LSM6DS3.h>

void setup() {
  Serial.begin(115200);
  while (!Serial) {}
  if (!IMU.begin()) {
    Serial.println("IMU not found");
    while (true) {}
  }
  Serial.print("Accelerometer sample rate: ");
  Serial.println(IMU.accelerationSampleRate());
}

void loop() {
  float x, y, z;
  if (IMU.accelerationAvailable()) {
    IMU.readAcceleration(x, y, z);
    Serial.print(x); Serial.print('\t');
    Serial.print(y); Serial.print('\t');
    Serial.println(z);
  }
  delay(200);
}

Com a placa deitada sobre a mesa, z deve ficar perto de 1,0 (um g). Incline a placa e veja os valores mudarem.

Passo 2: Arduino Nano 33 IoT MQTT via SSL

Você vai se conectar ao broker.connectmq.com na porta 8883. O certificado do broker é emitido pela Let's Encrypt, cuja raiz está incluída no firmware atual do NINA, então não é preciso colar nenhum certificado no sketch. Para o primeiríssimo teste, você pode usar o servidor MQTT público (gratuito) de forma anônima; ele exige apenas um client ID único e não vazio. Lembre-se de que os topics públicos podem ser lidos por qualquer pessoa.

Crie o arduino_secrets.h:

#define SECRET_SSID "YOUR_WIFI"
#define SECRET_PASS "YOUR_WIFI_PASSWORD"
// Deixe vazio para o broker público, preencha para o seu broker privado do ConnectMQ
#define SECRET_MQTT_CLIENT_ID "nano33-c7e2a4"
#define SECRET_MQTT_USER ""
#define SECRET_MQTT_PASS ""

O sketch principal publica uma mensagem JSON compacta com aceleração e rotação cinco vezes por segundo, o que fica bem dentro do limite do servidor MQTT público de 10 mensagens por segundo por cliente:

#include <WiFiNINA.h>
#include <ArduinoMqttClient.h>
#include <Arduino_LSM6DS3.h>
#include "arduino_secrets.h"

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

const char topicImu[]    = "connectmq/demo/nano33-c7e2a4/imu";
const char topicStatus[] = "connectmq/demo/nano33-c7e2a4/status";
const char topicRate[]   = "connectmq/demo/nano33-c7e2a4/rate/set";

WiFiSSLClient sslClient;
MqttClient mqttClient(sslClient);

unsigned long publishIntervalMs = 200;   // 5 mensagens por segundo
unsigned long lastPublish = 0;

void connectWifi() {
  if (WiFi.status() == WL_NO_MODULE) {
    Serial.println("WiFi module not found");
    while (true) {}
  }
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print("Connecting to ");
    Serial.println(SECRET_SSID);
    WiFi.begin(SECRET_SSID, SECRET_PASS);
    delay(5000);
  }
  Serial.print("IP: ");
  Serial.println(WiFi.localIP());
}

void onMqttMessage(int size) {
  char buf[16];
  int i = 0;
  while (mqttClient.available() && i < (int)sizeof(buf) - 1) {
    buf[i++] = (char)mqttClient.read();
  }
  buf[i] = '\0';
  unsigned long ms = strtoul(buf, nullptr, 10);
  if (ms >= 100 && ms <= 60000) {          // nunca mais rápido que 10 msg/s
    publishIntervalMs = ms;
    Serial.print("New interval: ");
    Serial.println(publishIntervalMs);
  }
}

bool connectMqtt() {
  mqttClient.setId(SECRET_MQTT_CLIENT_ID);
  if (strlen(SECRET_MQTT_USER) > 0) {
    mqttClient.setUsernamePassword(SECRET_MQTT_USER, SECRET_MQTT_PASS);
  }
  mqttClient.setKeepAliveInterval(30 * 1000L);
  mqttClient.setConnectionTimeout(10 * 1000L);

  mqttClient.beginWill(topicStatus, true, 1);
  mqttClient.print("offline");
  mqttClient.endWill();

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

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

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

void setup() {
  Serial.begin(115200);
  unsigned long start = millis();
  while (!Serial && millis() - start < 3000) {}

  if (!IMU.begin()) {
    Serial.println("IMU init failed");
    while (true) {}
  }
  connectWifi();
  while (!connectMqtt()) delay(5000);
}

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

  if (millis() - lastPublish >= publishIntervalMs &&
      IMU.accelerationAvailable() && IMU.gyroscopeAvailable()) {
    lastPublish = millis();
    float ax, ay, az, gx, gy, gz;
    IMU.readAcceleration(ax, ay, az);   // g
    IMU.readGyroscope(gx, gy, gz);      // graus por segundo

    // Envia o JSON direto em stream; print(float, digits) evita problemas de suporte a float no printf
    mqttClient.beginMessage(topicImu);
    mqttClient.print("{\"ax\":"); mqttClient.print(ax, 3);
    mqttClient.print(",\"ay\":"); mqttClient.print(ay, 3);
    mqttClient.print(",\"az\":"); mqttClient.print(az, 3);
    mqttClient.print(",\"gx\":"); mqttClient.print(gx, 1);
    mqttClient.print(",\"gy\":"); mqttClient.print(gy, 1);
    mqttClient.print(",\"gz\":"); mqttClient.print(gz, 1);
    mqttClient.print("}");
    mqttClient.endMessage();
  }
}

Acompanhe o stream e diminua a taxa a partir do seu computador:

mosquitto_sub -h broker.connectmq.com -p 1883 -i pc-c7e2a4 -t "connectmq/demo/nano33-c7e2a4/#" -v
mosquitto_pub -h broker.connectmq.com -p 1883 -i ctl-c7e2a4 -t "connectmq/demo/nano33-c7e2a4/rate/set" -m 1000

Repare que o seu notebook usa a porta 1883 sem criptografia, enquanto a placa usa SSL na 8883. Os dois alcançam os mesmos topics no mesmo broker.

O payload é enviado em stream com print(value, digits) em vez de snprintf. O suporte a float em funções no estilo printf varia entre os cores do Arduino, enquanto print() formata floats da mesma forma em todos eles, e o envio em stream evita manter a mensagem inteira na RAM.

Passo 3: Migre para Credenciais Privadas

O servidor MQTT público serve para demonstrações, testes e protótipos, mas dados de movimento de máquinas ou pessoas reais não devem ser públicos. Em um broker MQTT gerenciado como o ConnectMQ, você cria um broker no portal e recebe usuário, senha e client ID gerados. Coloque-os no arduino_secrets.h, mantenha a conexão na 8883 e remova o prefixo connectmq/demo/ em favor da sua própria estrutura de topics. Os client IDs ficam vinculados às credenciais emitidas, então o client ID precisa corresponder exatamente.

Para orientações sobre o projeto de topics, rotação de credenciais e privilégio mínimo, leia boas práticas de segurança MQTT.

Escolhendo QoS e Taxa para Dados da IMU

Dados de sensores em alta taxa e mensagens de comando têm necessidades diferentes:

  • Telemetria a 5 Hz ou mais: QoS 0. Perder uma amostra entre centenas não faz diferença, e o QoS 0 evita tráfego extra de confirmações no link com o NINA.
  • Mudanças de taxa e outros comandos: inscreva-se com QoS 1 para que o broker tente a entrega novamente.
  • Status: QoS 1 retido com um Last Will correspondente, para que os dashboards sempre saibam se a placa está online.

Se você precisa de recursos como análise de vibração, considere calcular valores-resumo no dispositivo (por exemplo, a aceleração RMS em um segundo) e publicá-los, em vez das amostras brutas. Isso reduz a largura de banda e fica bem dentro dos limites de mensagens de qualquer plano. Níveis de QoS do MQTT explicados aborda essas escolhas com mais profundidade.

Calculando Resumos de Vibração na Placa

Amostras brutas da IMU são úteis para experimentos, mas, para monitorar um ventilador, uma bomba de uma estação de saneamento ou uma máquina de lavar, normalmente o que importa é o quanto o equipamento está vibrando ao longo do tempo. Calcular a raiz da média dos quadrados (RMS) da magnitude da aceleração em um segundo transforma dezenas de amostras em um único número significativo. Remover antes a componente de 1 g da gravidade faz o valor ficar perto de zero quando a máquina está parada.

float sumSq = 0;
int samples = 0;
unsigned long windowStart = 0;

void sampleVibration() {
  float x, y, z;
  if (IMU.accelerationAvailable()) {
    IMU.readAcceleration(x, y, z);
    float mag = sqrt(x * x + y * y + z * z) - 1.0;   // remove a gravidade
    sumSq += mag * mag;
    samples++;
  }
  if (millis() - windowStart >= 1000 && samples > 0) {
    float rms = sqrt(sumSq / samples);
    mqttClient.beginMessage("connectmq/demo/nano33-c7e2a4/vibration");
    mqttClient.print("{\"rms_g\":");
    mqttClient.print(rms, 4);
    mqttClient.print(",\"n\":");
    mqttClient.print(samples);
    mqttClient.print("}");
    mqttClient.endMessage();
    sumSq = 0;
    samples = 0;
    windowStart = millis();
  }
}

Chame sampleVibration() em loop() junto com mqttClient.poll(). O resultado é uma mensagem por segundo em vez de um stream, e o campo n informa em quantas amostras o valor se baseia. Do lado de quem recebe, um limite sobre rms_g é uma forma simples e eficaz de sinalizar vibração anormal. Calibre-o gravando primeiro alguns minutos de operação normal, porque cada máquina e cada posição de montagem se comportam de forma diferente.

Mantendo a Conexão Saudável

Um registrador de movimento costuma rodar sem supervisão por dias, então se prepare para instabilidades de rede. A lógica de reconexão do sketch tenta de novo a cada poucos segundos, mas a reinicialização de um roteador pode demorar mais, então considere aumentar o intervalo após falhas repetidas para não sobrecarregar a rede. Publique o topic de status retido a cada reconexão bem-sucedida e registre WiFi.RSSI() junto com seus dados: sinal fraco é o motivo mais comum para uma placa dentro de um gabinete metálico ficar caindo. Se as leituras pararem enquanto o status ainda indica online, verifique se poll() é chamado a cada passagem por loop().

Checklist de Solução de Problemas

  1. connect() falha na 8883, mas funciona na 1883 com WiFiClient: atualize o firmware do NINA. Se você usa um broker com uma CA incomum, envie o certificado raiz dela com a ferramenta de certificados do atualizador de firmware.
  2. "WiFi module not found": placa errada selecionada ou biblioteca WiFiNINA desatualizada.
  3. Erro 2 (identificador rejeitado): client ID vazio.
  4. Erro 4 ou 5: as credenciais ou o client ID não correspondem ao que o portal emitiu.
  5. Desconexões após alguns minutos: algo em loop() bloqueia o poll(), ou duas placas compartilham um client ID.
  6. Valores da IMU congelados: verifique se IMU.begin() teve sucesso e se você só lê quando accelerationAvailable() é verdadeiro.

Guias Relacionados

O guia da biblioteca ArduinoMqttClient se aprofunda na API usada aqui, e o tutorial Arduino UNO R4 WiFi MQTT mostra o mesmo padrão na pilha WiFiS3. Para uma visão mais ampla de projetos MQTT embarcados, veja o tutorial IoT com ESP32.

Envie os Dados do Seu Nano 33 IoT para o ConnectMQ

O ConnectMQ é um broker MQTT gerenciado, ou seja, um broker MQTT na nuvem com SSL na porta 8883, um certificado Let's Encrypt em que o módulo NINA confia de fábrica e um portal com explorador de topics ao vivo e regras de alerta por limite, o que combina bem com alertas de movimento e vibração. Crie um broker Serverless gratuito em app.connectmq.com, sem precisar de cartão de crédito.

Perguntas frequentes

O Arduino Nano 33 IoT suporta MQTT via SSL?

Sim. O módulo Wi-Fi NINA-W102 realiza o handshake SSL/TLS, e o WiFiSSLClient combinado com o ArduinoMqttClient se conecta à porta 8883 com muito pouco código.

Preciso adicionar um certificado raiz para o ConnectMQ?

Normalmente não. O ConnectMQ usa um certificado Let's Encrypt, e a raiz dele faz parte do firmware atual do NINA. Atualize o firmware se a verificação falhar.

Com que velocidade posso publicar dados da IMU?

Mantenha o dispositivo dentro dos limites do seu broker. No servidor MQTT público, são 10 mensagens por segundo por cliente; para taxas de amostragem maiores, agrupe várias leituras em uma mensagem ou publique resumos calculados.

Posso usar o ATECC608A para autenticação MQTT?

O elemento criptográfico pode armazenar chaves para autenticação baseada em certificados com brokers que suportam certificados de cliente. Na configuração deste guia, você se autentica com o usuário, a senha e o client ID emitidos no portal.

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.