Eu recebi dois DevKits LSM110A da SmartCore em uma parceria e, a princípio, o objetivo parecia bastante direto: entender o módulo, validar sua comunicação LoRaWAN e reunir uma base técnica sólida para posteriormente facilitar o uso do equipamento por outras pessoas.
O problema é que, conforme os testes avançaram, ficou claro que não bastava verificar se o módulo respondia aos comandos AT ou se conseguia transmitir um pacote ocasionalmente. Era necessário observar como o firmware se comportava ao longo de diferentes configurações e estados, especialmente em relação a canais, frame counters, janelas RX, persistência de sessão, OTAA e ABP.
Foi por isso que esta investigação acabou ficando muito maior do que eu imaginava. Passei pelo firmware que veio de fábrica, por uma atualização SJIT que adicionava comandos que pareciam resolver parte das limitações e, por fim, pelo firmware RAK RUI3. No meio desse caminho apareceram problemas relacionados a CHMASK, frame counter, ATZ, UART, temporização Class A, channel mask, P2P e até situações em que o gateway comprovava a recepção do sinal enquanto a TTN já não aceitava aquele frame dentro da sessão.
Todo o ensaio LoRaWAN apresentado neste artigo foi realizado com a The Things Network, utilizando AU915/FSB2. Netmore/Everynet não fez parte desta campanha. A intenção não era comparar diferentes servidores LoRaWAN, mas manter uma infraestrutura conhecida e um único perfil de referência para que as diferenças observadas pudessem ser atribuídas com mais segurança ao firmware e ao comportamento dos comandos AT.
Resultado em uma frase: o firmware original demonstrou que o hardware era capaz de operar LoRaWAN, mas apresentou limitações importantes de estado e ABP; a atualização SJIT intermediária trouxe recursos adicionais, porém não se mostrou suficientemente estável nos meus ensaios; e o RAK RUI3 foi a opção que apresentou o comportamento mais consistente no cenário testado, chegando a 32/32 confirmed uplinks OTAA, 32/32 ABP e P2P byte-exact até 250 bytes.
Legenda sugerida: os dois DevKits usados durante toda a investigação. A caracterização foi feita remotamente, com os módulos conectados a um Raspberry Pi 4 no laboratório.
Antes de começar: escopo, segurança e nomenclatura
As chaves criptográficas e credenciais de rede foram removidas. AppKey, NwkSKey, AppSKey, tokens e coordenadas precisas não precisam aparecer para que os testes possam ser reproduzidos. DevEUI e DevAddr permanecem porque são identificadores úteis para correlacionar UART, gateway e TTN.
Para evitar ambiguidade, vou chamar as três etapas de firmware assim:
| Nome neste artigo | Firmware | UART | Papel nos testes |
|---|---|---|---|
| Firmware A — fábrica | SJIT/SJI APP V1.0.0, MW_LORAWAN V2.4.0, SW V0.0.24 | 9600 8N1 | Firmware original dos DevKits |
| Firmware B — SJIT atualizado | APP V1.0.4, MW_LORAWAN V2.4.0, SW V0.0.31 | 9600 8N1 | Primeira atualização testada |
| Firmware C — RAK RUI3 | RUI_4.2.4_RAK3272-SiP_latest_final | 115200 8N1 | Firmware que estabilizou o fluxo final |
Objetivo desta investigação
Estes testes não foram realizados apenas para verificar se o LSM110A era capaz de se comunicar via LoRaWAN. O objetivo final deste trabalho era desenvolver uma biblioteca que facilitasse o uso do equipamento por outros usuários e, antes de construir essa camada, era necessário validar se o próprio SDK/firmware fornecido com o DevKit era suficientemente confiável para servir como sua base.
Isso significava comprovar não apenas que um comando AT retornava OK ou que um pacote conseguia chegar ocasionalmente à rede, mas que o módulo apresentava um comportamento previsível e repetível em situações reais de uso: configuração, OTAA, ABP, canais, frame counters, janelas RX, confirmed uplinks, persistência de sessão e P2P.
Se o firmware apresentasse problemas nesses pontos, criar uma biblioteca diretamente sobre ele apenas esconderia essas limitações e poderia fazer com que o usuário acreditasse estar utilizando uma interface confiável quando o comportamento problemático estaria, na verdade, em uma camada inferior. Por isso, a validação do firmware veio antes do desenvolvimento da biblioteca.
Caso o firmware original não atendesse a esse requisito, também fazia parte do objetivo investigar as alternativas disponíveis, testar seus comandos AT e determinar experimentalmente qual versão poderia oferecer uma base realmente estável para o desenvolvimento posterior.
1. Por que eu testei o firmware antes de qualquer biblioteca
A pergunta inicial era simples: o SDK/firmware AT que vinha no LSM110A poderia ser considerado 100% utilizável e confiável para o uso pretendido, ou seria necessário atualizar o equipamento antes de construir algo em cima dele?
Eu queria chegar a uma base que pudesse ser usada por outras pessoas sem depender de comportamentos duvidosos ou de workarounds escondidos. Por isso, primeiro foi necessário caracterizar a UART, a gramática AT, OTAA, ABP, AU915/FSB2, confirmed uplink, ACK, RX1/RX2, persistência de sessão e P2P. Só depois disso faria sentido considerar o firmware uma fundação estável.
Também não assumi que uma imagem de firmware era boa apenas porque estava disponível em um repositório ou manual. Durante os testes, a documentação e o runtime divergiram em pontos importantes. Na prática, cada opção precisou ser gravada, interrogada por AT, submetida a readback e validada com tráfego real.
O resultado foi uma comparação bastante clara: o Firmware A tinha uma pilha LoRaWAN funcional, mas era difícil controlar a sub-banda e preservar o estado ABP; o Firmware B adicionou mecanismos que teoricamente atacavam esses problemas, mas o setter de máscara apresentou comportamento instável; e o RUI3 foi o firmware que apresentou a combinação mais consistente de configuração explícita, readback, ABP, OTAA e P2P dentro da TTN
3. Arquitetura do laboratório remoto usada para o LSM110A

3.1. Topologia física
Os dois DevKits LSM110A permaneceram conectados às portas USB de um Raspberry Pi 4 dedicado ao laboratório. O gateway LoRaWAN, baseado em concentrador SX1301/Radioenge, ficou associado a um Banana Pi M2 Zero. O acesso remoto foi feito por uma rede overlay privada; no relato oral ela apareceu como “Thingscale”, enquanto o ambiente efetivamente usado no laboratório é Tailscale. SSH foi o principal meio de controle e SSHFS foi usado quando era conveniente montar arquivos remotamente.
ACESSO REMOTO
Linux / Windows / macOS / celular (Termux)
|
SSH / SSHFS
|
rede privada Tailscale
|
+----------------+----------------+
| |
Raspberry Pi 4 Banana Pi M2 Zero
host de laboratório host do gateway
| |
+------+-------+ |
| | |
LSM110A #1 LSM110A #2 Gateway SX1301
OTAA/ABP ABP/OTAA Packet Forwarder
UART USB UART USB |
| |
+------------- TTN/LNS -----------+
A associação entre /dev/ttyUSBx e o papel OTAA/ABP mudou ao longo dos ensaios. Por isso, uma regra arquitetural importante foi adotada: identificar o módulo pelo DevEUI e nunca confiar permanentemente no número da porta USB.
3.2. Sistemas operacionais usados
Os ensaios foram executados a partir dos três sistemas operacionais usados no dia a dia do laboratório:
- Linux;
- Windows;
- macOS.
O mesmo laboratório também foi controlado por telefone usando Termux + SSH, inclusive para recuperação de módulos quando a serial deixava de responder. No Windows, o conversor USB-UART utilizado no kit exigiu o driver Silicon Labs CP210x Virtual COM Port (VCP) para aparecer como uma porta COM. A Silicon Labs documenta que o driver VCP é justamente o componente que faz a família CP210x operar como porta serial virtual. O modelo exato do bridge físico deve ser confirmado visualmente antes de uma publicação que pretenda citar o part number, mas o pacote de driver usado é o CP210x VCP.
3.3. Gateway como instrumento de medida, não apenas infraestrutura
O gateway não foi tratado somente como um caminho para a TTN. Ele também serviu como instrumento de diagnóstico. O Packet Forwarder Semtech opera sobre UDP e o tráfego com o servidor foi observado diretamente na porta 1700. Isso permitiu separar duas perguntas diferentes:
- “o LSM110A realmente emitiu um frame que o concentrador conseguiu demodular?”;
- “a TTN aceitou esse frame como pertencente à sessão cadastrada?”.
Essa separação foi decisiva em problemas de ABP/FCnt.
4. Controle positivo: outro dispositivo transmitindo continuamente
Durante parte da investigação, um módulo LoRaWAN da Radioenge, já conhecido e validado, permaneceu transmitindo periodicamente, aproximadamente a cada dez segundos. Ele funcionou como um controle positivo/keep-alive do laboratório. A lógica foi simples: se o LSM110A desaparecesse dos logs, mas o dispositivo de referência continuasse aparecendo normalmente no gateway e na TTN, a hipótese “o gateway inteiro parou” perdia força. Isso foi especialmente útil porque o gateway havia passado por adaptações de Packet Forwarder/Armbian e também precisava ser monitorado em operação prolongada. Essa prática evita um erro comum em bancada: diagnosticar simultaneamente duas variáveis desconhecidas. O dispositivo de referência forneceu uma fonte de RF/LoRaWAN cujo comportamento já era conhecido.
5. Metodologia: como cada conclusão foi comprovada
A investigação evoluiu de testes manuais para uma abordagem de evidência multicamada.
Camada Pergunta Evidência usada Host/serial O comando AT foi aceito? transcript UART, status OK, AT_ERROR,
AT_PARAM_ERROR, AT_BUSY_ERROR
MAC local A stack iniciou/concluiu TX? debug do modem, TX_DONE, frequência/
DR, +EVT:...
RF/gateway O gateway demodulou o frame? rxpk no Semtech UDP Packet Forwarder,
RSSI, SNR, frequência, Base64
Network Server O LNS aceitou a sessão/MIC/FCnt? TTN Live Data, ns.up.*, DevAddr, FCnt,
MAC commands
Retorno O dispositivo recebeu resposta de rede? confirmed ACK, CFS=1, JoinAccept,
LinkCheckAns, downlink
Uma consequência importante é que nenhuma dessas provas isoladas substitui as demais. Exemplos:
OK
significa que o parser AT aceitou o comando. Não prova que houve RF.
+EVT:TX_DONE
prova que o modem concluiu o TX local, mas não que a TTN recebeu. Um rxpk no gateway prova que o concentrador demodulou o pacote, mas o Network Server ainda pode descartá-lo por MIC, DevAddr, FCnt ou contexto de sessão. Um confirmed uplink seguido por ACK é a evidência mais forte do caminho bidirecional:
dispositivo -> RF -> gateway -> LNS/TTN -> downlink -> gateway -> dispositivo
6. Linha do tempo consolidada
Data aproximada Etapa Resultado principal 02/09/2026 caracterização inicial do Firmware A UART 9600, APP V1.0.0; OTAA e
gramática AT mapeados
02-03/09 TTN/OTAA AU915 primeiro join fora de FSB2 falha; join
posterior em FSB2 funciona; CFList
converge canais
03-07/09 expansão ABP e segundo módulo hopping amplo, DevAddr, RX windows,
ATZ/FCnt e Packet Forwarder investigados
04/09 validadores e LabBench parser, guards, ausência de CHMASK em
V1.0.0 e segurança de sessão
consolidados
09-11/09 Firmware B V1.0.4 CHMASK/ABPFCNT surgem; CHMASK
gera falhas e estado de UART
problemático
11/09 programação do Firmware C RUI3 UART muda para 115200; runtime
identifica RUI_4.2.4_RAK3272-SiP
11-12/09 testes RUI3 ABP/OTAA/P2P MASK=0002 comprovado, OTAA
JoinAccept, ABP ACK, P2P 250 B
12/09 revisão da automação correções RX1/confirmed/BUSY; v5.2
preparada para 32 TX ABP + 32 TX OTAA
7. Fase 1 – Firmware A de fábrica: identificação e UART
[CAPTURA DE TELA — retorno de AT+VER=? e AT+CHMASK=? no Firmware A, destacando APP V1.0.0, UART 9600 e AT_ERROR para CHMASK]
O firmware original foi caracterizado antes de qualquer regravação. Os registros consolidados mostram:
APP_VERSION: V1.0.0
MW_LORAWAN_VERSION: V2.4.0
MW_RADIO_VERSION: V1.2.0
SW_VERSION: V0.0.24
A interface operava em:
9600 baud
8 data bits
1 stop bit
sem paridade
O parser automatizado precisou ser orientado a stream. CR e LF podiam chegar fragmentados em leituras UART distintas, e o firmware misturava resposta síncrona, linhas vazias, debug e eventos assíncronos. A primeira implementação que tentava inferir a transação por número fixo de linhas produziu interpretações erradas; o raw log permitiu corrigir isso. Um dos resultados de capability mais importantes foi:
AT+CHMASK=?
AT_ERROR
O mesmo ocorreu com AT+BAUDRATE=? nessa baseline. Ou seja, a documentação de revisões posteriores não podia ser aplicada automaticamente ao firmware que efetivamente estava no módulo.
7.1. Exemplo de divergência entre help, documentação e runtime
A metodologia passou a seguir esta ordem:
- capturar AT? completo
- consultar
AT+CMD? - consultar getter real
AT+CMD=? - testar setter somente se seguro
- reler o getter
- observar efeitos colaterais e eventos assíncronos
Isso foi adotado porque comandos aparentemente triviais apresentavam comportamento stateful. Um caso antigo importante foi AT+MODE=1: mesmo quando o modem já estava em LoRa, o setter podia reiniciar o MCU e terminar em BOOTALERT. Outro foi a reescrita do AppEUI: em um ensaio, escrever novamente o mesmo valor provocou inicialização de DevNonce. A lição para o uso dos comandos AT foi direta: read-before-write não é apenas uma otimização; é um mecanismo de proteção de estado.
8. OTAA no Firmware A: por que inicialmente pareceu aleatório
No primeiro ciclo OTAA, selecionar AT+BAND=1 colocava o modem em AU915, mas isso não equivalia a selecionar FSB2. O dispositivo podia tentar JoinRequest em diferentes canais da grade regional. Um primeiro JoinRequest foi observado por volta de 915,4 MHz, fora do conjunto de canais escutado pelo gateway FSB2 e falhou. Em uma tentativa posterior, o JoinRequest caiu em 918,2 MHz e o join foi aceito. A partir daí, o Live Data da TTN mostrou a peça que faltava: o JoinAccept continha uma CFList do tipo CHANNEL_MASKS, permitindo à rede restringir o conjunto de canais. Depois do join, os uplinks observados convergiram para FSB2. A hipótese evoluiu assim:
HIPÓTESE INICIAL
“Sem AT+CHMASK, OTAA em FSB2 é inviável.”
EVIDÊNCIA NOVA
JoinRequest finalmente cai em um canal ouvido -> TTN responde JoinAccept
-> JoinAccept contém CFList/máscara -> dispositivo passa a usar FSB2.
CONCLUSÃOAT+CHMASKlocal não era requisito absoluto para OTAA funcionar;
era um possível meio de tornar o bootstrap mais determinístico.
9. ABP no Firmware A: o problema de sub-banda aparece com mais força
ABP é estruturalmente diferente do OTAA porque não existe JoinAccept para iniciar a sessão. O modem possui as chaves/session parameters localmente e passa a transmitir. Se ele começa com a grade AU915 ampla, não há uma CFList inicial para corrigir o estado regional. Uma rodada de 64 uplinks mostrou transmissões distribuídas por CH0–CH63, entre 915,2 e 927,8 MHz. Isso explicou por que o ABP parecia uma “loteria”: o gateway TTN FSB2 escuta principalmente CH8–CH15 no bloco de 125 kHz; portanto, somente parte dos uplinks tinha chance de ser demodulada antes de a rede conseguir enviar LinkADRReq. Um exemplo de debug registrado durante essa fase foi:
TX on freq 922800000 Hz at DR 5
Esse TX corresponde a um canal fora da FSB2. Em outro ponto, o log mostrava:
TX on freq 917800000 Hz at DR 5
RX_1 ...
RX_2 on freq 923300000 Hz at DR 8
917,8 MHz está dentro de FSB2. A sequência demonstrou que o problema não era “hopping em si”, mas o conjunto sobre o qual o hopping estava sendo realizado.
9.1. Fluxo comparativo OTAA x ABP
OTAA
AU915 amplo
-> JoinRequest eventualmente cai em FSB2
-> TTN recebe
-> JoinAccept com CFList/channel mask
-> modem converge para FSB2
ABP
sessão ativada localmente
-> não existe JoinAccept
-> AU915 amplo pode permanecer
-> um uplink precisa cair em FSB2
-> TTN precisa responder LinkADRReq/RxTimingSetupReq
-> modem precisa ouvir o downlink
-> somente então ocorre convergência
Essa diferença se tornou o núcleo da investigação ABP.
10. DevAddr, sessão e validação pelo gateway
Em uma fase, houve discrepância entre o DevAddr usado no modem e o cadastrado na TTN. A baseline final passou a usar:
DevEUI ABP: 0080E115051FD6B4
DevAddr: 260D54CE
NwkID: 19
A correção do DevAddr fez a TTN voltar a associar frames à sessão esperada. Entretanto, somente corrigir cadastro não resolvia todos os casos, porque o estado de FCnt e a máscara regional também podiam divergir.
11. A captura do Packet Forwarder como prova intermediária
Para separar “não chegou ao gateway” de “chegou, mas o LNS rejeitou”, foi capturado o tráfego UDP/1700 do Packet Forwarder. O gateway enviava mensagens Semtech contendo rxpk com frequência, data rate, RSSI, SNR e o PHYPayload em Base64. Um trecho típico da captura mostra:
"freq":917.200000,
"stat":1,
“modu”:”LORA”,
"datr":"SF10BW125",
"codr":"4/5",
"rssi":-40,
...
A captura também mostrou tráfego UDP de ida e volta entre gateway e servidor, comprovando que o Packet Forwarder estava vivo. Assim, quando o LSM110A não aparecia na aplicação, era possível verificar se o problema estava antes ou depois do gateway. Em frames ABP analisados, foram confirmados DevAddr, FPort, DR, payload e MIC coerentes. Isso descartou a hipótese de “não existe RF” em parte importante da investigação do Firmware A.
12. ATZ e frame counter: o problema que parecia configuração, mas era sessão
O comportamento de ATZ foi uma das descobertas mais críticas. Em determinados estados, setters como DevAddr e session keys podiam retornar erro. Um reset fazia esses setters voltarem a ser aceitos, o que inicialmente sugeria usar ATZ como etapa de provisionamento. Porém, o reset também alterava outros estados internos. O padrão observado foi:
sessão ABP funcionando
-> ATZ
-> parâmetros visíveis reconfigurados
-> modem volta a transmitir
-> gateway pode continuar vendo RF
-> TTN deixa de aceitar normalmente
A explicação mais consistente é reset/rollback de FCntUp e/ou outros estados de sessão. Em LoRaWAN, reutilizar o mesmo DevAddr e as mesmas chaves com um contador regressivo é interpretado como replay. O Network Server pode simplesmente descartar o frame. A validação foi importante porque foi feita em camadas: o gateway permitia provar que o rádio ainda estava emitindo, enquanto a TTN revelava que o frame não era aceito como uma continuação válida da sessão. Ao recriar a sessão/ dispositivo ou readequar o estado de contador no lado da rede, a comunicação voltava. Dessa descoberta nasceu uma regra que permanece até hoje:
Nunca executar ATZ automaticamente como rotina de “limpeza” de uma sessão ABP ativa.
12.1. O que os comandos AT mostraram sobre provisionamento protegido
Na APP V1.0.0, alguns parâmetros de sessão não podiam ser simplesmente reescritos enquanto a MAC estava ativa. Um caso reproduzido foi:
AT+DADDR=?
05:1F:D6:B4
OK
AT+DADDR=26:0D:54:CE
AT_ERROR
Em determinados estados, a sequência operacional que permitia voltar a alterar DevAddr e chaves era:
setter protegido -> AT_ERROR
ATZ
aguardar boot
regravar parâmetros
AT+JOIN=0
Foi justamente essa necessidade prática de reset antes do reprovisionamento que tornou o ABP perigoso: uma sessão ABP não é renegociada com o servidor. Se o estado local de contador ou sessão muda, repetir os mesmos valores visíveis não garante que o LNS aceite os próximos frames. Há uma correção importante na interpretação histórica: os ensaios não provam que o opcode ATZ, isoladamente, sempre grave FCnt=0. O que foi comprovado é que o fluxo reset + reprovisionamento perdeu a continuidade da sessão. Na geração V1.0.4, a análise do próprio firmware mostrou um mecanismo ainda mais direto: AT+DADDR=<addr> sem a opção de preservação reinicializa o contador ABP, enquanto AT+DADDR=<addr>,1 foi introduzido para manter o uplink count. Portanto, no relatório técnico, ATZ deve ser descrito como parte de um fluxo potencialmente destrutivo, e não como único culpado universal.
13. Séries de comandos AT que transformaram sintomas em evidência
[GRÁFICO — comparação da campanha de 96 transmissões e da R13: quantidade em FSB2, fora de FSB2, recebida pelo gateway e ACK]
A caracterização deixou de depender de um único AT+SEND e passou a usar séries controladas de comandos AT. Isso foi decisivo porque o Firmware A podia transmitir corretamente em RF e, ainda assim, não ser ouvido pelo gateway FSB2 ou não ser aceito pela sessão LoRaWAN. Três campanhas históricas são especialmente importantes.
Campanha de 96 transmissões úteis – APP V1.0.0 Em uma campanha ABP com a região AU915 ampla, os logs UART mostraram:
TX_DONE : 96
no plano FSB2 : 11
fora do plano : 85
network_rx : True
primeiro RX rede : tentativa 16
pós-rede : 80 amostras
pós-rede no plano : 10
pós-rede fora : 70
canais observados : CH8..CH63
Ou seja, 88,54% das 96 transmissões ficaram fora do bloco CH8–CH15 escutado pelo gateway para uplinks de 125 kHz. Mesmo depois de ocorrer retorno da rede, 70 das 80 amostras posteriores continuaram fora do plano. Isso mostrou que receber um downlink não significava convergência imediata e estável da máscara nesse firmware.
Campanha R13 – 32 confirmed uplinks Em uma rodada posterior, deliberadamente sem ATZ e sem nova ativação AT+JOIN=0, foram enviados 32 confirmed uplinks apenas para mapear o comportamento efetivo do rádio. O resultado foi:
32/32 comandos chegaram a TX_DONE
5/32 caíram em CH8..CH15 = 15,625%
27/32 ficaram fora de CH8..CH15 = 84,375%
5/32 foram recebidos pelo gateway com CRC válido
0/32 receberam ACK
O resultado foi particularmente forte porque os cinco frames que caíram em FSB2 foram exatamente os cinco frames que o gateway demodulou. Não houve frames extras do mesmo dispositivo recebidos fora desse conjunto.
Tentativa | Payload | Canal | Frequência | FSB2 | Gateway | FCnt observado |
6 | ABR006 | CH8 | 916,8 MHz | sim | CRC_OK | 17 |
9 | ABR009 | CH12 | 917,6 MHz | sim | CRC_OK | 20 |
11 | ABR011 | CH14 | 918,0 MHz | sim | CRC_OK | 22 |
15 | ABR015 | CH15 | 918,2 MHz | sim | CRC_OK | 26 |
16 | ABR016 | CH13 | 917,8 MHz | sim | CRC_OK | 27 |
O Packet Forwarder registrou, para os mesmos frames:
10:45:35 received packet with valid CRC from mote: 260D54CE (fcnt=17)
10:48:36 received packet with valid CRC from mote: 260D54CE (fcnt=20)
10:50:37 received packet with valid CRC from mote: 260D54CE (fcnt=22)
10:54:38 received packet with valid CRC from mote: 260D54CE (fcnt=26)
10:55:39 received packet with valid CRC from mote: 260D54CE (fcnt=27)
O salto 17 -> 20 -> 22 -> 26 -> 27 é compatível com uplinks intermediários transmitidos em frequências que o gateway não escutava. O contador continuava sendo incrementado localmente, mas somente os frames que retornavam à FSB2 apareciam no gateway.
Sessão ABP saudável imediatamente antes da regressão A existência de problemas posteriores não significa que o ABP nunca tenha funcionado. Antes da regressão, a mesma identidade foi aceita normalmente pela TTN: FCnt Payload Tipo Canal Frequência DR Resultado
FCnt | Payload | Tipo | Canal | Frequência | DR físico | Resultado |
789 | ABPU01 | unconfirmed | CH11 | 917,4 MHz | SF7/BW125 | aceito |
790 | ABPU02 | unconfirmed | CH14 | 918,0 MHz | SF7/BW125 | aceito |
791 | ABPU03 | unconfirmed | CH13 | 917,8 MHz | SF7/BW125 | aceito |
792 | ABPC04 | confirmed | CH12 | 917,6 MHz | SF7/BW125 | ACK em RX1 |
793 | ABPU01 | unconfirmed | CH15 | 918,2 MHz | SF7/BW125 | aceito |
Trecho de UART da campanha saudável:
AT+SEND=10:0:414250553031
TX on freq 917400000 Hz at DR 5
MAC txDone
AT+SEND=10:0:414250553032
TX on freq 918000000 Hz at DR 5
MAC txDone
AT+SEND=10:0:414250553033
TX on freq 917800000 Hz at DR 5
MAC txDone
AT+SEND=10:1:414250433034
TX on freq 917600000 Hz at DR 5
MAC txDone
RX_1 on freq 925700000 Hz at DR 13
+EVT:SEND_CONFIRMED
O contraste entre FCnt 789-793 aceitos e FCnt 17-27 observados posteriormente no mesmo DevAddr se tornou uma das provas mais importantes de perda de continuidade da sessão ABP.
14. Fase 2 – Firmware B APP V1.0.4: a atualização que deveria resolver CHMASK
A primeira atualização relevante levou os módulos para:
APP_VERSION: V1.0.4
MW_LORAWAN_VERSION: V2.4.0
MW_RADIO_VERSION: V1.2.0
SW_VERSION: V0.0.31
UART: 9600 8N1
A documentação SJIT Rev. 1.2 associa essa revisão de firmware a novos recursos como:
AT+CHMASK;AT+BAUDRATE;- manutenção de uplink count via
AT+DADDR=addr,1; AT+DEVNONCE;AT+UNCNFRETX;AT+CNFRETX.
Na detecção automática, a suíte realmente observou:
CHMASK: True
ABPFCNT: True
DEVNONCE: True
CNFRETX: True
UNCNFRETX: True
Em teoria, essa era exatamente a revisão necessária para resolver o problema do ABP.
15. CHMASK no Firmware B: manual, help e implementação não concordavam totalmente
A geração V1.0.4 documentava AT+CHMASK, mas o material disponível já mostrava sinais de uma interface AT muito próxima da estrutura interna da LoRaMAC. O manual descrevia: Fixed Channel (US915, AU915) – Channel mask[0:5]
Essa nomenclatura expõe diretamente seis posições de channel_mask[], em vez de abstrair o conceito como “FSB2”. Para a TTN AU915 FSB2, a máscara trabalhada durante os testes era:
FF00:0000:0000:0000:0002:0000
com FF00 habilitando CH8–CH15 e 0002 representando CH65 no bloco de 500 kHz. Mais importante: os documentos antigos revelam uma discrepância de sintaxe. O manual exemplifica máscaras fixas separadas por vírgula, enquanto o código dessa geração usa parsing de seis words com :. O readback trabalha internamente com channel_mask[i]. Assim, havia três representações simultâneas: a descrição channel_mask[0:5], o exemplo do manual e a sintaxe efetivamente esperada pela implementação. Essa inconsistência ajuda a explicar por que o comando precisava ser validado no hardware, e não apenas copiado do manual. Na prática, o setter FSB2 usado nos ensaios não produziu um comportamento estável e repetível.
16. Falha concreta do CHMASK no Firmware B
Uma execução automática registrou:
[CONFIG] aplicando perfil ABP V1.0.4 sem ATZ...
...
AT+CHMASK=FF00:0000:0000:0000:0002:0000
-> AT_NO_NETWORK_JOINED
Esse retorno por si só já era estranho: uma máscara regional é uma configuração MAC e, idealmente, não deveria depender de “estar joined” para ser definida durante o provisionamento. Em execuções posteriores, o módulo deixou de responder completamente. O autodetect tentou os dois baud rates relevantes e obteve:
Tentativas:
(115200, 'AT', 'TIMEOUT')
(115200, 'AT+VER=?', 'TIMEOUT')
(9600, 'AT', 'TIMEOUT')
(9600, 'AT+VER=?', 'TIMEOUT')
RuntimeError: LSM110A sem resposta UART em 115200/9600
Esse comportamento levou a caracterização a tratar o setter de CHMASK como operação potencialmente destrutiva para a sessão UART/runtime, até que o módulo fosse recuperado por power cycle.
16.1. O que podemos afirmar e o que não podemos
É importante manter a precisão histórica:
- podemos afirmar que CHMASK gerou
AT_NO_NETWORK_JOINEDem uma configuração FSB2; - podemos afirmar que houve rodadas em que a UART ficou muda e só voltou após recuperação/power cycle;
- podemos afirmar que os testes dessa fase não produziram uma evidência positiva, repetível e equivalente à fase
RUI3 de tráfego TTN com máscara controlada;
- não é tecnicamente correto transformar isso em “foi provado por SDR que o rádio não transmitia”, porque esse
ensaio específico não foi feito sistematicamente para cada comando nessa fase.
Essa distinção faz parte da metodologia: ausência de evidência no gateway não deve ser apresentada como prova absoluta de ausência de RF se a camada RF não foi medida diretamente naquele instante.
16.2. Outros comandos relevantes da geração V1.0.4
A mesma geração introduziu comandos que ajudam a entender por que o reprovisionamento anterior podia ser destrutivo:
AT+DADDR=<addr> -> forma simples
AT+DADDR=<addr>,1 -> mantém uplink count
AT+ABPFCNT=? -> leitura de FCnt prevista no firmware
AT+ABPFCNT=<valor> -> escrita do FCnt prevista no firmware
AT+BAUDRATE=9600|115200
AT+DEVNONCE=<count>
AT+UNCNFRETX=<count>
AT+CNFRETX=<count>
A análise da implementação V1.0.4 mostra que a forma simples de AT+DADDR executa uma reinicialização do contador ABP; a forma com ,1 foi criada explicitamente para preservar essa contagem. Isso fornece um mecanismo concreto para explicar por que “regravar exatamente o mesmo DevAddr” pode não ser uma operação neutra. O manual também afirma que AT+DR só é efetivo com ADR desligado. Assim, um readback de DR que diverge do DR físico usado em um uplink com ADR ativo não deve ser classificado automaticamente como erro do rádio.
17. Recuperação remota: reboot do Raspberry Pi como power cycle USB
A perda de UART seria muito mais cara se os testes exigissem acesso físico. Como os dois módulos estavam conectados ao Raspberry Pi 4 do laboratório, um reboot do host interrompia e restaurava a alimentação USB, funcionando como um power cycle remoto prático. Esse mecanismo foi usado inclusive a partir do celular via Termux/SSH. A consequência operacional foi relevante: os testes podiam continuar durante viagens ou fora do laboratório, mesmo quando um firmware deixava a porta serial em estado irrecuperável por software. Do ponto de vista de engenharia, o episódio também motivou a política “remote-safe” das versões seguintes: evitar comandos com histórico de reset, factory reset, troca de modo ou alteração de sessão quando um simples getter puder determinar que a escrita é desnecessária.
18. Pesquisa externa sem transformar tutorial em “verdade automática”
Depois de acumular evidência própria, foram consultadas referências públicas e materiais da SmartCore/Blogspot. A decisão de não começar copiando um tutorial foi deliberada: seguir um roteiro pronto desde o início poderia produzir um teste enviesado, no qual o comportamento do módulo seria apenas confirmado contra o roteiro em vez de ser descoberto empiricamente. As referências externas passaram a ser usadas como hipóteses e comparação, não como substituto de validação. Um material importante mostrava o LSM110A sendo usado com o ecossistema RAK/RAK3272-SiP, incluindo ST-LINK V2, STM32CubeProgrammer e um arquivo RAK3272-SiP_latest_final.hex. Isso abriu um caminho diferente: usar um firmware RUI3 adaptado ao hardware.
19. Programação de firmware: ST-LINK/V2 e STM32CubeProgrammer

O gravador usado no processo foi descrito no relato como “STM-Key V2”; o nome técnico do probe utilizado nesse tipo de fluxo é ST-LINK/V2, programador/debugger SWD/JTAG para STM32. A gravação foi feita com STM32CubeProgrammer. A ST documenta que STM32CubeProgrammer aceita ST-LINK via SWD/JTAG e arquivos .bin, .hex, .elf e .srec, com versões para Windows, Linux e macOS.
19.1. Mapa de memória do firmware SJIT
O manual de memória do LSM110A documenta:
IAP / bootloader:
início 0x08000000
fim 0x08001FFF
tamanho 0x2000 (8 KiB)
aplicação LSM110A:
início 0x08002000
fim 0x0802FFFF
Isso explica por que imagens binárias/app-only do ecossistema SJIT precisam respeitar o offset da aplicação e por que “apagar tudo” era uma operação arriscada. A mesma documentação alerta para áreas de dados/credenciais em endereços posteriores. Para um arquivo Intel HEX, entretanto, os endereços já fazem parte do próprio arquivo. O STM32CubeProgrammer ignora um endereço manual quando o formato possui endereçamento embutido. Essa diferença é essencial: .bin -> normalmente precisa de endereço de carga explícito
.hex -> carrega os endereços codificados no arquivo
19.2. Firmware RAK: .bin x .hex
A documentação atual da RAK para RAK3272 informa que:
- o .bin contém somente a aplicação;
- o .hex inclui bootloader + aplicação e deve ser programado com STM32CubeProgrammer;
- o firmware RUI3 usa baud padrão de 115200.
Portanto, para a imagem RUI3 usada na migração, não se deve aplicar arbitrariamente o offset 0x08002000 a um .hex completo como se fosse um .bin de aplicação SJIT. O endereço de memória deve seguir o formato e o artefato que está sendo gravado.
20. Fase 3 – Firmware C RAK RUI3: primeira identificação
Depois da programação, o primeiro teste simples já mostrou uma mudança decisiva:
AT
OK
AT+VER=?
AT+VER=RUI_4.2.4_RAK3272-SiP
OK
A UART agora era:
115200 baud
8N1
Isso está alinhado com a documentação RAK3272-SiP/RUI3, que usa 115200 como padrão. No laboratório remoto, a identificação posterior ficou assim:
ABP /dev/ttyUSB2 @115200 DevEUI=0080E115051FD6B4
OTAA /dev/ttyUSB3 @115200 DevEUI=0080E115051FC14F
Mais uma vez, o número da porta é um detalhe do ensaio, não uma identidade permanente.
21. Mudança de gramática AT: SJIT x RUI3
A migração não foi apenas uma atualização de versão; a API AT mudou substancialmente.
Função SJIT antigo RUI3 Modo LoRaWAN/P2P AT+MODE, PCONF AT+NWM=1 LoRaWAN / AT+NWM=0 P2P
LoRa
ABP/OTAA AT+JOIN=0/1 AT+NJM=0/1; OTAA usa AT+JOIN=1
DevEUI AT+DEUI AT+DEVEUI
DevAddr AT+DADDR AT+DEVADDR
Máscara AT+CHMASK=<6 words> AT+MASK=<16-bit sub-band mask>
Confirmed embutido em AT+SEND=port:ack:data AT+CFM=1 + AT+SEND=port:data
Retry AT+CNFRETX AT+RETY
Baud AT+BAUDRATE AT+BAUD
Public/private AT+NWKTYPE AT+PNM
A migração não pode ser tratada como simples troca de nomes de comandos: as duas famílias possuem semânticas AT diferentes e devem ser configuradas conforme o firmware efetivamente instalado.
22. AU915/FSB2 no RUI3: a simplificação que resolveu o problema regional
[CAPTURA DE TELA — RUI3 mostrando AT+BAND=6, AT+MASK=0002 e readback da máscara]
No RUI3: AT+BAND=6
seleciona AU915, e:
AT+MASK=0002
seleciona a sub-banda 2. Para AU915, 0002 corresponde a:
Frequência | Canal |
916.8 MHz | CH8 |
917.0 MHz | CH9 |
917.2 MHz | CH10 |
917.4 MHz | CH11 |
917.6 MHz | CH12 |
917.8 MHz | CH13 |
918.0 MHz | CH14 |
918.2 MHz | CH15 |
917.5 MHz / 500 kHz | CH65 |
A leitura no módulo confirmou:
AT+MASK=?
0002
OK
A diferença conceitual para o SJIT é enorme: em vez de expor seis words da LoRaMAC, RUI3 oferece uma máscara de sub-banda compacta.
23. Configuração ABP no RUI3
A sequência de configuração passou a seguir um princípio conservador: ler, comparar, escrever somente se necessário e reler. Exemplo sanitizado:
AT+NWM=1
AT+NJM=0
AT+CLASS=A
AT+BAND=6
AT+MASK=0002
AT+PNM=1
AT+ADR=1
AT+RX1DL=1
AT+RX2DL=2
AT+RX2DR=8
AT+RX2FQ=923300000
AT+DEVEUI=0080E115051FD6B4
AT+DEVADDR=260D54CE
AT+NWKSKEY=<REDACTED>
AT+APPSKEY=<REDACTED>
Um uplink simples produziu:
AT+CFM=0
AT+SEND=10:01020304
OK
+EVT:TX_DONE
Esse resultado comprova TX local. O confirmed uplink posterior forneceu a prova da rede:
AT+CFM=1
AT+SEND=10:A5000001
OK
+EVT:SEND_CONFIRMED_OK
AT+CFS=?
AT+CFS=1
OK
24. Prova ABP na TTN e dissecação do frame
[CAPTURA DE TELA — Live Data da TTN mostrando o confirmed uplink ABP, frequência 917,2 MHz, FCnt, FPort 10 e downlink ACK]
A TTN registrou o confirmed uplink ABP em 917,2 MHz, SF7/BW125, RSSI aproximado de -66 dBm e SNR de 7 dB. O frame bruto em Base64 foi:
gM5UDSaABQAK1Rkzh3AZdMU=
Decodificando os bytes:
80 CE 54 0D 26 80 05 00 0A D5 19 33 87 70 19 74 C5
Interpretação dos campos públicos:
80 -> MHDR: Confirmed Data Up
CE 54 0D 26 -> DevAddr on-air, little-endian
-> 26 0D 54 CE = 260D54CE
80 -> FCtrl com ADR
05 00 -> FCnt = 5 (LSB)
0A -> FPort = 10
... -> FRMPayload criptografado + MIC
Esse exemplo é valioso porque demonstra por que procurar diretamente 26 0D 54 CE em uma captura on-air pode falhar: DevAddr é transmitido em little-endian no frame LoRaWAN. A TTN também gerou downlink com ack=true. Assim, a sequência SEND_CONFIRMED_OK + CFS=1 não era apenas um status local; ela correspondia a um ACK real do Network Server. Um segundo uplink ABP, não confirmado, foi visto em 917,6 MHz/CH12, mantendo a operação dentro de FSB2.
25. OTAA RUI3: descoberta da sintaxe real de JOIN
A documentação genérica permitia imaginar uma forma estendida de join. A build específica respondeu:
AT+JOIN=1:0:10:8
AT_PARAM_ERROR
Enquanto a forma simples funcionou imediatamente:
AT+JOIN=1
OK
+EVT:JOINED
AT+NJS=?
AT+NJS=1
OK
Essa descoberta ilustra novamente a regra do projeto: runtime real da build tem precedência sobre uma suposição baseada em documentação de outra versão.
26. Prova OTAA completa: JoinRequest e JoinAccept na TTN
[CAPTURA DE TELA — JoinRequest OTAA em 916,8 MHz e JoinAccept com AU_915_928_FSB_2, RX delay e CFList]
No ciclo posterior ao P2P, foi realizado um join fresco. A TTN registrou:
DevEUI: 0080E115051FC14F
JoinEUI: 0101010101010101
DevNonce: 0002
Frequência: 916.8 MHz
Canal: CH8
Modulação: SF10/BW125
RSSI: -79 dBm
SNR: 5.5 dB
Isso é uma prova forte de que o uplink OTAA saiu exatamente dentro da FSB2. O JoinAccept posterior trouxe: rx_delay = 5
rx2_dr = 8
frequency_plan_id = AU_915_928_FSB_2
E a CFList habilitou exatamente:
CH8, CH9, CH10, CH11, CH12, CH13, CH14, CH15, CH65
Assim, três camadas concordaram entre si:
módulo: AT+MASK=? -> 0002
TTN: frequency_plan_id -> AU_915_928_FSB_2
JoinAccept CFList -> 8..15 + 65
27. Um erro de temporização AT revelado pelo cruzamento TTN x UART
Uma sequência automatizada de comandos AT encontrou um problema que, se fosse analisado somente pelo modem, poderia ser confundido com perda de downlink. Antes do teste OTAA, o módulo reportava:
AT+RX1DL=?
5
A sequência de configuração forçou:
AT+RX1DL=1
Em seguida, os confirmed uplinks começaram a terminar em:
+EVT:SEND_CONFIRMED_FAILED(4)
AT+CFS=?
AT+CFS=0
Entretanto, o Live Data da TTN mostrou que esses uplinks chegaram. A TTN ainda programava o retorno com rx1_delay=5.
O diagnóstico ficou claro:
modem foi configurado para abrir RX1 em 1 s
TTN agenda o downlink para RX1 em 5 s
modem fecha a janela cedo demais
ACK existe na rede, mas o dispositivo não o ouve
Depois de um JoinAccept fresco, o próprio módulo voltou a apresentar RX1DL=5. Portanto, a correção da v5.2 foi parar de sobrescrever indiscriminadamente um timing já estabelecido pela rede. Esse é um dos melhores exemplos do valor da metodologia multicamada: o log do modem dizia “confirmed failed”, enquanto a TTN dizia “uplink recebido e downlink agendado”. A falha estava no sincronismo da janela, não no uplink RF.
28. AT_BUSY_ERROR: por que um próximo SEND não deve começar cedo demais
Outra falha da v5.1 foi iniciar um novo probe antes de a transação anterior ter terminado. Em Class A, TX_DONE não significa que a transação acabou. Ainda podem ocorrer RX1, RX2 e retransmissão de confirmed packet. Nos probes OTAA apareceram AT_BUSY_ERROR entre tentativas. A solução adotada para a revisão seguinte foi:
- usar RETY=0 durante caracterização determinística;
- esperar o ciclo real de RX;
- se houver
AT_BUSY_ERROR, esperar e repetir o mesmo probe, sem consumir a amostra estatística; - separar “comando não pôde iniciar porque a MAC estava ocupada” de “falha RF”.
29. P2P RUI3: ping-pong byte a byte
[VÍDEO — ping-pong P2P entre os dois módulos, mostrando payload crescente e a validação byte-exact em 250 bytes]
Depois de validar LoRaWAN, os dois módulos foram colocados em P2P LoRa e testados em ping-pong real. O receptor foi colocado em RX contínuo/duplex compatível com a build, e cada pacote foi validado contra o payload esperado. Não bastava ocorrer RX; o conteúdo precisava ser idêntico byte a byte. A progressão incluiu:
1, 8, 16, 32, 64, 96, 128, 160, 192, 224 bytes
225, 226, ... 249, 250 bytes
Em 250 bytes:
ABP -> OTAA
exact=True
TX=True
RSSI ~ -76 dBm
SNR ~ 12 dB
OTAA -> ABP
exact=True
TX=True
RSSI ~ -76 dBm
SNR ~ 12 dB
Em 251 bytes, duas tentativas falharam antes da transmissão:
PING exact=False TX=False
PONG exact=False TX=False
O transcript indicou rejeição do comando (AT_PARAM_ERROR) em vez de degradação gradual do enlace RF. Conclusão experimental para RUI_4.2.4_RAK3272-SiP:
máximo bidirecional comprovado: 250 bytes
251 bytes: rejeitado pela interface/firmware
O limite operacional da suíte seguinte foi, portanto, definido em 250 bytes.
30. Por que o antigo limite de 242 bytes mudou
Nas versões SJIT anteriores, 242 bytes havia sido adotado como limite seguro experimental. O validador offline chegou a codificar essa regra. Com o RUI3, o ensaio foi estendido deliberadamente byte a byte acima de 242 e mostrou sucesso em 243-250 bytes. Portanto, o documento deve distinguir:
Firmware SJIT / baseline histórica: 242 B como limite seguro adotado
RUI3 4.2.4 / ensaio atual: 250 B como limite comprovado
Não é recomendável extrapolar “250 bytes” para qualquer firmware ou qualquer configuração P2P; o valor está vinculado à build e ao modo testados.
31. Política AT: ler antes de escrever
Os ensaios mostraram que vários setters possuem efeitos colaterais ou dependem do estado da MAC. Por isso, a política mais segura passou a ser:
GET
-> normalizar valor
-> comparar com o alvo
-> se já estiver correto: não escrever
-> se estiver diferente: SET
-> GET novamente
-> validar o readback
Essa regra é especialmente importante para comandos relacionados a modo, região, máscara, identidade e sessão. No firmware legado, reescrever AppEUI, DevAddr ou outros parâmetros podia alterar DevNonce, contador ou contexto; no RUI3, a mesma prudência evita sobrescrever parâmetros que acabaram de ser negociados pela rede. No RUI3, o procedimento foi aplicado a NWM, NJM, BAND, MASK, PNM, CLASS, ADR, RX1DL, RX2DL, RX2FQ, RX2DR, DevEUI e DevAddr.
32. Comparação das três gerações de firmware
Tema Firmware A – fábrica Firmware B – SJIT V1.0.4 Firmware C – RUI3 UART 9600 8N1 9600 8N1 115200 8N1 OTAA funcional após convergência interface atualizada, mas testes funcional; JoinRequest/
travados por CHMASK/estado JoinAccept comprovados
ABP funcional, porém sensível a CHMASK existe, mas setter funcional com MASK=0002; ACK
FSB2/FCnt/ATZ problemático confirmado
Channel mask não exposta por AT seis words; comportamento MASK=0002, simples e
instável comprovado
Frame counter não exposto na baseline ABPFCNT disponível sessão gerenciada de outra
forma; não usar resets
destrutivos
Reset ATZ perigoso para sessão continua sendo risco ATZ/ATR evitados durante a
validação normal
P2P funcional; limite seguro histórico disponível byte-exact até 250 B
242 B
Diagnóstico debug detalhado, mas parser mais recursos, mais estados eventos RUI3 claros e AT help
complexo amplo
32.1. Comparação quantitativa das campanhas
Cenário Comandos/transmissões Dentro de FSB2 Recebidos/aceitos ACK APP V1.0.0 – 96 TX_DONE 11/96 retorno de rede variável campanha ampla observado, mas sem
convergência estável
APP V1.0.0 – R13 32 confirmed 5/32 5/32 no gateway, 0/32
exatamente os 5 em FSB2
APP V1.0.0 – 5 frames documentados 5/5 5/5 TTN confirmed FCnt 792 com sessão saudável ACK anterior RUI3 – ABP final 32 confirmed 32/32 32/32 TTN 32/32 RUI3 – OTAA final 32 confirmed 32/32 32/32 TTN 32/32
Essa tabela evita uma leitura simplista de “firmware antigo não transmitia”. Ele transmitia; o problema era que, em determinados estados, transmitia no conjunto regional errado para o gateway, perdia continuidade de sessão ou não recebia o downlink esperado.
33. Windows, Linux e macOS: roteiro prático de conexão serial
Windows
- instalar o driver Silicon Labs CP210x VCP quando o conversor do DevKit não aparecer automaticamente;
- conferir a porta em Gerenciador de Dispositivos;
- Firmware A/B: começar em 9600 8N1;
- Firmware C/RUI3: começar em 115200 8N1;
- testar AT e depois um comando de versão antes de qualquer setter.
Exemplo RUI3:
AT
OK
AT+VER=?
AT+VER=RUI_4.2.4_RAK3272-SiP
OK
Linux Localizar a serial: ls -l /dev/ttyUSB*
Abrir com picocom, por exemplo no RUI3:
picocom -b 115200 --databits 8 --parity n --stopbits 1 /dev/ttyUSB2
Nos ensaios automatizados, a serial foi mantida em 8N1 e os eventos assíncronos foram preservados integralmente no log.
macOS O fluxo é equivalente: identificar a interface serial criada pelo driver/VCP e usar um terminal serial ou uma sequência automatizada de comandos AT. O ponto importante é que o protocolo do dispositivo não muda com o sistema operacional; o que muda é o nome do device e o driver do bridge USB-UART.
34. Guia de reprodução – RUI3 ABP
Este roteiro é uma referência técnica e deve ser adaptado às credenciais do próprio ambiente.
AT+NWM=1
AT+NJM=0
AT+CLASS=A
AT+BAND=6
AT+MASK=0002
AT+PNM=1
AT+ADR=1
AT+DEVEUI=<DEV_EUI_ABP>
AT+DEVADDR=<DEV_ADDR_ABP>
AT+NWKSKEY=<REDACTED>
AT+APPSKEY=<REDACTED>
Auditoria regional:
AT+BAND=?
AT+MASK=?
AT+CHE=?
AT+CHS=?
O valor crítico esperado é:
BAND = 6
MASK = 0002
Uplink não confirmado:
AT+CFM=0
AT+SEND=10:01020304
Uplink confirmado:
AT+CFM=1
AT+SEND=10:A1B2C3D4
AT+CFS=?
CFS=1 deve ser correlacionado com a TTN para provar que o ACK pertence à transmissão observada.
35. Guia de reprodução – RUI3 OTAA
Configuração base:
AT+NWM=1
AT+NJM=1
AT+CLASS=A
AT+BAND=6
AT+MASK=0002
AT+PNM=1
AT+ADR=1
AT+DEVEUI=<DEV_EUI_OTAA>
AT+APPEUI=<JOIN_EUI>
AT+APPKEY=<REDACTED>
Nesta build, o join comprovado foi:
AT+JOIN=1
Aguardar o evento assíncrono:
+EVT:JOINED
E conferir:
AT+NJS=?
AT+NJS=1
OK
Depois de um JoinAccept, não sobrescrever imediatamente parâmetros negociados pela rede sem uma razão explícita. Em especial, o ensaio atual mostrou rx_delay=5 vindo da TTN.
36. Guia de reprodução – P2P 250 bytes
A configuração P2P depende dos parâmetros escolhidos, mas a metodologia de validação deve permanecer:
- colocar os dois módulos no mesmo perfil P2P
- colocar B em recepção
- A envia payload determinístico
- extrair payload recebido em B
- comparar byte a byte
- inverter direção
- repetir tamanhos crescentes
- repetir 250 B várias vezes
O importante é não classificar sucesso apenas por TX_DONE; o receptor precisa provar integridade do payload.
37. O payload formatter da TTN pode gerar “dados falsos” em testes
Os payloads de teste, como A5…, passaram pelo decoder de aplicação que já existia na TTN. Por isso, o Live Data chegou a exibir campos como latitude, bateria e firmware com valores sem sentido. Isso não significa corrupção do LoRaWAN. O payload bruto recebido estava correto; o problema era semântico: o formatter estava interpretando bytes de teste segundo um protocolo de aplicação diferente. Para futuros ensaios, recomenda-se uma destas opções:
- desabilitar temporariamente o formatter;
- reservar um prefixo de payload para “frame de laboratório” e fazer o decoder ignorá-lo;
- validar sempre frm_payload/raw bytes antes de olhar campos decodificados.
38. Validação final RUI3: 32 transmissões OTAA + 32 transmissões ABP

A fase final deixou de usar um único pacote como prova e passou a executar 32 confirmed uplinks por método. Durante essa bateria, RETY=0 foi usado para que cada comando AT+SEND representasse uma amostra lógica única, sem retransmissão automática escondida. Resultado global:
OTAA: 32/32 confirmed uplinks com ACK
ABP : 32/32 confirmed uplinks com ACK
TOTAL confirmed: 64/64
busy retries: 0
timeouts: 0
Além desses 64 frames, um uplink pós-P2P foi recebido de cada dispositivo, totalizando 66/66 uplinks LoRaWAN correlacionados com a TTN.
38.1. OTAA – distribuição de canais e ADR
Todos os 32 confirmed uplinks OTAA ficaram em CH8–CH15:
Frequência | Canal |
916.8 MHz | CH8 |
917.0 MHz | CH9 |
917.2 MHz | CH10 |
917.4 MHz | CH11 |
917.6 MHz | CH12 |
917.8 MHz | CH13 |
918.0 MHz | CH14 |
918.2 MHz | CH15 |
917.5 MHz / 500 kHz | CH65 |
A progressão de ADR observada foi:
FCnt 1 -> SF10
FCnt 2 -> SF9
FCnt 3-4 -> SF8
FCnt 5-32 -> SF7
RSSI médio aproximado: -71,7 dBm. SNR médio: 7,9 dB. A TTN registrou LinkADRReq e respostas de aceitação.
38.2. ABP – distribuição de canais e continuidade
O ABP também permaneceu integralmente em CH8–CH15:
Frequência | Canal | Quantidade |
916,8 MHz | CH8 | 4 |
917,0 MHz | CH9 | 4 |
917,2 MHz | CH10 | 4 |
917,4 MHz | CH11 | 4 |
917,6 MHz | CH12 | 3 |
917,8 MHz | CH13 | 4 |
918,0 MHz | CH14 | 4 |
918,2 MHz | CH15 | 5 |
Os payloads A5000001 até A5000020 foram encontrados na TTN. O FCnt da sessão foi de 7 a 38, preservando a continuidade já existente. RSSI médio: -65,4 dBm; SNR médio: 8,5 dB. A comparação histórica é direta:
APP V1.0.0 - R13:
5/32 em FSB2, 27/32 fora, 0 ACK
RUI3 4.2.4:
32/32 em FSB2, 32/32 ACK
Essa mudança é uma das evidências mais fortes de que AT+BAND=6 + AT+MASK=0002 resolveu de forma determinística o problema regional que antes dependia do acaso/hopping e de downlinks de gerenciamento.
39. Critério AT usado para declarar sucesso ponta a ponta
Durante a fase final, cada camada continuou sendo interpretada separadamente:
OK -> comando AT aceito
+EVT:TX_DONE -> transmissão local concluída, quando emitido
+EVT:SEND_CONFIRMED_OK -> confirmed recebeu resposta válida
AT+CFS=1 -> último confirmed foi confirmado
Live Data TTN -> frame efetivamente aceito pela rede
O resultado só foi considerado ponta a ponta quando a resposta do modem e o registro da TTN concordaram. Essa distinção evita dois falsos diagnósticos históricos: tratar OK como prova de rede e tratar ausência de TX_DONE como prova de ausência de RF.
40. Matriz de falhas e diagnóstico rápido
Sintoma Não concluir imediatamente Verificação correta OK após SEND “TTN recebeu” esperar evento e consultar gateway/TTN TX_DONE “ACK recebido” confirmed status / CFS / Live Data TTN não mostra frame “rádio não transmitiu” debug TX + Packet Forwarder rxpk gateway vê frame, TTN não “gateway está ruim” DevAddr, MIC, FCnt, sessão, LNS AT_BUSY_ERROR “falha RF” aguardar RX1/RX2/retry e repetir comando confirmed failed, TTN vê uplink “uplink ruim” comparar timing RX/downlink ABP funciona após recriar device “foi acaso” investigar FCnt/session rollback CHMASK trava UART “baud mudou” autodetect 9600/115200; power cycle;
revisar firmware
payload decodificado absurdo “payload corrompeu” comparar raw frm_payload com payload
esperado
41. Lições de engenharia consolidadas
41.1. Região não é sub-banda
AU915 define a região. FSB2 é um subconjunto de canais. Uma API que permite selecionar somente AU915, mas não controlar canais, pode exigir convergência via rede.
41.2. ABP não é “OTAA sem join”
A ausência do JoinAccept muda o mecanismo de bootstrap regional. Esse detalhe foi a origem de boa parte da diferença operacional entre os dois métodos.
41.3. Reset não é operação neutra
Um reset/factory reset pode alterar counters, região, sessão e estado NVM. Em um modem LoRaWAN, isso pode invalidar uma sessão sem que a UART revele toda a diferença.
41.4. O gateway é uma fonte de verdade intermediária
Quando existe dúvida entre rádio e Network Server, a captura do Packet Forwarder é extremamente valiosa. Ela transforma “acho que transmitiu” em “o SX1301 demodulou este PHYPayload nesta frequência com este RSSI/SNR”.
41.5. Documentação deve ser validada contra runtime
A investigação encontrou comandos ausentes em uma versão, sintaxes diferentes entre builds e um JOIN estendido rejeitado pelo RUI3 específico. A documentação é indispensável, mas deve ser versionada e confrontada com o firmware real.
41.6. Um setter AT já correto deve ser evitado
Uma suíte de testes pode causar o problema que pretende diagnosticar se resetar, reescrever credenciais ou alterar timing a cada execução. A política read-before-write foi a resposta a isso.
42. O que esta investigação ainda pode render em conteúdos separados
Uma publicação futura pode ser dividida em uma série mais acessível:
- Conhecendo o LSM110A e o DevKit SmartCore – hardware, UART, SWD e formas de uso;
- Montando um laboratório LoRaWAN remoto – Raspberry Pi, Banana Pi, Tailscale, SSH, gateway e keep-alive;
- Como descobrir o que um firmware realmente suporta – AT?, getters, setters, raw logs e parser;
- AU915 x FSB2 na prática – por que selecionar a banda não é selecionar a sub-banda;
- OTAA: JoinRequest, JoinAccept e CFList vistos na TTN;
- ABP: DevAddr,
FCnte por queATZpode destruir sua sessão; - Capturando Semtech UDP/1700 e interpretando frames do gateway;
8. Atualizando o LSM110A com ST-LINK/STM32CubeProgrammer;
- Migrando para RAK RUI3 e entendendo MASK=0002;
- P2P ping-pong: como medir o limite real de payload;
- Como montar uma sequência de configuração AT idempotente e segura.
A vantagem dessa divisão é preservar o caminho de descoberta, em vez de publicar apenas uma lista de comandos finais sem explicar por que eles são necessários.
43. Identificadores usados na bancada
Papel DevEUI Observação OTAA 0080E115051FC14F JoinEUI 0101010101010101 ABP 0080E115051FD6B4 DevAddr validado 260D54CE
Chaves criptográficas foram deliberadamente removidas.
44. Tabela de canais AU915 FSB2
Canal | Tipo | Frequência |
8 | 125 kHz | 916.8 MHz |
9 | 125 kHz | 917.0 MHz |
10 | 125 kHz | 917.2 MHz |
11 | 125 kHz | 917.4 MHz |
12 | 125 kHz | 917.6 MHz |
13 | 125 kHz | 917.8 MHz |
14 | 125 kHz | 918.0 MHz |
15 | 125 kHz | 918.2 MHz |
65 | 500 kHz | 917.5 MHz |
45. Evidências principais preservadas
E-01 – Baseline V1.0.0 Relatórios e results.json de 02-04/09/2026: APP V1.0.0, MW_LORAWAN V2.4.0, SW V0.0.24, UART 9600, CHMASK/BAUDRATE ausentes. E-02 – OTAA e CFList Live Data/relatório inicial: JoinRequest fora da FSB2 falhou; JoinRequest posterior dentro da FSB2 foi aceito; JoinAccept aplicou channel masks. E-03 – Hopping ABP amplo Série de 64 uplinks mostrou CH0–CH63 antes de convergência; debug registrou TX fora e dentro da FSB2. E-04 – Packet Forwarder lorawan_udp1700.txt: rxpk, frequência, SF/BW, RSSI/SNR e Base64 capturados diretamente no UDP/1700.
E-05 – ATZ/FCnt Relatório 07/09: sessão ativa -> ATZ -> mesma configuração -> TTN deixa de aceitar; comportamento compatível com rollback de contador/estado. E-06 – Firmware B V1.0.4 Logs 11/09: capability CHMASK/ABPFCNT/DEVNONCE presente; AT+CHMASK=FF00:...:0002:0000 -> AT_NO_NETWORK_JOINED; depois UART sem resposta em 9600 e 115200.
E-07 – RUI3 Runtime: RUI_4.2.4_RAK3272-SiP, 115200 8N1, BAND=6, MASK=0002. E-08 – OTAA RUI3 real TTN 12/09: JoinRequest 916.8 MHz CH8, SF10/BW125, RSSI -79, SNR 5.5; JoinAccept rx_delay=5, RX2 DR8 e CFList 8-15/65. E-09 – ABP confirmed TTN 12/09: confirmed uplink FCnt 5, FPort 10, 917.2 MHz SF7/BW125, RSSI -66, SNR 7; downlink ACK; modem SEND_CONFIRMED_OK, CFS=1. E-10 – P2P RUI3: ping-pong byte-exact até 250 B; 251 B rejeitado por AT_PARAM_ERROR; na bateria final, 39/39 ping-pongs e 78/78 entregas direcionais foram byte-exact. E-11 – Bateria final de confiabilidade RUI3 32/32 confirmed OTAA + 32/32 confirmed ABP com ACK; todos os 64 uplinks dentro de CH8–CH15; 66/66 uplinks LoRaWAN correlacionados considerando os dois probes pós-P2P.
45.1. Tabela completa da campanha R13 – APP V1.0.0
A tabela abaixo preserva as 32 transmissões confirmed usadas para demonstrar o hopping amplo. Ela é particularmente útil para um tutorial porque mostra que o gateway recebeu exatamente os casos em que a frequência caiu no bloco físico CH8–CH15.
# | Payload | Canal TX | Frequência | DR | FSB2? | Gateway | FCnt | ACK |
1 | ABR001 | CH16 | 918,4 MHz | 2 | não | – | – | não |
2 | ABR002 | CH4 | 916,0 MHz | 2 | não | – | – | não |
3 | ABR003 | CH30 | 921,2 MHz | 2 | não | – | – | não |
4 | ABR004 | CH5 | 916,2 MHz | 2 | não | – | – | não |
5 | ABR005 | CH40 | 923,2 MHz | 2 | não | – | – | não |
6 | ABR006 | CH8 | 916,8 MHz | 2 | sim | CRC_OK | 17 | não |
7 | ABR007 | CH6 | 916,4 MHz | 2 | não | – | – | não |
8 | ABR008 | CH60 | 927,2 MHz | 2 | não | – | – | não |
9 | ABR009 | CH12 | 917,6 MHz | 2 | sim | CRC_OK | 20 | não |
10 | ABR010 | CH37 | 922,6 MHz | 2 | não | – | – | não |
11 | ABR011 | CH14 | 918,0 MHz | 2 | sim | CRC_OK | 22 | não |
12 | ABR012 | CH49 | 925,0 MHz | 2 | não | – | – | não |
13 | ABR013 | CH43 | 923,8 MHz | 2 | não | – | – | não |
14 | ABR014 | CH61 | 927,4 MHz | 2 | não | – | – | não |
15 | ABR015 | CH15 | 918,2 MHz | 2 | sim | CRC_OK | 26 | não |
16 | ABR016 | CH13 | 917,8 MHz | 2 | sim | CRC_OK | 27 | não |
17 | ABR017 | CH62 | 927,6 MHz | 2 | não | – | – | não |
18 | ABR018 | CH38 | 922,8 MHz | 2 | não | – | – | não |
19 | ABR019 | CH32 | 921,6 MHz | 2 | não | – | – | não |
20 | ABR020 | CH17 | 918,6 MHz | 2 | não | – | – | não |
21 | ABR021 | CH29 | 921,0 MHz | 2 | não | – | – | não |
22 | ABR022 | CH45 | 924,2 MHz | 2 | não | – | – | não |
23 | ABR023 | CH48 | 924,8 MHz | 2 | não | – | – | não |
24 | ABR024 | CH52 | 925,6 MHz | 2 | não | – | – | não |
25 | ABR025 | CH35 | 922,2 MHz | 2 | não | – | – | não |
26 | ABR026 | CH23 | 919,8 MHz | 2 | não | – | – | não |
27 | ABR027 | CH19 | 919,0 MHz | 2 | não | – | – | não |
28 | ABR028 | CH21 | 919,4 MHz | 2 | não | – | – | não |
29 | ABR029 | CH47 | 924,6 MHz | 2 | não | – | – | não |
30 | ABR030 | CH18 | 918,8 MHz | 2 | não | – | – | não |
31 | ABR031 | CH51 | 925,4 MHz | 2 | não | – | – | não |
32 | ABR032 | CH63 | 927,8 MHz | 2 | não | – | – | não |
Resumo: 5/32 em FSB2, 27/32 fora, 5/32 CRC_OK no gateway e 0/32 ACK.
46. Conclusão: qual firmware eu usaria no LSM110A hoje?
O principal resultado desta investigação não foi simplesmente encontrar uma sequência de comandos capaz de fazer o LSM110A transmitir. O mais importante foi entender, com evidências de UART, gateway e TTN, como cada firmware se comportava e se ele era confiável o suficiente para servir como base para o uso do equipamento — e, posteriormente, para o desenvolvimento de uma biblioteca.
Ao longo dos testes, os três firmwares apresentaram comportamentos bastante diferentes.
46.1 Firmware A — o firmware original do DevKit
O firmware que veio originalmente nos DevKits mostrou desde o início que o hardware era perfeitamente capaz de operar LoRaWAN. OTAA funcionava e o dispositivo conseguia transmitir e receber informações da rede.
O problema apareceu principalmente quando comecei a analisar o comportamento com mais profundidade, especialmente em ABP.
Os principais pontos observados foram:
- a seleção de
AU915não significava que o módulo ficaria automaticamente restrito à FSB2 utilizada pela TTN; - no ABP, o módulo podia transmitir em diversos canais da região AU915, fazendo com que apenas parte das transmissões coincidisse com os canais monitorados pelo gateway;
- em uma campanha de 32 transmissões confirmed, somente 5/32 caíram dentro da FSB2, e foram exatamente esses cinco frames que o gateway conseguiu receber;
- em outra campanha maior, de 96 transmissões, somente 11/96 ocorreram dentro do conjunto esperado;
- o uso de determinados comandos de configuração podia exigir um
ATZantes de permitir a alteração dos parâmetros; - esse processo de reset e reprovisionamento podia quebrar a continuidade da sessão ABP, principalmente em relação ao frame counter;
- houve situações em que o gateway comprovava que o rádio havia transmitido o frame, mas a TTN já não o aceitava dentro da sessão existente.
Esse último ponto foi especialmente importante. Ele mostrou que um problema LoRaWAN não pode ser analisado apenas olhando a resposta do comando AT.
Era perfeitamente possível ter:
AT+SEND→ transmissão RF realizada→ gateway recebe o pacote→ TTN rejeita o frame
Ou seja, o problema não estava necessariamente no rádio ou no gateway. Em alguns casos, estava no estado da sessão LoRaWAN.
A captura do Packet Forwarder foi fundamental justamente para separar essas situações.
Portanto, o Firmware A comprovou que a pilha LoRaWAN funcionava, mas não apresentou o nível de previsibilidade necessário, principalmente em ABP, gerenciamento de canais e persistência de estado, para que eu o considerasse uma base ideal para o objetivo do projeto.
46.2 Firmware B — a atualização SJIT
A primeira atualização de firmware parecia inicialmente resolver uma das principais limitações do Firmware A.
Ela adicionava comandos como:
AT+CHMASKAT+ABPFCNTAT+DEVNONCEAT+BAUDRATE
e outros recursos relacionados ao gerenciamento da sessão.
Isso era exatamente o tipo de controle que estava faltando.
Na teoria, AT+CHMASK permitiria restringir explicitamente os canais utilizados pelo módulo e, portanto, solucionar o comportamento imprevisível observado anteriormente no ABP.
Na prática, porém, surgiu outro problema.
A implementação do CHMASK apresentou um comportamento pouco consistente. A própria forma de representação já era incomum para uma interface AT, expondo estruturas semelhantes ao array interno channel_mask[].
Durante os testes, comandos de configuração da máscara chegaram a retornar:
AT_NO_NETWORK_JOINED
e houve situações em que, depois da tentativa de configurar a máscara, a UART deixou de responder completamente.
Nesses casos, nem:
AT
nem:
AT+VER=?
obtinham resposta, tanto a 9600 como a 115200 baud.
A recuperação exigia um power cycle do dispositivo — que, no meu laboratório remoto, acabou sendo feito reiniciando o Raspberry Pi responsável por alimentar os DevKits pelas portas USB.
Portanto, apesar de o Firmware B introduzir comandos que aparentemente resolviam limitações importantes do firmware original, a implementação desses recursos não apresentou a robustez que eu esperava durante os ensaios.
Ao invés de continuar acumulando workarounds sobre uma interface que já havia demonstrado comportamentos instáveis, passei a procurar uma terceira alternativa.
46.3 Firmware C — RAK RUI3
A mudança para o firmware RAK RUI3 alterou significativamente o comportamento do equipamento.
A primeira diferença já apareceu na própria UART:
RUI_4.2.4_RAK3272-SiP115200 8N1
Mas a mudança mais importante estava na forma como os parâmetros LoRaWAN podiam ser configurados.
Para AU915/FSB2, por exemplo, a configuração passou a ser explicitamente:
AT+BAND=6AT+MASK=0002
Isso substituiu toda a complexidade encontrada anteriormente com a representação de CHMASK.
O resultado também pôde ser comprovado na prática.
No OTAA, foi possível observar:
JoinRequest→ gateway→ TTN→ JoinAccept→ módulo
e a própria TTN confirmou que o dispositivo estava utilizando o plano:
AU_915_928_FSB_2
com os canais esperados:
CH8 até CH15+CH65
No ABP, os confirmed uplinks passaram a receber ACK normalmente.
A bateria final trouxe o resultado mais importante de toda a investigação:
OTAA32/32 confirmed uplinks com ACKABP32/32 confirmed uplinks com ACK
Além disso, todos os uplinks permaneceram dentro dos canais esperados da FSB2.
Considerando também os testes realizados depois da restauração do modo LoRaWAN após o P2P, foram 66/66 uplinks correlacionados com a TTN.
O P2P também pôde ser caracterizado de forma muito mais objetiva. O teste progressivo mostrou comunicação bidirecional e comparação byte a byte até:
250 bytes
Enquanto 251 bytes foram rejeitados pela própria interface do firmware.
Assim, dentro do cenário ensaiado, o RUI3 apresentou justamente o comportamento que eu procurava desde o início: configuração explícita, readback coerente, ABP reproduzível, OTAA reproduzível e P2P mensurável.
46.4 O que a comparação dos três firmwares mostrou
O contraste entre as versões ficou bastante evidente.
Firmware A — fábricaLoRaWAN: funcionalOTAA: funcionalABP: funcional, mas imprevisível em determinados estadosAU915/FSB2: difícil de controlar explicitamenteSessão/FCnt: sensível a reset e reprovisionamentoResultado: não suficientemente previsível para o objetivo do projeto
Firmware B — SJIT atualizado
LoRaWAN: recursos adicionais
CHMASK: disponível
Controle de FCnt: melhorado
Problema principal: comportamento instável na configuração da máscara/UART
Resultado: ainda não suficientemente robusto nos ensaios
Firmware C — RAK RUI3
AU915/FSB2: configuração explícita
ABP: 32/32 confirmed com ACK
OTAA: 32/32 confirmed com ACK
LoRaWAN total correlacionado: 66/66 uplinks
P2P: byte-exact até 250 bytes
Resultado: comportamento consistente no cenário testado
Essa comparação responde diretamente à pergunta que motivou toda a investigação.
Eu não precisava apenas descobrir qual firmware conseguia transmitir. Eu precisava descobrir qual firmware oferecia uma base suficientemente previsível para que eu pudesse confiar nos comandos AT e, posteriormente, construir uma biblioteca sobre eles sem simplesmente esconder problemas existentes em uma camada inferior.
O firmware original demonstrou que o hardware e a pilha LoRaWAN eram capazes de funcionar, mas apresentou limitações importantes de gerenciamento de canais e estado ABP.
A atualização SJIT intermediária acrescentou recursos que teoricamente resolveriam parte desses problemas, porém não apresentou a estabilidade necessária durante os testes.
Entre as opções efetivamente testadas, o RAK RUI3 foi o firmware que melhor satisfez os critérios de confiabilidade adotados nesta investigação.
É importante limitar essa conclusão ao que realmente foi ensaiado: toda a validação LoRaWAN deste trabalho foi realizada com a The Things Network em AU915/FSB2. Netmore/Everynet não fez parte desta campanha experimental.
O laboratório remoto também teve um papel importante nesse processo. Raspberry Pi, Banana Pi, Tailscale, SSH/SSHFS, Termux, captura do Packet Forwarder e os eventos da TTN permitiram investigar cada camada separadamente e continuar os testes mesmo quando determinados firmwares exigiam power cycle ou recuperação da UART.
No fim, a investigação deixou de responder apenas:
“O LSM110A funciona?”
e passou a responder uma pergunta muito mais útil:
“Qual combinação de firmware, comandos AT e configuração apresenta um comportamento suficientemente previsível para que o LSM110A possa ser utilizado de forma confiável e servir como base para o desenvolvimento posterior?”
Dentro do cenário que foi efetivamente testado, a resposta foi o RAK RUI3.
