Um teste de distância com um
ESP32 com Antena Externa. Vamos utilizar hoje dois módulos: um da Espressif e
um da TTGO. Vamos, então, verificar o RSSI entre esses dois ESP32 com antenas,
gerar um gráfico a partir do histórico e gravar um log dos valores em um
arquivo .csv.
Temos, então, o ESP32 Wrover
como AP e o ESP32 da TTGO como Station. Utilizei uma antena que tirei de um
roteador TP-Link e outra, um pouco maior, conhecida como antena de 9dbm. Não
percebemos diferença nenhuma entre as duas.
Enfim, os dois
microcontroladores se conectam via socket e, a cada envio de pacote de dados,
imprimimos em um display um gráfico com as barras que indicam a proporção de dbm.
Montagem do AP com o Wrover
Montagem do STATION com o TTGO
RESULTADO
Distância máxima com 2x
antenas externas: 315 metros
Distância máxima com antena externa
e outra interna: 157 metros
Arquivo LOG.CSV
Gravei os dados em um cartão
do SD, com dados em milis, dbm e a string do pacote.
Biblioteca Adafruit GFX
Na IDE do Arduino vá em
Sketch->Incluir Biblioteca->Gerenciar Bibliotecas...
Instale Adafruit GFX Library
Biblioteca Adafruit ST7735
Na IDE do Arduino vá em
Sketch->Incluir Biblioteca->Gerenciar Bibliotecas...
Instale Adafruit ST7735
Configurando as placas
Fique atento às diferenças:
AP.ino
Incluímos as bibliotecas
necessárias e definimos alguns parâmetros.
#include <WiFi.h> #include <Adafruit_GFX.h> #include <Adafruit_ST7735.h> #include <SPI.h> #include <vector> #include <SD.h> //Rede que o ESP criará. No Station deve ser igual #define SSID "RSSI_Test" #define PASSWORD "87654321" //Tempo de timeout para considerar a conexão pedida #define TIMEOUT 2000 //Largura e altura do display #define DISPLAY_WIDTH 160 #define DISPLAY_HEIGHT 128 //Configurações de cor, margem e tamanho do gráfico #define PLOT_COLOR ST77XX_GREEN #define PLOT_MARGIN 20 #define PLOT_SIZE (DISPLAY_HEIGHT - 2*PLOT_MARGIN) //Arquivo de log no SD #define FILE_PATH "/log.csv"
Definimos os pinos, entre outras variáveis
//Pinos do display #define DISPLAY_DC 12 //A0 #define DISPLAY_CS 13 //CS #define DISPLAY_MOSI 14 //SDA #define DISPLAY_CLK 27 //SCK #define DISPLAY_RST 0 //Pino do SDCard. Os pinos mosi, miso e sck são os nativos (23, 19 e 18 respectivamente) #define SDCARD_CS 15 //Pixel onde o gráfico começa horizontalmente int currentX = PLOT_MARGIN; //Objeto responsável pelo display Adafruit_ST7735 display = Adafruit_ST7735(DISPLAY_CS, DISPLAY_DC, DISPLAY_MOSI, DISPLAY_CLK, DISPLAY_RST); //Criamos um server (qualquer porta válida serve contanto que o cliente utilize a mesma porta) WiFiServer server(80); //Variável para armazenar o cliente (no caso o ESP32 em modo station) conectado WiFiClient client; //String que recebemos do cliente String received; //RSSI enviado pelo cliente para este ESP32 long rssi = 0; //Faz o controle do temporizador (interrupção por tempo) hw_timer_t *timer = NULL; //Utilizado para guardar os ultimos std::vector<int> rssiHistory;
Setup
void setup()
{
Serial.begin(115200);
setupDisplay();
//Inicializa o SD
if (!SD.begin(SDCARD_CS))
{
display.println("Erro ao inicializar lib SD!");
}
//Cria a rede WiFi, inicializa o server e espera o cliente conectar
setupWiFi();
server.begin();
waitForClient();
//Espera 3 segundos, limpa a tela e inicializa o Watchdog
delay(3000);
display.fillScreen(ST77XX_BLACK);
display.setCursor(0, 0);
setupWatchdog();
}
Setup WiFi
//Cria um Access Point e configura o IP
void setupWiFi()
{
display.println("Creating softAP " + String(SSID));
WiFi.disconnect();
WiFi.mode(WIFI_AP);
WiFi.softAPConfig(IPAddress(192, 168, 0, 1), IPAddress(192, 168, 0, 1), IPAddress(255, 255, 255, 0));
WiFi.softAP(SSID, PASSWORD);
display.println("softAP " + String(SSID) + " created!");
}
Setup Display
//Incializa o display, muda a orientação e limpa a tela
void setupDisplay()
{
//Inicializa o display
display.initR(INITR_BLACKTAB);
//Rotaciona o conteúdo mostrado
display.setRotation(3);
//Pinta a tela de preto
display.fillScreen(ST77XX_BLACK);
}
waitForClient
void waitForClient()
{
display.println("Waiting for client");
//Aguarda o cliente conectar
while(!(client = server.available()))
{
display.print(".");
delay(500);
}
display.println("Client connected");
//Tempo máximo que o cliente deve demorar para responder
//antes de dizermos que a conexão foi perdida
client.setTimeout(TIMEOUT);
}
IRAM_ATTR resetModule e setupWatchdog
//função que o temporizador irá chamar, para reiniciar o ESP32
void IRAM_ATTR resetModule(){
ets_printf("(watchdog) reiniciar\n");
esp_restart_noos(); //reinicia o chip
}
void setupWatchdog()
{
timer = timerBegin(0, 80, true); //timerID 0, div 80
//timer, callback, interrupção de borda
timerAttachInterrupt(timer, &resetModule, true);
//timer, tempo (us), repetição
timerAlarmWrite(timer, 10000000, true);
timerAlarmEnable(timer); //habilita a interrupção
}
Loop
void loop()
{
timerWrite(timer, 0); //reseta o temporizador (alimenta o watchdog)
checkConnection(); //checa se possui conexão com o cliente
readFromClient(); //lê os dados do cliente
sendToClient(); //envia confirmação para o cliente
plot(); //mostra o gráfico de histórico de rssi
log(); //salva um log no cartão SD
}
checkConnection
void checkConnection()
{
//Se o cliente não estiver conectado
if(!client.connected())
{
//Limpa a tela e espera pelo cliente
display.fillScreen(ST77XX_BLACK);
display.println("Client disconnected");
waitForClient();
}
}
readFromClient
void readFromClient()
{
//Espera até o cliente enviar algo ou desconectar
while(client.connected() && !client.available())
{
delay(100);
}
//Se chegou aqui e ainda estiver conectado é porque possui algo para receber do cliente
if(client.connected())
{
received = client.readStringUntil('\n'); //Lê o texto que o cliente enviou
received.remove(received.length()-1); //Remove o \n do final
rssi = client.parseInt(); //Lê o rssi que o cliente enviou
clearText(); //Limpa o texto
display.setCursor(0, 0); //Move o cursor do texto para o começo do display
display.println("RSSI: " + String(rssi)); //Mostra o RSSI no display
display.println("Received: " + received); //Mostra a mensagem recebida do cliente
//Se a quantidade de barras do gráfico passou do limite apagamos o registro mais antigo
if(rssiHistory.size() == (DISPLAY_WIDTH - 2*PLOT_MARGIN)/2)
{
rssiHistory.erase(rssiHistory.begin());
}
//Adiciona no final do histórico (mais recente)
rssiHistory.push_back(rssi);
}
}
sendToClient
void sendToClient()
{
//Se o cliente estiver conectado enviamos de volta a mensagem com um OK
if(client.connected())
{
String sending = received + " OK";
client.println(sending);
}
}
plot
void plot()
{
//Coloca no ponto inicial e limpamos o gráfico
currentX = PLOT_MARGIN;
display.fillRect(PLOT_MARGIN, 2*PLOT_MARGIN, DISPLAY_WIDTH - 2*PLOT_MARGIN, DISPLAY_HEIGHT - 2*PLOT_MARGIN, ST77XX_BLACK);
//Para cada valor do histórico fazemos o cálculo do tamanho da barra do gráfico, desenhamos e avançamos para o próximo
for (int i = 0; i < rssiHistory.size(); i++)
{
int value = rssiHistory[i] > -120 ? map(rssiHistory[i], -120, 0, 0, PLOT_SIZE) : 0;
display.drawFastVLine(currentX, DISPLAY_HEIGHT - value, value, PLOT_COLOR);
currentX += 2;
}
}
clearText e log
void clearText()
{
//Limpa a área com o texto da mensagem vinda do cliente
display.fillRect(0, 0, DISPLAY_WIDTH, 2*PLOT_MARGIN, ST77XX_BLACK);
}
void log()
{
//Abrimos o arquivo para escrevermos no final dele
File file = SD.open(FILE_PATH, FILE_APPEND);
//Se não conseguimos abrir o arquivo mostramos uma mensagem de erro
if(!file)
{
Serial.println("Failed to open file");
return;
}
//Gravamos uma linha com o tempo desde o boot, o rssi atual e a mensagem recebida
String data = String(millis()) + ";" + String(rssi) + ";" + received;
file.println(data);
file.close();
}
Station.ino
Incluímos as bibliotecas
necessárias e definimos alguns parâmetros.
#include <WiFi.h> #include <Adafruit_GFX.h> #include <Adafruit_ST7735.h> #include <SPI.h> #include <vector> #include <SD.h> //Nome da rede que nos conectaremos. Criado pelo AP #define SSID "RSSI_Test" #define PASSWORD "87654321" #define HOST "192.168.0.1" //IP que foi configurado no setup do AP #define PORT 80 //Porta do sever. Qualquer porta válida contanto que seja igual nos dois arquivos //Tempo de timeout para considerar a conexão pedida #define TIMEOUT 2000 //Largura e altura do display #define DISPLAY_WIDTH 160 #define DISPLAY_HEIGHT 128 //Configurações de cor, margem e tamanho do gráfico #define PLOT_COLOR ST77XX_GREEN #define PLOT_MARGIN 20 #define PLOT_SIZE (DISPLAY_HEIGHT - 2*PLOT_MARGIN) //Arquivo de log no SD #define FILE_PATH "/log.csv"
Definimos as configurações que
envolvem o display e o SD Card.
long count = 0; //Contador de mensagens enviadas long rssi = 0; //RSSI calculado String received; //Mensagem de confirmação que o AP nos envia //Pixel onde o gráfico começa horizontalmente int currentX = PLOT_MARGIN; //Utilizado para conexão com o server WiFiClient socket; #define DISPLAY_DC 12 //A0 #define DISPLAY_CS 13 //CS #define DISPLAY_MOSI 14 //SDA #define DISPLAY_CLK 27 //SCK #define DISPLAY_RST 0 //Pino do SDCard. Os pinos mosi, miso e sck são os nativos (23, 19 e 18 respectivamente) #define SDCARD_CS 15 //Objeto responsável pelo display Adafruit_ST7735 display = Adafruit_ST7735(DISPLAY_CS, DISPLAY_DC, DISPLAY_MOSI, DISPLAY_CLK, DISPLAY_RST); hw_timer_t *timer = NULL; //faz o controle do temporizador (interrupção por tempo) //Utilizado para guardar os ultimos std::vectorrssiHistory;
Setup
void setup()
{
setupDisplay();
//Inicializa o SD
if (!SD.begin(SDCARD_CS))
{
display.println("Erro ao inicializar lib SD!");
}
//Conecta no access point criado pelo outro ESP32 e conecta ao server
setupWiFi();
connectToServer();
//Espera 3 segundos, limpa a tela e inicializa o Watchdog
delay(3000);
display.fillScreen(ST77XX_BLACK);
display.setCursor(0, 0);
setupWatchdog();
}
setupDisplay
//Incializa o display, muda a orientação e limpa a tela
void setupDisplay()
{
//Inicializa o display
display.initR(INITR_BLACKTAB);
//Rotaciona o conteúdo mostrado
display.setRotation(1);
//Pinta a tela de branco
display.fillScreen(ST77XX_BLACK);
display.setTextColor(ST77XX_WHITE);
}
setupWiFi
//Conecta ao AP
void setupWiFi()
{
WiFi.disconnect();
WiFi.mode(WIFI_STA);
WiFi.begin(SSID, PASSWORD);
display.println("Connecting to " + String(SSID));
//Enquanto não estiver conectado à rede WiFi
while (WiFi.status() != WL_CONNECTED) {
delay(500);
display.print(".");
}
display.println("");
display.print("Connected to ");
display.println(SSID);
}
connectToServer
void connectToServer()
{
display.println("Trying socket connection");
//Espera a conexão com o server
while(!socket.connect(HOST, PORT))
{
display.print(".");
delay(500);
}
display.println();
display.println("Connected!");
//Tempo máximo que o cliente deve demorar para responder
//antes de dizermos que a conexão foi perdida
socket.setTimeout(TIMEOUT);
}
IRAM_ATTR resetModule e setupWatchdog
//função que o temporizador irá chamar, para reiniciar o ESP32
void IRAM_ATTR resetModule(){
ets_printf("(watchdog) reiniciar\n");
esp_restart_noos(); //reinicia o chip
}
void setupWatchdog()
{
timer = timerBegin(0, 80, true); //timerID 0, div 80
//timer, callback, interrupção de borda
timerAttachInterrupt(timer, &resetModule, true);
//timer, tempo (us), repetição
timerAlarmWrite(timer, 10000000, true);
timerAlarmEnable(timer); //habilita a interrupção
}
loop
void loop()
{
timerWrite(timer, 0); //reseta o temporizador (alimenta o watchdog)
checkConnection(); //checa se possui conexão com o server
checkRSSI(); //verifica o rssi
plot(); //mostra o gráfico de histórico de rssi
sendToServer(); //envia uma mensagem com um contador para o server
readFromServer(); //espera a confirmação do server
log(); //salva um log no cartão SD
delay(1000); //espera um segundo
}
checkConnection
void checkConnection()
{
//Verifica a conexão com o AP
if(WiFi.status() != WL_CONNECTED)
{
display.fillScreen(ST77XX_BLACK);
display.setCursor(0, 0);
display.println("WiFi disconnected");
setupWiFi();
delay(1000);
}
//verifica a conexão do socket
if(!socket.connected())
{
display.fillScreen(ST77XX_BLACK);
display.setCursor(0, 0);
display.println("Socket disconnected");
connectToServer();
delay(3000);
display.fillScreen(ST77XX_BLACK);
}
}
checkRSSI
void checkRSSI()
{
//Verifica o RSSI
rssi = WiFi.RSSI();
//Limpa o texto e mostra o RSSI no display
clearText();
display.setCursor(0, 0);
display.print("RSSI: " + String(rssi));
//Se a quantidade de barras do gráfico passou do limite apagamos o registro mais antigo
if(rssiHistory.size() == (DISPLAY_WIDTH - 2*PLOT_MARGIN)/2)
{
rssiHistory.erase(rssiHistory.begin());
}
//Adiciona no final do histórico (mais recente)
rssiHistory.push_back(rssi);
}
plot
void plot()
{
//Coloca no ponto inicial e limpamos o gráfico
currentX = PLOT_MARGIN;
display.fillRect(PLOT_MARGIN, 2*PLOT_MARGIN, DISPLAY_WIDTH - 2*PLOT_MARGIN, DISPLAY_HEIGHT - 2*PLOT_MARGIN, ST77XX_BLACK);
//Para cada valor do histórico fazemos o cálculo do tamanho da barra do gráfico, desenhamos e avançamos para o próximo
for (int i = 0; i < rssiHistory.size(); i++)
{
int value = rssiHistory[i] > -120 ? map(rssiHistory[i], -120, 0, 0, PLOT_SIZE) : 0;
display.drawFastVLine(currentX, DISPLAY_HEIGHT - value, value, PLOT_COLOR);
currentX += 2;
}
}
sendToServer
void sendToServer()
{
//Se estiver conectado com o server
if(socket.connected())
{
//Envia um hello com um contador, mostra no display e incrementa o contador
String sending = "Hello " + String(count);
display.setCursor(0, 10);
display.println("Sending: " + sending);
socket.println(sending);
socket.print(String(rssi));
count++;
}
}
readFromServer
void readFromServer()
{
//Espera até o server enviar algo ou desconectar
while(socket.connected() && !socket.available())
{
delay(100);
}
//Se tem algo para receber
if(socket.available())
{
//Faz a leitura, remove o \n do final e mostra no display
received = socket.readStringUntil('\n');
received.remove(received.length()-1);
display.println("Received: " + received);
}
}
clearText e log
void clearText()
{
//Limpa a área com o texto da mensagem vinda do cliente
display.fillRect(0, 0, DISPLAY_WIDTH, 2*PLOT_MARGIN, ST77XX_BLACK);
}
void log()
{
//Abrimos o arquivo para escrevermos no final dele
File file = SD.open(FILE_PATH, FILE_APPEND);
//Se não conseguimos abrir o arquivo mostramos uma mensagem de erro
if(!file)
{
Serial.println("Failed to open file");
return;
}
//Gravamos uma linha com o tempo desde o boot, o rssi atual e a mensagem recebida
String data = String(millis()) + ";" + String(rssi) + ";" + received;
file.println(data);
file.close();
}
Faça o download dos arquivos:













2 Comentários
excelente tutorial , obrigado vai ser de muito uso para mim.
ResponderExcluirgostaria de outros testes com antena externa melhor .
Parabens
Esqueci d ebotar meu nome
ResponderExcluirexcelente tutorial , obrigado vai ser de muito uso para mim.
gostaria de outros testes com antena externa melhor .
Parabens