Spisu treści:
2025 Autor: John Day | [email protected]. Ostatnio zmodyfikowany: 2025-01-13 06:58
Dzisiejszy temat dotyczy testu odległości z ESP32 z anteną zewnętrzną. Wykorzystajmy dziś dwa moduły: od Espressif i TTGO. Sprawdźmy teraz RSSI pomiędzy tymi dwoma antenami ESP32, wygenerujmy wykres z historii i zapiszmy log wartości w pliku.csv.
Następnie mamy ESP32 Wrover jako AP, a ESP32 TTGO jako stację. Użyłem anteny, którą wziąłem z nieco większego TP-Linka i innego routera znanego jako antena 9dbm. Nie zauważyłem żadnej różnicy między nimi.
Na koniec oba mikrokontrolery łączą się przez gniazdo i przy każdym wysyłaniu pakietów danych drukujemy na wyświetlaczu wykres z paskami wskazującymi stosunek dbm.
Krok 1: Montaż AP za pomocą Wrover
Krok 2: Montaż STACJI z TTGO
Krok 3: WYNIK
Maksymalna odległość z 2x antenami zewnętrznymi: 315 metrów
Maksymalna odległość z anteną zewnętrzną i wewnętrzną: 157 metrów
Krok 4: Archiwizuj LOG. CSV
Zarejestrowałem dane na karcie SD, z danymi w milis, dbm i ciągiem paczki.
Krok 5: Biblioteka Adafruit GFX
W Arduino IDE przejdź do Szkic-> Dołącz bibliotekę-> Zarządzaj bibliotekami…
Zainstaluj bibliotekę Adafruit GFX
Krok 6: Biblioteka Adafruit ST7735
W Arduino IDE przejdź do Szkic-> Dołącz bibliotekę-> Zarządzaj bibliotekami…
Zainstaluj Adafruit ST7735
Krok 7: Konfiguracja kart
Bądź na bieżąco z różnicami:
Krok 8: AP.ino
Zawarliśmy niezbędne biblioteki i zdefiniowaliśmy niektóre parametry.
#include #include #include #include #include #include //Ponownie wezwać ESP. No Station deve ser igual #define SSID "RSSI_Test" #define PASSWORD "87654321" //Czas oczekiwania na rozważenie połączenia #define TIMEOUT 2000 //Largura i altura do display #define DISPLAY_WIDTH 160 #define DISPLAY_HEIGHT 128 //Konfiguracjaõ 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"
Piny definiujemy m.in
//Piny wyświetlają#definiują DISPLAY_DC 12 //A0 #definiują DISPLAY_CS 13 //CS #definiują DISPLAY_MOSI 14 //SDA #definiują DISPLAY_CLK 27 //SCK #definiują DISPLAY_RST 0 //Pino do karty SD. Os pinos mosi, miso e sck são os nativos (23, 19 i 18 odpowiednio) #define SDCARD_CS 15 //Pixel onde o grafá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 serwuj contanto que o cliente use a mesma porta) serwer WiFiServer(80); //Variável para armazenar lub cliente (bez przypadku lub ESP32 w modowej stacji) połącz się z klientem WiFiClient; //String que recebemos do cliente String odebrany; //RSSI zaprasza do pełnej obsługi klientów ESP32 long rssi = 0; //Faz o controle do temporizador (przerwanie przez tempo) hw_timer_t *timer = NULL; //Użyj do pilnowania ultimos std::vector rssiHistory;
Ustawiać
void setup(){ Serial.begin(115200); konfiguracjaWyświetlacz(); //Zainicjuj SD if (!SD.begin(SDCARD_CS)) { display.println("Błąd zainicjowania biblioteki SD!"); } //Uruchom ponownie WiFi, zainicjuj serwer i połącz się z klientem setupWiFi(); serwer.początek(); czekaćNaKlienta(); //Espera 3 segundos, limpa a tela e inicializa o Watchdog delay(3000); display.fillScreen(ST77XX_BLACK); display.setCursor(0, 0); setupWatchdog(); }
Skonfiguruj Wi-Fi
//Cria um Access Point i konfiguracja IPvoid setupWiFi() { display.println("Tworzenie softAP" + String(SSID)); Wi-Fi.rozłącz(); tryb WiFi (WIFI_AP); WiFi.softAPConfig(IPAddress(192,168,0,1),IPAddress(192,168,0,1),IPAddress(255,255,255,0)); WiFi.softAP (SSID, HASŁO); display.println("softAP" + String(SSID) + "utworzono!"); }
Wyświetlacz konfiguracji
//Zainicjuj wyświetlanie, ustawiaj orientację i ślimuj się w telavoid setupDisplay() { //Zainicjuj wyświetlanie display.initR(INITR_BLACKTAB); //Obrót o conteúdo mostrado display.setRotation(3); //Wyślij tę wiadomość display.fillScreen(ST77XX_BLACK); }
czekaj na klienta
void waitForClient(){ display.println("Oczekiwanie na klienta"); //Ostrzegaj o połączeniu klienta while(!(klient = server.available())) { display.print("."); opóźnienie (500); } display.println("Klient podłączony"); //Maksymalny czas, w którym klient buduje postrach dla osoby odpowiadającej //czas oczekiwania w związku z nieustannym połączeniem client.setTimeout(TIMEOUT); }
IRAM_ATTR resetModuł i setupWatchdog
//função que o temporizador irá chamar, dla ponownego uruchomienia ESP32void IRAM_ATTR resetModule(){ ets_printf("(watchdog) ponowne uruchomienie\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), powtórzenie timerAlarmWrite(timer, 10000000, true); timerAlarmEnable(timer); //habilita a interrupção }
Pętla
void loop() { timerWrite(timer, 0); //resetuj o temporizador (alimenta o watchdog) checkConnection(); //Sprawdź, czy możesz połączyć się z klientem odczytajOdKlienta(); //le os dados do cliente sendToClient(); //envia Confirmação para o cliente działka(); //mostra o wykresie historycznym rssi log(); //salva um log no cartão SD }
Sprawdź połączenie
void checkConnection(){ //Nie można połączyć się z klientem if(!client.connected()) { //Pozwól, aby klient display.fillScreen(ST77XX_BLACK) był otwarty i zaawansowany; display.println("Klient odłączony"); czekaćNaKlienta(); } }
czytajOdKlienta
void readFromClient(){ //Proszę o kontakt z klientem lub o jego usunięcie while(client.connected() && !client.available()) { delay(100); } //Se chegou aqui e inda estiver conectado é porque possui algo para receber to cliente if(client.connected()) { receive = client.readStringUntil('\n'); //Lê o texto que o cliente enviou receive.remove(received.length()-1); //Usuń o \n wykonaj final rssi = client.parseInt(); //Lê or rssi que o cliente enviou clearText(); //Limpa o wyświetlanie tekstu.setCursor(0, 0); //Przesuń kursor, aby wyświetlić tekst para o começo wyświetlić display.println("RSSI: " + String(rssi)); //Mostra o RSSI brak wyświetlania display.println("Odebrane: " + odebrane); //Mostra a mensagem recebida do cliente //Se a quantidade de barras to grafico passou to limite apagamos o registro mais antigo if(rssiHistory.size() == (DISPLAY_WIDTH - 2*PLOT_MARGIN)/2) { rssiHistory.erase(rssiHistory.rozpocząć()); } //Adiciona no final do histórico (mais presente) rssiHistory.push_back(rssi); } }
sendToClient
void sendToClient(){ //Połącz projekt klienta z komunikatem z komunikatem OK if(client.connected()) { String wysyłanie = odebrano + " OK"; klient.println(wysyłanie); } }
wątek
void plot(){ //Koloka nie ma początkowego ponto e limpamos o graficznego 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 -120 ? map(rssiHistory, -120, 0, 0, PLOT_SIZE): 0; display.drawFastVLine(currentX, DISPLAY_HEIGHT - wartość, wartość, PLOT_COLOR); currentX += 2; } }
czysty tekst i log
void clearText(){ //Pomiń obszar z tekstem, aby wyświetlić komunikaty klientów display.fillRect(0, 0, DISPLAY_WIDTH, 2*PLOT_MARGIN, ST77XX_BLACK); } void log() { //Abrimos o arquivo para escrevermos no final dele Plik plik = SD.open(FILE_PATH, FILE_APPEND); //Se não conseguimos brir o arquivo mostramos uma mensagem de erro if(!file) { Serial.println("Nie udało się otworzyć pliku"); powrót; } //Gravamos uma linha com o tempo desde o boot, or rssi atual e a mensagem recebida String data = String(millis()) + ";" + Ciąg(rssi) + ";" + otrzymał; plik.println(dane); plik.zamknij(); }
Krok 9: Stacja.ino
Zawarliśmy niezbędne biblioteki i zdefiniowaliśmy niektóre parametry.
#include #include #include #include #include #include // Nome od rede que nos conectaremos. Criado pelo AP #define SSID "RSSI_Test" #define PASSWORD "87654321" #define HOST "192.168.0.1" //IP, które można skonfigurować bez konfiguracji dla AP #define PORT 80 //Porta do sever. Qualquer porta válida contanto que seja igual nos dois arquivos //Tempo de timeout dla rozważenia conexão pedida #define TIMEOUT 2000 //Largura e altura do display #define DISPLAY_WIDTH 160 #define DISPLAY_HEIGHT 128 //Konfiguracja dużych rozmiarów, #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"
Definiujemy ustawienia, które dotyczą wyświetlacza i karty SD.
długa liczba = 0; //Contador de mensagens enviadaslong rssi = 0; //Odebrano ciąg znaków RSSI; //Mensagem de Confirmação que o AP nos envia //Pixel onde o grafáfico começa horizontalmente int currentX = PLOT_MARGIN; //Utilizado para conexão com o serwer WiFiClient gniazdo; #define DISPLAY_DC 12 //A0 #define DISPLAY_CS 13 //CS #define DISPLAY_MOSI 14 //SDA #define DISPLAY_CLK 27 //SCK #define DISPLAY_RST 0 //Przypnij do karty SD. Liczba pinów mosi, miso i sck natywna (23, 19 i 18 odpowiednio) #define SDCARD_CS 15 //Objekt odpowiada na wyświetlanie Adafruit_ST7735 display = Adafruit_ST7735(DISPLAY_CS, DISPLAY_DC, DISPLAY_MOSI, DISPLAY_CLK, DISPLAY_RSRS); hw_timer_t *timer = NULL; //faz o controle do temporizador (interrupção por tempo) //Utilizado para guardar os ultimos std::vector rssiHistory;
Ustawiać
void setup(){ setupDisplay(); //Zainicjuj SD if (!SD.begin(SDCARD_CS)) { display.println("Błąd zainicjowania biblioteki SD!"); } //Połącz bez punktu dostępowego, poproś o wyjście z ESP32 i połącz się z konfiguracją serweraWiFi(); połączyć się z serwerem(); //Espera 3 segundos, limpa a tela e inicializa o Watchdog delay(3000); display.fillScreen(ST77XX_BLACK); display.setCursor(0, 0); setupWatchdog(); }
konfiguracjaWyświetlacz
//Zainicjuj wyświetlanie, ustawiaj orientację i ślimuj się w telavoid setupDisplay() { //Zainicjuj wyświetlanie display.initR(INITR_BLACKTAB); //Obrót o conteúdo mostrado display.setRotation(1); //Wybierz ekran display.fillScreen(ST77XX_BLACK); display.setTextColor(ST77XX_WHITE); }
konfiguracjaWiFi
//Połącz ao AP void setupWiFi() { WiFi.disconnect(); tryb WiFi (WIFI_STA); WiFi.begin(SSID, HASŁO); display.println("Łączenie z " + String(SSID)); //Enquanto não estiver conectado à rede WiFi while (WiFi.status() != WL_CONNECTED) { delay(500); display.print("."); } display.println(""); display.print("Połączony z"); display.println(SSID); }
połączyć się z serwerem
void connectToServer(){ display.println("Próbowanie połączenia z gniazdem"); //Obsługuj serwer conexão com o while(!socket.connect(HOST, PORT)) { display.print("."); opóźnienie (500); } display.println(); display.println("Połączono!"); //Maksymalny czas, w którym klient wymyśla postrach dla osoby odpowiadającej //czas oczekiwania na połączenie z perdida socket.setTimeout(TIMEOUT); }
IRAM_ATTR resetModuł i setupWatchdog
//função que o temporizador irá chamar, dla ponownego uruchomienia ESP32void IRAM_ATTR resetModule(){ ets_printf("(watchdog) ponowne uruchomienie\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), powtórzenie timerAlarmWrite(timer, 10000000, true); timerAlarmEnable(timer); //habilita a interrupção }
pętla
void loop() { timerWrite(timer, 0); //resetuj o temporizador (alimenta o watchdog) checkConnection(); //Sprawdź możliwe połączenie z serwerem checkRSSI(); //weryfikacja lub wykres rssi(); //mostra o grafice historycznej rssi sendToServer(); //wyślij uma mensagem com um contador dla serwera readFromServer(); //espera a Confirmação do server log(); //salva um log no cartão SD delay(1000); // espera um segundo }
Sprawdź połączenie
void checkConnection(){ //Weryfikacja połączenia z AP if(WiFi.status() != WL_CONNECTED) { display.fillScreen(ST77XX_BLACK); display.setCursor(0, 0); display.println("WiFi rozłączono"); konfiguracjaWiFi(); opóźnienie (1000); } //weryfikuj gniazdo conexão do if(!socket.connected()) { display.fillScreen(ST77XX_BLACK); display.setCursor(0, 0); display.println("Gniazdo odłączone"); połączyć się z serwerem(); opóźnienie(3000); display.fillScreen(ST77XX_BLACK); } }
sprawdźRSSI
void checkRSSI(){ //Weryfikacja RSSI rssi = WiFi. RSSI(); //Limpa o texto i mostra o RSSI brak wyświetlania clearText(); display.setCursor(0, 0); display.print("RSSI: " + String(rssi)); //Sprawdź, ile barras do grafiki 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 presente) rssiHistory.push_back(rssi); }
wątek
void plot(){ //Koloka nie ma początkowego ponto e limpamos o graficznego 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 -120 ? map(rssiHistory, -120, 0, 0, PLOT_SIZE): 0; display.drawFastVLine(currentX, DISPLAY_HEIGHT - wartość, wartość, PLOT_COLOR); currentX += 2; } }
wyślij do serwera
void sendToServer(){ //Połącz się z serwerem if(socket.connected()) { //Połącz się z serwerem witaj ze stykiem, nie wyświetlaj ani nie zwiększaj połączenia String wysyłanie = "Witaj " + String(liczba); display.setCursor(0, 10); display.println("Wysyłanie: " + wysyłanie); socket.println(wysyłanie); socket.print(String(rssi)); liczyć++; } }
odczyt z serwera
void readFromServer(){ //Wstrzymaj się od serwera lub wyślij algo lub desconectar while(socket.connected() && !socket.available()) { delay(100); } //Ustaw algo tem para receber if(socket.available()) { //Faz a leitura, usuń o \n wykonaj końcowy e nie odebrano wyświetlania = socket.readStringUntil('\n'); otrzymane.usuń(otrzymane.długość()-1); display.println("Odebrane: " + odebrane); } }
czysty tekst i log
void clearText(){ //Pomiń obszar z tekstem, aby wyświetlić komunikaty klientów display.fillRect(0, 0, DISPLAY_WIDTH, 2*PLOT_MARGIN, ST77XX_BLACK); } void log() { //Abrimos o arquivo para escrevermos no final dele Plik plik = SD.open(FILE_PATH, FILE_APPEND); //Se não conseguimos brir o arquivo mostramos uma mensagem de erro if(!file) { Serial.println("Nie udało się otworzyć pliku"); powrót; } //Gravamos uma linha com o tempo desde o boot, or rssi atual e a mensagem recebida String data = String(millis()) + ";" + Ciąg(rssi) + ";" + otrzymał; plik.println(dane); plik.zamknij(); }
Krok 10: Pliki
Pobierz pliki:
JA NIE