Utilizando LoRaWAN com Linux embarcado por Pedro Bertoleti

Utilizando LoRaWAN com Linux embarcado

Introdução

O uso de Linux em sistemas embarcados é, há anos, muito representativo. Os motivos para isso são muitos, dos quais destacam-se a robustez do sistema operacional e praticidade na implementação e uso de recursos complexos, como protocolos de comunicação industrial e interfaces gráficas em alta definição. Porém, nem sempre um equipamento com Linux embarcado se encontra em um local com acesso direto à Internet, sendo preciso portanto haver alternativas de conectividade, sobretudo para envios de dados pouco volumosos, como dados de telemetria e leituras de sensores.

Neste quesito, uma conectividade que se encaixa muito bem é o LoRaWAN, devido ao seu grande alcance e baixa demanda energética. Este artigo mostrará uma maneira de se utilizar LoRaWAN com Linux embarcado, utilizando uma Raspberry Pi 3 com Linux como sistema embarcado.

Como LoRaWAN se encaixa com Linux embarcado?

LoRaWAN serve muito bem a um propósito: envio e recepção de dados poucos volumosos (em termos práticos, algumas dezenas ou centenas de bytes ao dia). Logo, como isto se encaixaria em um cenário com Linux embarcado, considerando que um dispositivo deste porte é capaz de dar vida a soluções extremamente complexas e gerar um volume de dados bem expressivo?

A resposta para isso é simples: Edge Computing. Em poucas palavras, Edge Computing é a arquitetura de uma solução onde o processamento de dados (ou pré-processamento, a depender da aplicação) é feito no próprio dispositivo eletrônico, chamado dispositivo de borda.

Aplicando esta arquitetura Edge Computing, usa-se o LoRaWAN como conectividade para enviar somente dados processados, pré-processados e/ou compactados. Sistemas embarcados que rodam o Linux, por definição, possuem um hardware com poder computacional bastante relevante, permitindo a realização de uma infinidade de aplicações e processamento de dados no próprio dispositivo embarcado. Um exemplo muito ilustrativo disso é a área de visão computacional, onde um dispositivo embarcado é capaz de capturar e extrair dados de imagens, utilizando para isso uma série de ferramentas matemáticas e Inteligência Artificial.

Logo, como um dispositivo embarcado capaz de rodar Linux é também normalmente capaz de processar dados volumosos e complexos em tempo hábil, enviando para a nuvem (via LoRaWAN, neste caso) somente o resultado final deste processamento complexo é enviado, ou seja, apenas um volume de dados mínimo que resume todo o processamento feito inteiramente no dispositivo em borda.

Um exemplo disso seria um sistema embarcado com Linux que deve contabilizar um número de pessoas utilizando visão computacional. Neste caso, toda a captura, processamento da imagem e obtenção da contagem de pessoas é feito no próprio dispositivo embarcado, sendo que este envia para a nuvem somente poucos bytes contendo o valor da contagem realizada.

LoRaWAN: que hardware utilizar?

Das formas disponíveis de um hardware para conectividade LoRaWAN com Linux embarcado, uma das mais simples e, por muitas vezes, mais práticas alternativas é a utilização de um módulo LoRaWAN de mercado. Estes módulos são placas eletrônicas contendo toda a circuitaria necessária para, a partir de comandos AT, estabelecer uma comunicação LoRaWAN, conforme abaixo:

    • Circuitaria de RF;
    • Um microcontrolador simples, para permitir comunicação serial com o microcontrolador/SoC host da solução e embarcar a stack LoRaWAN;
    • Um chip transceiver LoRa (exemplo: SX1276);
    • Circuitaria de alimentação.

Estes módulos possuem maior facilidade de uso em relação a embarcar o stack LoRaWAN no Linux e fazê-lo conversar diretamente com um chip transceiver LoRa. Além disso, permitem que se delegue a um módulo dedicado toda a comunicação LoRaWAN.

Embora em alguns casos isso seja ligeiramente mais caro, essa abordagem leva a importantes vantagens, tais como permitir um menor uso de recursos computacionais por parte do Linux (focando estes no real propósito da solução), evitar problemas com timing na stack LoRaWAN e, ainda, garantir a comunicação LoRaWAN usando módulo consagrado, devidamente testado e inclusive homologado na Anatel (ponto extremamente importante se você almeja construir um produto próprio).

Neste artigo, será utilizado o módulo LoRaWAN do fabricante Radioenge, mostrado na Figura 1. Este módulo possui dimensões muito pequenas (3mm x 22mm x 33mm), opera com os modos OTAA e ABP e utiliza uma UART (3V3, 9600/8/N/1) como interface de comunicação com microcontrolador / SoC host, possui potência de saída de 20dBm e comporta uso de antena 915MHz com conector SMA (o módulo inclusive acompanha uma antena de 2.1dBi). Ainda, este módulo permite o uso de entradas e saídas digitais e entradas analógicas.

Figura 1 – módulo LoRaWAN (fabricante: Radioenge)

Este módulo é homologado na Anatel (Código: 02021-18-07215) e pode, portanto, ser integrado com segurança em um produto eletrônico. Para mais informações sobre este módulo LoRaWAN, clique aqui..

Atividade proposta

Neste artigo, para demonstrar o uso de LoRaWAN com Linux embarcado e módulo LoRaWAN (fabricante: Radioenge), será feito um software que tem como tarefas:

    • Abrir comunicação UART com o módulo LoRaWAN;
    • Inicializar o módulo LoRaWAN como classe A e modo ABP;
    • Se a abertura desta comunicação é sucedida, faz o envio da string “Teste” (ou seja, faz um uplink dessa string para a nuvem via LoRaWAN);
    • A comunicação UART é encerrada e o programa termina.

Materiais necessários

Para fazer a atividade proposta neste artigo, você precisará ter um mãos os seguintes materiais:

    • Uma placa Raspberry Pi 3 com cartão micro-SD e plenamente funcional (já configurada);
    • Fonte para a Raspberry Pi (5V/2A, com conector micro-USB);
    • Um módulo LoRaWAN Radioenge com antena (pode ser a própria que vem no módulo, de 2,1dBi);
    • Jumpers.

Circuito esquemático

O circuito esquemático para a comunicação da Raspberry Pi 3 com o módulo LoRaWAN é bem simples: resume-se às ligações de alimentação (5V e GND) e comunicação UART (TX e RX). Como o módulo LoRaWAN consome pouca energia (pico de consumo de corrente em 111mA na transmissão e consumo nominal em stand-by em apenas 1,8µA), a própria alimentação 5V da Raspberry Pi é mais do que suficiente para alimentar o módulo. Para detalhes do pinout do módulo LoRaWAN, observe a Figura 2.

Figura 2 – pinout do módulo LoRaWAN

(obtido do datasheet)

Desta forma, as ligações devem ser feitas conforme descrito na Tabela 1.

Raspberry Pi 3Módulo LoRaWAN
5V (pino 2)Alimentação VCC (pinos 4 e 5)
GNDAlimentação GND (pino 1)
TX (pino 8)RX (pino 2)
RX (pino 10)TX (pino 3)

Tabela 1 – ligações entre Raspberry Pi 3 e módulo LoRaWAN

Software para comunicação entre a Raspberry Pi e o módulo LoRaWAN

Agora é chegada a hora do código-fonte. Como exemplo de software para comunicar Raspberry Pi e módulo LoRaWAN, é utilizado o código-fonte apresentado na listagem 1.

É importante ressaltar que, para este exemplo funcionar, é necessário ter ao menos um plano de conectividade LoRaWAN ativo. Para isso, você precisa do DevEUI (fornecido em uma etiqueta colada ao módulo ou obtido via comando AT) e escolher uma das operadoras LoRaWAN disponíveis no Brasil. Para saber mais sobre as operadoras que vendem conectividade LoRaWAN (utilizando a infraestrutura da American Tower) no país, clique aqui.

Listagem 1 – código-fonte da atividade proposta:

#include
#include
#include
#include
#include
#include
#include

/* Definição – tamanho maximo das strings / chaves */
#define TAM_MAX_CMD_AT 80
#define TAM_NWSKEY_APPSKEY 60
#define TAM_APPEUI 30
#define TAM_DEVADDR 15

/* Definição – tempo de espera entre comandos AT */
#define TEMPO_ESPERA_COMANDO_AT 2000000 //us

/* Função: envia buffer via UART
* Parâmetros: – file descriptor da UART
* – ponteiro para buffer
* – tamanho do buffer
* Retorno: 1: envio ok
* 0: falha em um dos envios
*/
int envia_uart(int fd_uart, char * pt_buffer, int tam_buffer)
{
ssize_t bytes_escritos_na_uart = 0;
int status_escrita = 1;

bytes_escritos_na_uart = write(fd_uart, pt_buffer, tam_buffer);

if (bytes_escritos_na_uart != tam_buffer)
{
status_escrita = 0;
}

usleep(TEMPO_ESPERA_COMANDO_AT);
return status_escrita;
}

/* Função: configura módulo LoRaWAN para operação ABP

* Parâmetros: file descriptor da UART
* Retorno: 1: envio ok
* 0: falha em um dos envios
*/
int configura_modulo_lorawan(int fd_uart)
{
int status_envio = 0;
const char nwskey[TAM_NWSKEY_APPSKEY] = “NNNNNNNNNN\0”;
// Network session key
const char appskey[TAM_NWSKEY_APPSKEY] = “AAAAAAAAAA\0”;
// Application session key
const char appeui[TAM_APPEUI] = “AAAAAAAAAA\0”;
// Application EUI
const char devaddress[TAM_DEVADDR] = “EEEEEEEEEE\0”;
// Device Address
const char chmask[35] = “00FF:0000:0000:0000:0000:0000\0”;
// Máscara referente a Everynet (LA915)
char cmd_at[TAM_MAX_CMD_AT] = {0};
// Buffer de envio de comando AT

/* Envio do channel mask */
memset(cmd_at, ‘\0’, TAM_MAX_CMD_AT);
snprintf(cmd_at, TAM_MAX_CMD_AT, “AT+CHMASK=%s\n\r”, chmask);
if (!envia_uart(fd_uart, cmd_at, strlen(cmd_at)))
{
goto FIM_ENVIO;
}

/* Envio do join mode */
memset(cmd_at, ‘\0’, TAM_MAX_CMD_AT);
snprintf(cmd_at, TAM_MAX_CMD_AT, “AT+NJM=0\n\r”);
if (!envia_uart(fd_uart, cmd_at, strlen(cmd_at)))
{
goto FIM_ENVIO;
}

/* Envio do device address */
memset(cmd_at, ‘\0’, TAM_MAX_CMD_AT);
snprintf(cmd_at, TAM_MAX_CMD_AT, “AT+DADDR=%s\n\r”, devaddress);
if (!envia_uart(fd_uart, cmd_at, strlen(cmd_at)))
{
goto FIM_ENVIO;
}

/* Envio do application EUI */
memset(cmd_at, ‘\0’, TAM_MAX_CMD_AT);

snprintf(cmd_at, TAM_MAX_CMD_AT, “AT+APPEUI=%s\n\r”, appeui);
if (!envia_uart(fd_uart, cmd_at, strlen(cmd_at)))
{
goto FIM_ENVIO;
}

/* Envio do application session key */
memset(cmd_at, ‘\0’, TAM_MAX_CMD_AT);
snprintf(cmd_at, TAM_MAX_CMD_AT, “AT+APPSKEY=%s\n\r”, appskey);
if (!envia_uart(fd_uart, cmd_at, strlen(cmd_at)))

{
goto FIM_ENVIO;
}

/* Envio do network session key */
memset(cmd_at, ‘\0’, TAM_MAX_CMD_AT);
snprintf(cmd_at, TAM_MAX_CMD_AT, “AT+NWKSKEY=%s\n\r”, nwskey);
if (!envia_uart(fd_uart, cmd_at, strlen(cmd_at)))
{
goto FIM_ENVIO;
}

/* Desabilita ADR (Automatic Data Rate) */
memset(cmd_at, ‘\0’, TAM_MAX_CMD_AT);
snprintf(cmd_at, TAM_MAX_CMD_AT, “AT+ADR=0\n\r”);
if (!envia_uart(fd_uart, cmd_at, strlen(cmd_at)))
{
goto FIM_ENVIO;
}

/* Configura Data Rate e SPread Factor para máximo alcance
e menor payload. Aqui, o consumo do módulo é o maior
possível, porém a chance do payload chegar ao gateway é
significativamente maior. */
memset(cmd_at, ‘\0’, TAM_MAX_CMD_AT);
snprintf(cmd_at, TAM_MAX_CMD_AT, “AT+DR=0\n\r”);
if (!envia_uart(fd_uart, cmd_at, strlen(cmd_at)))
{
goto FIM_ENVIO;
}

/* Configura classe A para o LoRaWAN */
memset(cmd_at, ‘\0’, TAM_MAX_CMD_AT);
snprintf(cmd_at, TAM_MAX_CMD_AT, “AT+CLASS=A\n\r”);
if (!envia_uart(fd_uart, cmd_at, strlen(cmd_at)))
{
goto FIM_ENVIO;
}

/* Desliga confirmação de envio */
memset(cmd_at, ‘\0’, TAM_MAX_CMD_AT);
snprintf(cmd_at, TAM_MAX_CMD_AT, “AT+CFM=0\n\r”);
if (!envia_uart(fd_uart, cmd_at, strlen(cmd_at)))
{
goto FIM_ENVIO;
}

status_envio = 1;

FIM_ENVIO:
return status_envio;
}

int main (int argc, char *argv[])
{
/* Credenciais LoRaWAN
Lembre-se de substituir pelas suas!

*/
char cmd_at[TAM_MAX_CMD_AT] = {0};
// Buffer de envio de comando AT
struct termios options;
// Estrutura de configuração da UART
int porta_lorawan = 5;
// Porta LoRaWAN
int fd = 0;
// File descriptor para enviar dados para a UART
int result = 0;
// Variável que contém resultados/status das
// operações com UART

/* Abre conexão com a UART para comunicação com módulo
LoRaWAN, em modo escrita/leitura e modo não
blocante.
*/
fd = open(“/dev/ttyS0”, O_RDWR | O_NOCTTY);
if (fd == -1)
{
perror(“Impossivel se comunicar com a UART: “);
goto TERMINA_PROGRAMA;
}

/* Faz flush dos buffers de escrita e leitura da UART */
result = tcflush(fd, TCIOFLUSH);
if (result)
{
perror(“Impossivel fazer flush dos buffers da UART: “);
goto TERMINA_PROGRAMA;
}

/* Configura UART para 9600/8/N/1 */
result = tcgetattr(fd, &options);
if (result)
{
perror(“Impossivel obter configs atuais da UART: “);
goto TERMINA_PROGRAMA;
}

options.c_iflag &= ~(INLCR | IGNCR | ICRNL | IXON | IXOFF);
options.c_oflag &= ~(ONLCR | OCRNL);
options.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
options.c_cc[VTIME] = 1;
options.c_cc[VMIN] = 0;
cfsetospeed(&options, B9600);
cfsetispeed(&options, cfgetospeed(&options));

result = tcsetattr(fd, TCSANOW, &options);

if (result)
{
perror(“Impossivel configurar UART: “);
goto TERMINA_PROGRAMA;
}

/* Configura módulo LoRaWAN */

if (!configura_modulo_lorawan(fd))
{
perror(“Impossivel enviar comandos AT via UART: “);
goto TERMINA_PROGRAMA;
}

/* Faz envio da string de teste */
memset(cmd_at, ‘\0’, TAM_MAX_CMD_AT);
snprintf(cmd_at, TAM_MAX_CMD_AT, “AT+SEND=%d:Teste\n\r”,
porta_lorawan);
if (!envia_uart(fd, cmd_at, strlen(cmd_at)))
{
perror(“Impossivel enviar comandos AT via UART: “);
goto TERMINA_PROGRAMA;
}

/* Fecha comunicação UART com módulo LoRaWAN */
close(fd);

TERMINA_PROGRAMA:
printf(“\n\rPrograma terminado.\n\r”);
return 0;
}

Assumindo que o código-fonte da listagem 1 seja salvo como comm_modulo_lorawan.c, utilize na Raspberry Pi 3 o seguinte comando para compilar:

gcc comm_modulo_lorawan.c -o comm_modulo_lorawan -Wall

E, finalmente, para rodar o software, utilize o seguinte comando na Raspberry Pi 3:

sudo ./comm_modulo_lorawan

Após rodar o programa com sucesso, basta constatar o envio da mensagem utilizando a plataforma online da operadora LoRaWAN que você escolheu. Para visualizar quais operadoras LoRaWAN vinculadas à American Tower estão disponíveis, clique aqui.

Próximos passos

Caso desejar continuar a explorar o uso do módulo LoRaWAN e Linux embarcado, são sugeridos os seguintes pontos como próximos passos:

    • Ler do módulo LoRaWAN, as mensagens de downlink (ou seja, mensagens enviadas da nuvem/gateway LoRaWAN para o dispositivo na borda). Para se saber como ler mensagens de downlink recebidas pelo módulo LoRaWAN em questão, consulte o item “6.3.4 Recebendo mensagens do servidor”, presente datasheet do módulo LoRaWAN: https://www.radioenge.com.br/storage/2021/08/manual-lorawan-2021.pdf;
    • Ler do módulo os status dos comandos AT, de forma a detectar erros nos comandos e permitir a mitigação do erro reportado. Para se aprofundar mais nos comandos AT do módulo e nas suas respostas possível, consulte o datasheet do mesmo: https://www.radioenge.com.br/storage/2021/08/manual-lorawan-2021.pdf ;
    • Explorar as configurações de Data Rate e Automatic Data Rate de modo a se chegar ao melhor ponto de alcance LoRaWAN e consumo energético do seu projeto. Recomendo a leitura do seguinte artigo para compreender a influência destes e outros pontos da comunicação LoRaWAN no consumo energético: https://www.ncbi.nlm.nih.gov/pmc/articles/PMC8512702/

Sobre o Autor: Pedro Bertoleti é Consultor Tecnológico no Instituto de Pesquisas Eldorado. Você pode se conectar com o Pedro pelo LinkedIn clicando aqui.

Add a Comment

Your email address will not be published. Required fields are marked *