ESP32 e Arduino

SIM7600 MQTT: Publique de um ESP32 via 4G LTE com TinyGSM

Conecte um ESP32 a um broker MQTT via 4G LTE com um modem SIM7600, TinyGSM e PubSubClient, recupere-se de quedas de rede e mantenha o consumo e o custo de dados móveis sob controle.

Placa ESP32 com modem 4G SIM7600 e antena enviando mensagens SIM7600 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

O SIM7600 MQTT permite que um ESP32 publique dados onde não existe Wi-Fi algum: estações de bombeamento, canteiros de obras, veículos, lavouras e gabinetes remotos. Neste tutorial você vai ligar um modem 4G LTE SIM7600, registrá-lo na rede móvel com TinyGSM, conectar o PubSubClient ao servidor MQTT público broker.connectmq.com através do modem e se recuperar de forma limpa de quedas de rede. Você também vai descobrir para onde vão de fato os dados móveis e como manter o consumo mensal baixo.

Como as peças se encaixam

O SIM7600 é um modem celular completo, com pilha TCP/IP própria. O ESP32 conversa com ele por uma UART usando comandos AT. O TinyGSM encapsula esses comandos em uma classe Client do Arduino, a TinyGsmClient, e como o PubSubClient aceita qualquer Client, o código MQTT é quase idêntico ao de um sketch com Wi-Fi.

Camada Componente Responsabilidade
Aplicação Seu sketch Ler sensores, decidir o que publicar
MQTT PubSubClient CONNECT, PUBLISH, SUBSCRIBE, keep-alive
Transporte TinyGsmClient Abre sockets TCP dentro do modem via comandos AT
Modem SIM7600 Registro na rede, contexto PDP, TCP/IP
Rádio Rede LTE e SIM Cobertura, APN, plano de dados

A maioria dos problemas com MQTT celular não é problema de MQTT. São problemas de alimentação, antena, SIM ou APN que aparecem como "o MQTT não conecta". Por isso o sketch verifica cada camada separadamente e registra onde falha.

Hardware

  • Uma placa ESP32 com módulo SIM7600. Placas integradas como a série LilyGO T-SIM7600 são o começo mais fácil; um breakout SIM7600 separado mais um ESP32 DevKit também funciona.
  • Um chip micro ou nano SIM com plano de dados ativo. Chips de dados para IoT são ideais; um chip de celular serve para testes.
  • Uma antena LTE conectada à porta de antena principal. Nunca ligue o modem sem antena.
  • Uma fonte capaz de fornecer os picos de corrente de transmissão do modem. Uma boa célula 18650 ou uma fonte de 5 V de pelo menos 2 A é uma base sensata.

A alimentação é a causa número um de falhas. Modems LTE puxam picos curtos e altos de corrente ao transmitir. Uma porta USB fraca ou fios finos causam quedas de tensão que reiniciam o modem no meio da conexão, e os sintomas parecem aleatórios: às vezes ele registra, às vezes não, às vezes desconecta após algumas mensagens.

Sinal Pino típico na LilyGO T-SIM7600 Função
TX do modem para RX do ESP32 GPIO 26 Dados UART vindos do modem
RX do modem a partir do TX do ESP32 GPIO 27 Dados UART para o modem
PWRKEY GPIO 4 Pulso para ligar o modem
Habilitação de alimentação GPIO 12 Habilita a alimentação do modem em algumas revisões da placa

A atribuição de pinos varia entre placas e revisões. Consulte a documentação da sua placa e ajuste os defines no sketch.

Bibliotecas

Instale pelo Library Manager da Arduino IDE:

  • TinyGSM, de Volodymyr Shymanskyy.
  • PubSubClient, de Nick O'Leary.

O TinyGSM precisa saber o modelo do modem em tempo de compilação, por isso #define TINY_GSM_MODEM_SIM7600 deve aparecer antes do include.

O sketch completo de SIM7600 MQTT

#define TINY_GSM_MODEM_SIM7600
#define TINY_GSM_RX_BUFFER 1024          // larger buffer for incoming MQTT data

#include <TinyGsmClient.h>
#include <PubSubClient.h>

// ---- Board pins (LilyGO T-SIM7600 defaults, adjust for your board) ----
#define MODEM_TX      27
#define MODEM_RX      26
#define MODEM_PWRKEY  4
#define MODEM_POWER   12

// ---- Cellular settings ----
const char APN[]       = "internet";       // from your SIM provider
const char APN_USER[]  = "";
const char APN_PASS[]  = "";
const char SIM_PIN[]   = "";               // leave empty if the SIM has no PIN

// ---- MQTT settings ----
const char* MQTT_HOST = "broker.connectmq.com";
const uint16_t MQTT_PORT = 1883;
const char* CLIENT_ID = "lte-81c3e5";      // unique
const char* BASE = "connectmq/demo/lte-81c3e5";

HardwareSerial SerialAT(1);
TinyGsm modem(SerialAT);
TinyGsmClient gsmClient(modem);
PubSubClient mqtt(gsmClient);

unsigned long lastAttempt = 0, lastPublish = 0;
const unsigned long PUBLISH_INTERVAL = 60000;  // one reading per minute

void powerOnModem() {
  pinMode(MODEM_POWER, OUTPUT);
  digitalWrite(MODEM_POWER, HIGH);
  pinMode(MODEM_PWRKEY, OUTPUT);
  digitalWrite(MODEM_PWRKEY, LOW);
  delay(100);
  digitalWrite(MODEM_PWRKEY, HIGH);              // pulse to switch on
  delay(1000);
  digitalWrite(MODEM_PWRKEY, LOW);
}

bool ensureNetwork() {
  if (!modem.isNetworkConnected()) {
    Serial.println("Waiting for network registration...");
    if (!modem.waitForNetwork(60000L)) {
      Serial.println("No network: check antenna, SIM and coverage");
      return false;
    }
    Serial.printf("Registered, signal quality %d\n", modem.getSignalQuality());
  }
  if (!modem.isGprsConnected()) {
    Serial.printf("Opening data connection with APN %s\n", APN);
    if (!modem.gprsConnect(APN, APN_USER, APN_PASS)) {
      Serial.println("Data connection failed: check APN and data plan");
      return false;
    }
    Serial.print("Local IP: ");
    Serial.println(modem.localIP());
  }
  return true;
}

void onMessage(char* topic, byte* payload, unsigned int length) {
  Serial.printf("Command %s: %.*s\n", topic, (int)length, (const char*)payload);
}

bool connectMqtt() {
  String status = String(BASE) + "/status";
  if (!mqtt.connect(CLIENT_ID, nullptr, nullptr, status.c_str(), 1, true, "offline")) {
    Serial.printf("MQTT failed, state=%d\n", mqtt.state());
    return false;
  }
  mqtt.publish(status.c_str(), "online", true);
  mqtt.subscribe((String(BASE) + "/cmd").c_str(), 1);
  Serial.println("MQTT connected over LTE");
  return true;
}

void setup() {
  Serial.begin(115200);
  SerialAT.begin(115200, SERIAL_8N1, MODEM_RX, MODEM_TX);
  powerOnModem();

  Serial.println("Initializing modem...");
  if (!modem.init()) {
    Serial.println("init failed, trying restart");
    modem.restart();
  }
  Serial.println("Modem: " + modem.getModemInfo());
  if (strlen(SIM_PIN) && modem.getSimStatus() == SIM_LOCKED) modem.simUnlock(SIM_PIN);

  mqtt.setServer(MQTT_HOST, MQTT_PORT);
  mqtt.setCallback(onMessage);
  mqtt.setKeepAlive(120);                        // fewer pings, less data
  mqtt.setSocketTimeout(15);                     // cellular round trips are slower
}

void loop() {
  if (!mqtt.connected()) {
    if (millis() - lastAttempt > 15000) {
      lastAttempt = millis();
      if (ensureNetwork()) connectMqtt();
    }
    return;
  }
  mqtt.loop();

  if (millis() - lastPublish > PUBLISH_INTERVAL) {
    lastPublish = millis();
    char json[64];
    snprintf(json, sizeof(json), "{\"t\":%.1f,\"csq\":%d}",
             20.0 + (esp_random() % 100) / 10.0, modem.getSignalQuality());
    mqtt.publish((String(BASE) + "/telemetry").c_str(), json);
  }
}

O que observar no monitor serial

Uma inicialização saudável imprime a identificação do modem, Registered, signal quality N, o IP local e MQTT connected over LTE. A qualidade de sinal é o valor CSQ de 0 a 31, sendo que 99 significa desconhecido. Valores abaixo de cerca de 10 são marginais; reposicione a antena antes de culpar o software. Se o sketch para no registro, o problema é SIM, cobertura ou antena. Se registra, mas a conexão de dados falha, o APN está errado ou o plano não tem dados. Se ambos funcionam, mas o MQTT falha com estado -2, a conexão TCP está sendo bloqueada; alguns chips restritivos só permitem destinos de uma lista liberada.

Teste a partir do seu computador

mosquitto_sub -h broker.connectmq.com -p 1883 -i watch-81c3e5 -v -t "connectmq/demo/lte-81c3e5/#"

Você deve ver status online seguido de uma mensagem de telemetria a cada minuto. Envie um comando para verificar o caminho de descida, o que também prova que o NAT da operadora mantém a conexão aberta:

mosquitto_pub -h broker.connectmq.com -p 1883 -i cmd-81c3e5 -t "connectmq/demo/lte-81c3e5/cmd" -m "ping"

O servidor MQTT público (gratuito) serve para a ativação inicial, mas tudo o que você publica ali pode ser lido por qualquer pessoa, então mude para credenciais próprias antes de o dispositivo sair da bancada.

Mantendo baixo o consumo de dados do SIM7600 MQTT

Planos celulares cobram por byte, e o MQTT só é eficiente se você o usar com eficiência. Estas são as alavancas que mais importam, mais ou menos em ordem de impacto:

  1. Evite reconexões. Cada nova conexão custa um handshake TCP, o CONNECT e o CONNACK do MQTT, as inscrições e, com TLS, um handshake completo incluindo a cadeia de certificados. Um dispositivo que reconecta a cada poucos minutos pode gastar mais dados conectando do que enviando telemetria. Corrija a causa raiz das quedas em vez de reconectar por timer.
  2. Ajuste o keep-alive. A cada período de keep-alive, o cliente envia um pequeno PINGREQ e o broker responde. Um keep-alive mais longo economiza dados, mas os gateways NAT das operadoras derrubam conexões ociosas depois de um tempo, e se o keep-alive for maior que isso, a conexão morre silenciosamente. Comece com cerca de dois minutos e ajuste conforme o que observar.
  3. Encurte os payloads. Use chaves JSON curtas ("t" em vez de "temperature"), arredonde valores e omita campos que raramente mudam.
  4. Agrupe leituras. Enviar dez leituras em uma única mensagem a cada dez minutos custa muito menos overhead do que dez mensagens separadas.
  5. Publique na mudança. Para valores que mudam devagar, publique só quando o valor variar além de um limite, mais um heartbeat periódico.
  6. Use tópicos curtos. O tópico é enviado com cada mensagem. f/42/t é mais barato que um caminho longo e descritivo, embora a legibilidade também importe; encontre um equilíbrio.
  7. Fique de olho nas inscrições. Inscrições com curinga em tópicos movimentados podem trazer muito mais dados do que você espera.

Lembre-se de que as operadoras podem arredondar cada sessão ou período de cobrança para uma unidade mínima, então meça o consumo real no portal do seu provedor de SIM por alguns dias em vez de confiar em cálculos.

Em produção, use TLS na porta 8883 e o usuário, a senha e o client ID gerados no portal do ConnectMQ. No SIM7600 você tem duas opções. Algumas versões e forks do TinyGSM expõem um cliente seguro que usa o motor SSL embutido do modem, o que poupa memória do ESP32; verifique se a versão instalada suporta isso para o SIM7600. Como alternativa, rode o TLS no próprio ESP32 com uma biblioteca wrapper como a SSLClient sobre o TinyGsmClient. Em ambos os casos, valide o certificado do broker contra a raiz ISRG Root X1 em vez de desativar a verificação. O guia de ESP32 MQTT SSL explica a escolha do certificado e por que o NTP ou a hora da rede importam; o SIM7600 também pode fornecer a hora da rede.

Solução de problemas

  • O modem nunca responde a AT. Pinos UART errados, baud rate errado ou o modem não está alimentado. Verifique o pino de habilitação de alimentação e o pulso de PWRKEY da sua placa.
  • Registra só em 2G ou 3G, ou nem registra. A banda pode não ser suportada pela sua variante do SIM7600 (E, A, SA, G e outras cobrem regiões diferentes).
  • Conecta e cai após alguns minutos de silêncio. Keep-alive maior que o timeout de NAT da operadora. Reduza-o.
  • Resets por brownout durante a transmissão. A fonte não consegue fornecer a corrente de pico. Adicione um capacitor grande perto do modem e use fios mais grossos.
  • Mensagens atrasadas em segundos. Normal em links celulares; a latência é maior e mais variável que no Wi-Fi. Projete levando isso em conta.

Para uma estratégia de reconexão mais robusta com backoff, adapte a máquina de estados da lógica de reconexão MQTT no ESP32. Se houver opção cabeada no local, compare com ESP32 Ethernet MQTT com W5500 e, para ativos em movimento, veja o rastreador GPS com ESP32 via MQTT.

Operando uma frota celular

Visitar dispositivos celulares é caro, então o lado do broker deve ser a última das suas preocupações. Um broker MQTT gerenciado mantém o endpoint disponível enquanto os dispositivos trocam de célula e reconectam. O ConnectMQ dá a cada dispositivo suas próprias credenciais, mostra o estado de conexão via $SYS/broker/connection/{clientId}/state e permite acompanhar o tráfego ao vivo no portal, o que ajuda quando você está tentando entender para onde vão os dados de um chip. Um broker MQTT na nuvem com hostname público também evita as configurações de APN privado e VPN que brokers auto-hospedados muitas vezes exigem para dispositivos celulares. Se este é o seu primeiro projeto com ESP32, comece pelo tutorial de IoT com ESP32.

Comece com o ConnectMQ

Crie um broker Serverless gratuito em app.connectmq.com, sem cartão de crédito. Seus dispositivos SIM7600 podem publicar nele de qualquer lugar com cobertura, e você pode ver cada mensagem chegar no explorador de tópicos ao vivo.

Perguntas frequentes

O PubSubClient funciona com o SIM7600?

Sim. O TinyGSM fornece o TinyGsmClient, que implementa a interface Client do Arduino, então o PubSubClient usa os sockets TCP do modem exatamente como usaria o Wi-Fi.

Quantos dados o SIM7600 MQTT consome?

Depende principalmente da frequência de reconexões, do intervalo de keep-alive e do tamanho do payload. Um dispositivo que permanece conectado e envia mensagens compactas consome muito pouco; reconexões frequentes, principalmente com TLS, dominam o consumo. Meça no portal do seu provedor de SIM.

Qual APN devo usar?

O APN vem do seu provedor de SIM e normalmente está na documentação ou no portal IoT dele. Um APN errado deixa o modem se registrar na rede, mas impede a conexão de dados.

Posso usar MQTT sobre TLS com o SIM7600?

Sim, seja pelo motor SSL do modem, se a sua versão do TinyGSM suportar isso para o SIM7600, seja rodando o TLS no ESP32 com uma biblioteca wrapper sobre o TinyGsmClient. Sempre valide o certificado do broker.

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.