Os rádios subgiga são incríveis – em particular, o LoRa (e mais intrinsecamente, o ESP32 LoRA) . A grande questão é que tudo tem contrapartida; quanto maior a banda, maior a velocidade de transmissão, mas menor alcance. Quanto menor a banda, menor velocidade de transmissão, mas maior alcance.
Um rádio LoRa rodando em 915MHz consegue transferir pouco mais de 37kbps. Não é pouco para mensagem, porém para arquivos binários é algo impactante. Mas ainda que venhamos a utilizar apenas mensagens, devemos ter determinados cuidados para evitar que sobrecarreguemos a banda de transmissão, não apenas do transmissor para o receptor, mas cuidando também para não sobrecarregar o receptor, ainda mais se ele for um concentrador de rádios.

Crie um protocolo de mensagens
Lhe parece bastante intuitivo uma mensagem como essa abaixo?
temp=32,umid=40,rele1=on,rele2=off,ad0=524
Parece um ótimo protocolo. Fazendo split em “,” já temos os campos separados. Depois, só validar os campos e fazer split no sinal “=”. Daí o segundo campo é o valor, a ser convertido para inteiro. Mas vamos às considerações;
de todos esses 43 Bytes, apenas 12 serão utilizados. E pior, poderiam ser apenas 8 (desconsiderando algo importante que falta nessa mensagem).
Usar mensagens nesse formato é péssimo para a transmissão e para o processamento. Se chegar uma mensagem de ruído de outro dispositivo que não pertença à sua rede LoRa, essa mensagem passará por processamento desnecessariamente.
Mais uma coisa importantíssima; esse formato é ótimo para leitura humana, mas quem vai “ver” a mensagem é uma microcontroladora, nada disso é necessário. Depois de recebido, se for necessário exibir para o usuário, então adiciona-se o respectivo texto, fora da transmissão do ESP32 LoRa.
Pode parecer exagero pensando 1 para 1, mas em indústria, agro-negócio, condomínios, muito provavelmente diversos dispositivos poderão estar se comunicando com um concentrador. E pode ser pior.
Imagine se toda a informação do seu dispositivo for enviada para um broker MQTT na nuvem, onde clientes do país inteiro concentram seus dados em um sistema de gerenciamento. Por isso, “menos é mais”. Fui claro?
Vejamos uma mensagem em um formato mais adequado:
32 40 1 0 524
Os valores sempre serão posicionais, portanto não há razão para usar identificadores.
Parece bem pequena a mensagem, mas o ideal é mandar os bytes. Desse modo (como mostrado anteriormente), ainda consome-se mais recursos do que o necessário. Então o formato melhorado seria:
20 28 1 0 00 ff ff 0e
“Hummm, aumentou de tamanho!” – Você pode ter pensado.
Se mandarmos em formato literal, cada caractere será 1 Byte, totalizando 13 Bytes. Mandando em Bytes, cada Byte é, bem; 1 Byte.
Não se incomode em ver o formato em hexa. Você não precisará calcular nada disso, o trabalho será todo do programa, como pode ser visto no código mais adiante.
Para finalizar, ainda será necessário garantir a origem da mensagem minimamente. Não podemos ler qualquer coisa que chegar e considerar verdadeira, por isso o ideal é colocar um identificador de início e um de fim de mensagem. Explico.
$ 32 40 1 0 524 \n
Voltando ao formato literal, podemos fazer interpretação humana, por isso o fiz na mensagem acima. Repare que ela inicia com “$”. Isso é, se a mensagem que chegar não tiver esse primeiro Byte, descarta-se imediatamente.
Se a mensagem que chegar iniciar com “$”, validamos o último Byte. Se a mensagem não terminar com “\n”, descarta-se a mensagem. Mas antes de tudo, temos que ler o buffer de qualquer maneira, então a primeira validação deveria ser o tamanho da mensagem.
Agora sim, temos um protocolo definido! Vejamos:
0 – início da mensagem
1 – temperatura
2 – umidade
3 – relay 1
4 – relay 2
5, 6, 7 e 8 – leitura do AD, que vai de 0 a 1023, portanto 4 Bytes.
9 – terminador
Desse modo, nossa mensagem final seria parecido com:
24 20 28 1 0 00 ff ff 0e 0a
Agora podemos escrever nosso código.
Código para comunicação com ESP32 LoRa
As bibliotecas estão disponíveis no repositório do Arduino, portanto não há o que se falar a respeito da instalação. Já em relação à configuração, um pequeno ajuste deve ser feito para funcionar adequadamente o rádio LoRa. Siga esse tutorial, suba o sketch. Tendo funcionado, apenas substitua o código de teste pelo código a seguir:
#include <Arduino.h> #include <SPI.h> #include <LoRa.h> #include <WiFi.h> #include "SSD1306.h" #include "board_def.h" #define OLED_ADDRESS 0x3c #define I2C_SDA 21 #define I2C_SCL 22 SSD1306Wire display(OLED_ADDRESS, I2C_SDA, I2C_SCL, GEOMETRY_128_32); #define WIFI_SSID "SuhankoFamily" #define WIFI_PASSWORD "fsjmr112" String topics[5]; int adc_sum = 0; struct msgRecv { uint8_t start = '$'; uint8_t temperature = 0; uint8_t humidity = 0; uint8_t relay_1 = 0; uint8_t relay_2 = 0; int adc_value = 0; uint8_t end = '\n'; } msg_recv; uint8_t msg_array[10] = {0}; void setup() { topics[0] = "Temp: "; topics[1] = "Umidade: "; topics[2] = "Rele 1: "; topics[3] = "Rele 2: "; topics[4] = "AD: "; Serial.begin(9600); while (!Serial); if (OLED_RST > 0) { pinMode(OLED_RST, OUTPUT); digitalWrite(OLED_RST, HIGH); delay(100); digitalWrite(OLED_RST, LOW); delay(100); digitalWrite(OLED_RST, HIGH); } display.init(); display.flipScreenVertically(); display.clear(); display.setFont(ArialMT_Plain_16); display.setTextAlignment(TEXT_ALIGN_CENTER); display.drawString(display.getWidth() / 2, display.getHeight() / 2, LORA_SENDER ? "LoRa Sender" : "LoRa Receiver"); display.display(); delay(2000); String info = "(bB)"; if (info != "") { display.clear(); display.setFont(ArialMT_Plain_16); display.setTextAlignment(TEXT_ALIGN_CENTER); display.drawString(display.getWidth() / 2, display.getHeight() / 2, info); display.display(); delay(2000); } WiFi.begin(WIFI_SSID, WIFI_PASSWORD); if (WiFi.waitForConnectResult() != WL_CONNECTED) { display.clear(); Serial.println("WiFi Connect Fail"); display.drawString(display.getWidth() / 2, display.getHeight() / 2, "WiFi Connect Fail"); display.display(); delay(2000); esp_restart(); } Serial.print("Connected : "); Serial.println(WiFi.SSID()); Serial.print("IP:"); Serial.println(WiFi.localIP().toString()); display.clear(); display.drawString(display.getWidth() / 2, display.getHeight() / 2, "IP:" + WiFi.localIP().toString()); display.display(); delay(2000); SPI.begin(CONFIG_CLK, CONFIG_MISO, CONFIG_MOSI, CONFIG_NSS); LoRa.setPins(CONFIG_NSS, CONFIG_RST, CONFIG_DIO0); if (!LoRa.begin(BAND)) { Serial.println("Starting LoRa failed!"); while (1); } if (!LORA_SENDER) { display.clear(); display.drawString(display.getWidth() / 2, display.getHeight() / 2, "LoraRecv Ready"); display.display(); } } void loop() { #if LORA_SENDER int32_t rssi; if (WiFi.status() == WL_CONNECTED) { rssi = WiFi.RSSI(); display.clear(); display.setTextAlignment(TEXT_ALIGN_CENTER); display.drawString(display.getWidth() / 2, display.getHeight() / 2, "Send RSSI:" + String(rssi)); display.display(); LoRa.beginPacket(); LoRa.print("WiFi RSSI: "); LoRa.print(rssi); LoRa.endPacket(); } else { Serial.println("WiFi Connect lost ..."); } delay(2500); #else if (LoRa.parsePacket()){ memset(msg_array,0,10); uint8_t counter = 0; //enquanto tiver dados para ler, tem que ler. while (LoRa.available()){ //armazena no buffer... msg_array[counter] = (char)LoRa.read(); if (msg_array[0] == '$'){ //...mas só incrementa a posição se o primeiro Byte for $ counter++; } //Se a mensagem chegou ao Byte 9 sem o LF, então sai do loop, porque o buffer está limitado a 10 Bytes if (counter > 9){ break; //mensagem alem do tamanho permitido } } //Saiu do loop. A mensagem que está no buffer parece ser legítima? if (msg_array[0] == msg_recv.start && msg_array[9] == msg_recv.end){ //Então compõe uma string para o usuário com o resultado de cada valor for (uint8_t i=1;i<5;i++){ display.clear(); String msg = topics[i-1] + String(msg_array[i]); display.drawString(display.getWidth() / 2, display.getHeight() / 2, msg.c_str()); display.display(); delay(800); } //E o valor AD tem 4 Bytes, portanto é necessário somá-los para entregar o valor correto ao usuário adc_sum = msg_array[5] + msg_array[6] + msg_array[7] + msg_array[8]; Serial.println(adc_sum); display.clear(); String msg2 = topics[4] + String(adc_sum); display.drawString(display.getWidth() / 2, display.getHeight() / 2, msg2.c_str()); display.display(); delay(800); } } #endif }
Repare que no código adicionei comentários nos tratamentos feitos na função loop().
Onde comprar o ESP32 LoRa Paxcounter ?
Esse lindíssimo ESP32 LoRa está disponível na UsinaInfo, e você pode conferir preço e disponibilidade através desse link. Não perca a oportunidade de ter um TTGO, você vai amar!
Sender LoRa
Para fazer os testes, utilizei o AFMultiRadio Black Edition da AFEletronica, desse outro artigo. Essa é outra placa indescritível, a qualidade é espetacular e é a primeira no mundo (pelo menos de todas as pesquisas que fiz) que possui 3 rádios LoRa 1276 e também a primeira do mundo que se comunica com os rádios diretamente pelo barramento SPI. Se quiser dar uma conferida na loja, clique nesse link.
1 comentário
Comments are closed, but trackbacks and pingbacks are open.