ESP32 With External Long Distance Antenna

by Fernando Koyanagi in Circuits > Microcontrollers

24113 Views, 6 Favorites, 0 Comments

ESP32 With External Long Distance Antenna

ESP32 com Antena Externa Longa Distância
1.png

Today’s topic concerns a distance test with an ESP32 with External Antenna. Let's use two modules today: from Espressif and TTGO. Let's then check the RSSI between these two ESP32 antennas, generate a graph from the history, and write a log of the values in a .csv file.

We then have the ESP32 Wrover as AP, and the ESP32 of TTGO as Station. I used an antenna that I took from a slightly larger TP-Link and another router known as a 9dbm antenna. I haven’t noticed any difference between the two.

Finally, the two microcontrollers connect via socket and, with each sending of data packets, we print on a display a graph with the bars that indicate the ratio of dbm.

Mounting the AP With Wrover

3.png

Assembly of STATION With TTGO

4.png

RESULT

5.1.png
5.2.png
5.png

Maximum distance with 2x external antennas: 315 meters

Maximum distance with external and internal antenna: 157 meters

Archive LOG.CSV

6.1.png
6.2.png

I recorded the data on an SD card, with data in millis, dbm, and the package string.

Adafruit GFX Library

10.png

In the Arduino IDE, go to Sketch-> Include Library-> Manage Libraries...

Install Adafruit GFX Library

Adafruit ST7735 Library

11.png

In the Arduino IDE, go to Sketch-> Include Library-> Manage Libraries...

Install Adafruit ST7735

Configuring the Cards

12.1.png
12.png

Stay tuned for differences:

AP.ino

We have included the necessary libraries and defined some parameters.

#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"

We define the pins, among other variables

//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 and 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 and 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

We have included the necessary libraries and defined some parameters.

#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"

We define the settings that involve the display and the 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::vector rssiHistory;

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 and 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 and 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(); }

Files

Download the files:

PDF

INO