Queridos Alunos !
Eu assisti um vídeo que me deixou emocionado. Foi no canal do Lito Souza do Aviões e Músicas.
Então decidi tentar algo parecido usando meu Drone Phantom 4 e mais três ESP32 com rádio Lora.
Projetei um adaptador para meu drone de forma que transportasse com segurança o rádio com ESP32. Como sempre programei com Arduino IDE os ESPs e vou disponibilizar os códigos fontes aqui nesse post.
INTENÇÃO DESSA AULA
Apresentar uma técnica simples de utilização da intensidade de um sinal recebido de um rádio LoRa, para efetuar sua localização.
MATERIAIS UTILIZADOS
- 3x DevKits Heltec WiFi LoRa 32.
- 4x baterias de lítio 3,7V.
- Suportes de baterias de lítio 3,7V.
- 1x step-up.
- 1x step-down
- 1 Drone (opcional)
PRINCÍPIO DE FUNCIONAMENTO
Nesta aplicação, vamos utilizar um modo intuitivo de localização simplesmente como um experimento. Existem técnicas mais precisas e mais eficientes. Mas esta requer uma quantidade pequena de recursos e pode ser aplicada em outras situações também. Para isso, vamos supor que temos um alvo a ser localizado, que chamaremos de LOST.
Esse por sua vez, emite continuamente um sinal LoRa, com características conhecidas. Uma base para a operação de localização, que chamaremos de STATION, utilizará um receptor móvel para identificar a posição mais provável de LOST.
Este receptor móvel será transportado , no nosso caso, por um drone, por isso vamos chama-lo DRONE. Mas seria possível realizar a mesma operação sem necessariamente um drone. Com o drone temos a possibilidade de reduzir o número de obstáculos e sua interferência.
PRINCIPIO DE FUNCIONAMENTO - MONTAGEM LOST
Para a montagem do LOST, vamos utilizar um suporte de baterias para duas ou mais baterias de lítio. Apesar de sua tensão nominal ser de 3,7V, na prática podem atingir 4,2V. Com duas em série teremos uma tensão de 8,4V que deverá ser aplicada ao step-down. O módulo step-down ficará responsável por manter a tensão regulada em 5V. A tensão de 5V pode ser aplicada a entrada 5V do Heltec WiFi LoRa 32.
Atenção para a versão do DevKit Heltec, atualmente é possível encontrar as versões 1.0, 2.0 e 2.1. Alguns de seu pinos não coincidem.
PRINCÍPIO DE FUNCIONAMENTO – Pinout WiFi LoRa 32
Abaixo vemos algumas das diferenças nas versões dos devkits 1.0 e 2.x.
Aqui, em detalhe as diferentes distribuições dos pinos para cada versão.
As mudanças estão destacadas em quadros de mesma cor.
Entre as versões 2.0 e 2.1 não há diferenças de pinos que interessem este experimento
PRINCIPIO DE FUNCIONAMENTO – Montagem DRONE
Para a montagem do DRONE, vamos utilizar uma única bateria, ligada a um step-up, que elevará a tensão até os 5V necessários para a alimentação do devkit.
Além disso, o conjunto será fixado em uma peça impressa em 3d para ser transportado.
PRINCIPIO DE FUNCIONAMENTO – Montagem STATION
Já a STATION pode ser alimentada por um PC ou uma fonte, como as de celulares, já que ficará fixa.
PRINCÍPIO DE FUNCIONAMENTO
A informação mais relevante obtida pelo DRONE para o processo de localização de LOST é na verdade o RSSI.
Nosso utilizaremos para determinar o quão próximos estaremos de LOST.
Mas para isso, devemos proceder de forma organizada para que o RSSI seja mais que uma simples informação de proximidade e nos permita inferir a posição possível de LOST.
Vejamos a situação exposta no esquema a seguir . . .
Não sabemos onde LOST está, então começamos escolhendo uma direção para iniciar a busca. Vamos escolher a direção NORTE-SUL inicialmente.
Ao mover, vamos observando o RSSI obtido pelo DRONE:
Se o valor do RSSI diminui, estamos indo no sentido errado (estamos nos afastando).
Se o valor do RSSI aumenta, estamos indo no sentido correto (estamos nos aproximando).
Mantendo a direção e o sentido de aumento do RSSI, estaremos nos aproximando de LOST. Mas isso não ocorrerá indefinidamente, porque atingiremos uma distância mínima de LOST e começaremos a nos afastar.
A posição sobre esta reta de direção onde o RSSI é máximo, indicará o ponto em que estivemos mais próximos de LOST e é este ponto que interessa.
Embora somente com este ponto não possamos localizar de fato LOST, ele fornecerá uma informação importante. A reta dos possíveis locais onde LOST pode estar.
Observe na figura de exemplo:
Isso significa que LOST deve estar em algum lugar sobre a reta indicada na figura já que a menor distância entre LOST e DRONE é uma reta entre eles.
O passo seguinte é determinar em que ponto sobre esta reta LOST possivelmente estará.
Para isso, trazemos DRONE de volta a STATION e repetimos o processo, mas desta vez, em uma direção perpendicular a anterior. No nosso exemplo, na direção LESTE-OESTE.
No exemplo acima, temos um ponto sobre a direção LESTE-OESTE onde o valor de RSSI atinge um máximo. A posição provável de LOST deve ser algum ponto sobre a nova reta indicada.
As duas retas mostram posições prováveis para LOST onde RSSI tem o maior valore e possivelmente está mais próximo de DRONE.
Com as duas informações podemos estimar a provável posição de LOST.
Podemos agora limitar a região de busca para as regiões mais prováveis (em verde).
CapturasSinais LoRa capturados com SDR.
Abaixo vemos a captura dos sinais LoRa transmitidos por LOST, seguidos da transmissão de DRONE para STATION.
A sequência de eventos pode ser observada com mais detalhes na figura ao lado.
Note que os eventos mais antigos estão mais abaixo, enquanto que os mais recentes estão mais acima.
Problemas com o processo
É bastante claro que, o que foi exposto até aqui, é uma simplificação e deixa de lado vários fatores que podem comprometer a capacidade de localização de LOST;
A altitude de DRONE e de LOST devem ser levadas em consideração;
A possibilidade de obstáculos interferirem e/ou refletirem os sinais emitidos por LOST podem complicar a sua localização;
O direcionamento relativo das antenas pode interferir no valor do RSSI obtido por DRONE.
Entre outros . . .
Mas são problemas solucionáveis e a combinação com outras técnicas pode sim, tornar esta, uma habilidade interessante com rádios LoRa e/ou outros.
Códigos-fonte (LOST, DRONE e STATION)LOST – Declarações e setup()
//COM15 #include <heltec.h> //Frequência #define BAND 433E6 //Contador de envios unsigned int count = 0; void setup() { //Inicia os dispositivos Heltec.begin(true /*Ativa o display*/, true /*Ativa lora*/, true /*Ativa informações pela serial*/, true /*Ativa PABOOST*/, BAND /*frequência*/); //Ajusta o Spreading Factor LoRa.setSpreadingFactor(12); //Ajusta a largura de banda LoRa.setSignalBandwidth(250E3); //Inicializa o display setupDisplay(); }
LOST – setupDisplay()
void setupDisplay() { //Inicializa o display Heltec.display->init(); //Limpa o display Heltec.display->clear(); //Modifica direcionamento do texto Heltec.display->flipScreenVertically(); //Alinha o texto à esquerda Heltec.display->setTextAlignment(TEXT_ALIGN_CENTER); //Altera a fonte Heltec.display->setFont(ArialMT_Plain_24); //Exibe no display Heltec.display->drawString(60, 0, "Display OK"); Heltec.display->drawString(60, 30, "LOST"); Heltec.display->display(); delay(1000); }
LOST – refreshDisplay() e sendLoRaPacket()
void refreshDisplay(String displayMessage) { //Limpa o display Heltec.display->clear(); //Exibe a mensagem Heltec.display->drawString(60, 0, "Enviados: "); Heltec.display->drawString(60, 30, displayMessage); Heltec.display->display(); } //Envia um pacote LoRa void sendLoRaPacket(String str) { //Inicializa o pacote LoRa.beginPacket(); //Coloca a string no pacote LoRa.print(str); //Finaliza e envia o pacote LoRa.endPacket(); }
LOST – loop()
void loop() { //Cria uma mensagem e aumenta o contador String message = String(count++); //Envia o pacote sendLoRaPacket(message); //Exibe a mensagem no display refreshDisplay(message); //Espera 1 segundo delay(1000); }
DRONEDRONE – Declarações e setup()
//COM4 #include <heltec.h> //Frequência #define BAND 433E6 //Simbolo de sinal de entrada const String SINAL_ENTRADA = " <<<" //Contador de envios unsigned int count = 0; //Valor do RSSI String RSSI_atual = ""; void setup() { Heltec.begin(true /*Ativa o display*/, true /*Ativa lora*/, true /*Ativa informações pela serial*/, true /*Ativa PABOOST*/, BAND /*frequência*/); //Ajusta o Spreading Factor LoRa.setSpreadingFactor(12); //Ajusta a largura de banda LoRa.setSignalBandwidth(250E3); //Inicializa o display setupDisplay(); //Ativa o recebimento de pacotes LoRa.receive(); }
DRONE – setupDisplay()
void setupDisplay() { //Inicializa o display Heltec.display->init(); //Limpa o display Heltec.display->clear(); //Modifica direcionamento do texto Heltec.display->flipScreenVertically(); //Alinha o texto à esquerda Heltec.display->setTextAlignment(TEXT_ALIGN_LEFT); //Altera a fonte Heltec.display->setFont(ArialMT_Plain_16); //Exibe no display Heltec.display->drawString(0, 0, "Display OK"); Heltec.display->drawString(0, 16, "DRONE"); Heltec.display->display(); delay(1000); }
DRONE – refreshDisplay() e sendLoRaPacket()
void refreshDisplay() { //Limpa o display Heltec.display->clear(); //Exibe a mensagem Heltec.display->drawString(0, 0, "RSSI: " + RSSI_atual); Heltec.display->drawString(0, 16, "T. exec: " + String(millis() / 1000) + "s"); Heltec.display->drawString(0, 32, "Enviados: " + String(count)); Heltec.display->display(); } //Envia um pacote LoRa void sendLoRaPacket(String str) { //Inicializa o pacote LoRa.beginPacket(); //Coloca a string no pacote LoRa.print(str); //Finaliza e envia o pacote LoRa.endPacket(); //atualiza contagem de mensagens count++; }
DRONE – loop() e cbk()
void loop() { int packetSize = LoRa.parsePacket(); //Obtém o tamanho do pacote if (packetSize) //se for diferente de 0, recebemos dados . . . { cbk(); //executa o callback de recebimento refreshDisplay(); //Atualiza o display com o novo RSSI RSSI_atual.replace(SINAL_ENTRADA, ""); //remove o simbolo de sinal de entrada delay(200); //aguarda um pouco sendLoRaPacket("d:" + RSSI_atual); //Envia o RSSI obtido para STATION } else //se nenhum dado foi recebido... { refreshDisplay();//somente atualiza o display } } void cbk() { //Obtem o RSSI e inclui o sinal de entrada RSSI_atual = String(LoRa.packetRssi(), DEC) + SINAL_ENTRADA; }
STATIONSTATION – Declarações e setup()
//COM8 #include <heltec.h> //Frequência #define BAND 433E6 //Simbolo de sinal de entrada const String SINAL_ENTRADA = " <<<"; //Valor do RSSI enviado pelo DRONE String mensagem = ""; //Contador de recebimentos unsigned int count = 0; void setup() { Heltec.begin(true /*Ativa o display*/, true /*Ativa lora*/, true /*Ativa informações pela serial*/, true /*Ativa PABOOST*/, BAND /*frequência*/); //Ajusta o Spreading Factor LoRa.setSpreadingFactor(12); //Ajusta a largura de banda LoRa.setSignalBandwidth(250E3); //Inicializa o display setupDisplay(); //Ativa o recebimento de pacotes LoRa.receive(); }
STATION – setupDisplay()
void setupDisplay() { //Inicializa o display Heltec.display->init(); //Limpa o display Heltec.display->clear(); //Modifica direcionamento do texto Heltec.display->flipScreenVertically(); //Alinha o texto à esquerda Heltec.display->setTextAlignment(TEXT_ALIGN_LEFT); //Altera a fonte Heltec.display->setFont(ArialMT_Plain_16); //Exibe no display Heltec.display->drawString(0, 0, "Display OK"); Heltec.display->drawString(0, 16, "STATION"); Heltec.display->display(); delay(1000); }
STATION – refreshDisplay()
void refreshDisplay() { //Limpa o display Heltec.display->clear(); //Exibe a mensagem Heltec.display->drawString(0, 0, "RSSI: " + mensagem); Heltec.display->drawString(0, 16, "T. exec: " + String(millis() / 1000) + "s"); Heltec.display->drawString(0, 32, "Recebidos: " + String(count)); Heltec.display->display();}
STATION – cbk()
void cbk(int packetSize) { mensagem = ""; for (int i = 0; i < packetSize; i++) { mensagem += (char) LoRa.read(); } //O drone está nos enviando mensagens assim: "from_drone: RSSI" //onde "RSSI" é o RSSI dos pacotes que ele está pegando if (mensagem.startsWith("d:")) { count++; //Remove "d:" de "from_drone:" da string mensagem.replace("d:", ""); //Remove eventuais espaços em branco nas extremidades da string mensagem.trim(); //Exibe no Monitor Serial Serial.println(mensagem); //inclui o sinal de entrada mensagem = mensagem + SINAL_ENTRADA; //Exibe no display refreshDisplay(); } else { //indica a detecção de um sinal do "LOST" mensagem = "LOST"; //Exibe no display refreshDisplay(); }}
STATION – loop()
void loop() { //verifica se há dados int packetSize = LoRa.parsePacket(); //se há, inicia a leitura if (packetSize) { cbk(packetSize); } }
0 Comentários