[sw] ESP-NOW, test dosahu

Odpovědět
Pablo74
Příspěvky: 68
Registrován: 03 lis 2019, 17:00

[sw] ESP-NOW, test dosahu

Příspěvek od Pablo74 » 18 srp 2024, 17:55

Jsem mimo domov, mám omezenou zásobu HW.

Udělal jsem si jednoduchý test dosahu bezdrátové komunikace protokolem ESP-NOW. Teorii vynechám, je dostupná a srozumitelná v textu i videu. Jen zběžně: ESP-NOW je protokol od firmy Espressif (ano, to je ta, co vyrábí ESP8266 a ESP32), běží na frekvenci 2.4 GHz (ale není to WiFi).

Můj HW (dočasně omezené zásoby):
vysílač - Ideaspark 8266 (NodeMCU ESP8266 Development Board with 0.96‘’ OLED Display): https://www.aliexpress.com/item/1005005242283189.html
přijímač: TTGO T-Display: https://www.aliexpress.com/item/33048962331.html

Běžně se ESP-NOW používá tak, že vysílač i přijímač musí znát MAC adresu toho druhého zařízení; existuje i možnost broadcast, kdy vysílač neposílá konkrétnímu zařízení, ale všem. A toho jsem právě využil.

program pro vysílač:

Kód: Vybrat vše

/* 
Ideaspark ESP8266
*/

#include <ESP8266WiFi.h>
#include <espnow.h>
#include <Wire.h>
#include <U8g2lib.h>

// Inicializace U8g2 pro SH1106 128x64 OLED displej
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0,/*clock=*/14,/*data=*/12,U8X8_PIN_NONE);

// Struktura pro odesílaná data
typedef struct struct_message {
    char text[20];
    int number;
} struct_message;

// Vytvoření struktury pro odesílaná data
struct_message myData;

// MAC adresa pro broadcast
uint8_t broadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};

// Callback funkce při odeslání dat
void OnDataSent(uint8_t *mac_addr, uint8_t sendStatus) {
  Serial.print("Status posledního paketu: ");
  Serial.println(sendStatus == 0 ? "Doručeno" : "Chyba při doručení");
}

void setup() {
  Serial.begin(115200);
  
  // Inicializace OLED displeje
  u8g2.begin();
  u8g2.clearBuffer();
  u8g2.setFont(u8g2_font_ncenB08_tr);
  u8g2.drawStr(0, 10, "Init...");
  u8g2.sendBuffer();
  delay(1500);

  // Inicializace Wi-Fi
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();

  // Nastavení maximálního výkonu vysílače
  WiFi.setOutputPower(20.5);

  // Nastavení nižší přenosové rychlosti pro lepší dosah
  WiFi.setPhyMode(WIFI_PHY_MODE_11B);

  // Inicializace ESP-NOW
  if (esp_now_init() != 0) {
    Serial.println("ESP-NOW Init error!");
    u8g2.clearBuffer();
    u8g2.drawStr(15, 15, "ESP-NOW ERROR");
    u8g2.sendBuffer();
    delay(1500);
    return;
  }

  // Nastavení ESP-NOW role
  esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);

  // Registrace callback funkce
  esp_now_register_send_cb(OnDataSent);
  
  // Registrace peer (broadcast)
  esp_now_add_peer(broadcastAddress, ESP_NOW_ROLE_SLAVE, 1, NULL, 0);

  u8g2.clearBuffer();
  u8g2.drawStr(0, 10, "Ready to bradcast");
  u8g2.sendBuffer();
  delay(1500);
}

void loop() {
  // Příprava dat k odeslání
  strcpy(myData.text, "Connection Test");
  static int counter = 0;
  myData.number = counter;
  
  // Odeslání zprávy přes ESP-NOW
  esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));

  // Zobrazení čísla na displeji
  u8g2.clearBuffer();
  u8g2.setFont(u8g2_font_ncenB14_tr);
  u8g2.drawStr(15, 15, "ESP-NOW");
  char buf[20];
  snprintf(buf, sizeof(buf), "Sent: %d", counter);
  u8g2.drawStr(25, 48, buf);
  u8g2.sendBuffer();

  // Inkrementace čítače
  counter = (counter + 1) % 100;

  // Čekání 2.5 sekundy
  delay(2500);
}
program pro přijímač:

Kód: Vybrat vše

#include <esp_now.h>
#include <WiFi.h>
#include <TFT_eSPI.h>

// Inicializace TFT displeje
TFT_eSPI tft = TFT_eSPI();

// Struktura pro přijímaná data
typedef struct struct_message {
    char text[20];
    int number;
} struct_message;

// Vytvoření struktury pro přijímaná data
struct_message myData;

// Proměnné pro ukládání posledních tří čísel
int lastNumbers[3] = {0, 0, 0};

// Callback funkce při přijetí dat
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
  memcpy(&myData, incomingData, sizeof(myData));
  Serial.print("Bytes received: ");
  Serial.println(len);
  Serial.print("Text: ");
  Serial.println(myData.text);
  Serial.print("Number: ");
  Serial.println(myData.number);
  
  // Aktualizace posledních tří čísel
  lastNumbers[2] = lastNumbers[1];
  lastNumbers[1] = lastNumbers[0];
  lastNumbers[0] = myData.number;
  
  // Aktualizace displeje
  updateDisplay();
}

void updateDisplay() {
  tft.fillScreen(TFT_BLACK);
  tft.setTextColor(TFT_WHITE, TFT_BLACK);

  // text
  tft.setTextColor(TFT_WHITE, TFT_BLACK);
  tft.setTextSize(3);
  tft.setCursor(40, 60);
  tft.print("> ESP-NOW <");
  
  tft.setTextColor(TFT_WHITE, TFT_BLACK);
  // Nejnovější číslo - největší
  tft.setTextSize(5);
  tft.setCursor(80, 90);
  tft.print(lastNumbers[0]);
  
  // Předchozí číslo - střední
  tft.setTextSize(5);
  tft.setCursor(80, 140);
  tft.print(lastNumbers[1]);
  
  // Nejstarší číslo - nejmenší
  tft.setTextSize(5);
  tft.setCursor(160, 140);
  tft.print(lastNumbers[2]);
}

void setup() {
  Serial.begin(115200);
  
  // Inicializace Wi-Fi
  WiFi.mode(WIFI_STA);

  // Inicializace ESP-NOW
  if (esp_now_init() != ESP_OK) {
    Serial.println("Chyba při inicializaci ESP-NOW");
    return;
  }

  // Nastavení kanálu Wi-Fi (musí být stejný jako u vysílače)
  WiFi.channel(1);

  // Registrace callback funkce
  esp_now_register_recv_cb(OnDataRecv);
  
  // Inicializace TFT displeje
  tft.init();
  //tft.setRotation(1);
  tft.fillScreen(TFT_BLACK);
  
  updateDisplay();
}

void loop() {
  // Hlavní smyčka je prázdná, protože veškerá logika
  // je zpracovávána v callback funkci OnDataRecv
}
Vysílač periodicky vysílá celé číslo, začne od 0 a po čísle 99 se jde znovu od 0. Na přijímači se zobrazují tři poslední skutečně přijatá čísla (ideálně tedy čísla n, n-1, n-2). Je to celkem praktická věc, hned je vidět, kolik zpráv nebylo při testu přijato.

Programy jsou vhodné pro testování dosahu ESP-NOW komunikace, vysílač nechám stacionárně doma a s přijímačem jdu okolo domu. Na displeji vidím tři poslední přijatá čísla, interval mám na vysílači nastavený na dvě a půl sekundy.

Jistě vás teď napadlo, jaký je reálný dosah. Krátká odpověď: otestujte si to ve vašich podmínkách sami. Delší odpověď: protože je přenos přes 2.4 GHz a s malým výkonem, dosah tomu odpovídá. Na volném prostoru jsem se dostal spolehlivě na 40 metrů, záleží ovšem i na tom prostoru jako takovém - mlha nebo mokré listy vzrostlých stromů jsou překážkou. V zástavbě pak záleží na tloušťce stěn, kovových konstrukcích, rušení WiFi a dalších faktorech.

Prostě je potřeba to vyzkoušet na místě.

Budu rád, pokud můj příspěvek někomu pomůže nebo ho inspiruje.

Odpovědět

Kdo je online

Uživatelé prohlížející si toto fórum: Žádní registrovaní uživatelé a 1 host