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);
}
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
}
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.