Я подумал , а DeepSeek ответил:
Привет! Ты абсолютно прав —
ESP-NOW действительно будет самым простым и эффективным решением для твоей задачи.
В отличие от обычного Wi-Fi (MQTT или HTTP), ESP-NOW не требует наличия роутера в сети, работает по принципу "беспроводной мыши" (очень низкая задержка) и прощает отсутствие интернета. Это идеальный вариант для пультов, датчиков и передачи управляющих сигналов.
Ниже я привел два готовых примера: для популярной среды
Arduino IDE (язык C++) и для
MicroPython (если ты предпочитаешь Python).
Как это работает (Кратко)
- Sender (ESP-A) получает значение (сигнал) и отправляет структуру данных напрямую по MAC-адресу получателя.
- Receiver (ESP-B) слушает эфир, и когда ловит пакет от знакомого MAC-адреса, обрабатывает его (например, включает светодиод или реле).
Вариант 1: Arduino IDE (Рекомендуемый, C++)
Это самый распространенный способ. Оба кода заливаются через Arduino IDE.
1. Код для Receiver (Приемник) — ESP-B
Сначала загрузи этот скетч в ту плату, которая будет
получать сигнал. Он также выведет MAC-адрес в монитор порта — он понадобится на следующем этапе.
cpp
#include <esp_now.h>
#include <WiFi.h>
// Структура данных, которую мы ожидаем получить (должна совпадать с отправителем)
typedef struct struct_message {
int commandId; // ID команды (например, 1 = Вкл, 2 = Выкл)
int value; // Какое-то значение (например, яркость 0-255)
} struct_message;
struct_message myData;
// Callback-функция, вызывается при получении данных
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
memcpy(&myData, incomingData, sizeof(myData));
Serial.print("Получено с устройства: ");
Serial.print("Команда: ");
Serial.print(myData.commandId);
Serial.print(", Значение: ");
Serial.println(myData.value);
// --- ТВОЯ ЛОГИКА УПРАВЛЕНИЯ ---
if (myData.commandId == 1) {
// Например, включить LED на пине 2
digitalWrite(2, HIGH);
Serial.println("LED включен");
} else if (myData.commandId == 2) {
digitalWrite(2, LOW);
Serial.println("LED выключен");
}
}
void setup() {
Serial.begin(115200);
// Инициализация пина для примера с LED
pinMode(2, OUTPUT);
WiFi.mode(WIFI_STA);
if (esp_now_init() != ESP_OK) {
Serial.println("Ошибка инициализации ESP-NOW");
return;
}
// Регистрируем функцию приема данных
esp_now_register_recv_cb(OnDataRecv);
// Выводим MAC-адрес этого устройства (Приемника)
// Его нужно будет скопировать и вставить в код Отправителя
Serial.print("MAC Address Receiver: ");
Serial.println(WiFi.macAddress());
}
void loop() {
// Здесь ничего не нужно, все работает в прерывании
}
2. Код для Sender (Отправитель) — ESP-A
Замени в коде broadcastAddress[] на MAC-адрес, который ты получил в мониторе порта
Приемника. Загрузи этот код в другую плату.
cpp
#include <esp_now.h>
#include <WiFi.h>
// !!! ЗДЕСЬ ДОЛЖЕН БЫТЬ MAC-АДРЕС ТВОЕГО ПРИЕМНИКА (ESP-B) !!!
uint8_t broadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
// Та же самая структура данных, что и у приемника
typedef struct struct_message {
int commandId;
int value;
} struct_message;
struct_message myData;
// Callback отправки (опционально, для проверки статуса)
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
Serial.print("Статус отправки:\t");
Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Успех" : "Провал");
}
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
if (esp_now_init() != ESP_OK) {
Serial.println("Ошибка инициализации");
return;
}
esp_now_register_send_cb(OnDataSent);
// Добавляем пира (приемника)
esp_now_peer_info_t peerInfo;
memcpy(peerInfo.peer_addr, broadcastAddress, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
if (esp_now_add_peer(&peerInfo) != ESP_OK){
Serial.println("Не удалось добавить пира");
return;
}
Serial.println("Готов к отправке сигналов");
}
void loop() {
// Эмуляция нажатия кнопки: отправляем "Включить" (1) и "Выключить" (2)
myData.commandId = 1; // Команда "Включить"
myData.value = 100;
esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));
Serial.println("Отправлена команда: ВКЛ");
delay(3000); // Ждем 3 секунды
myData.commandId = 2; // Команда "Выключить"
esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));
Serial.println("Отправлена команда: ВЫКЛ");
delay(3000);
}
Вариант 2: MicroPython (ESP32 / ESP8266)
Если твои проекты пишутся на Python, используй встроенную библиотеку espnow.
Код получателя (Receiver):
python
import network
import espnow
# Активируем Wi-Fi в режиме станции
sta = network.WLAN(network.WLAN.IF_STA)
sta.active(True)
sta.disconnect() # Отключаемся от конкретной сети, если была подключена
# Инициализируем ESP-NOW
e = espnow.ESPNow()
e.active(True)
print("Приемник запущен. MAC:", sta.config('mac').hex())
while True:
# Ждем данные (блокируем выполнение)
peer, msg = e.recv()
if msg:
command = msg.decode('utf-8')
print(f"Получен сигнал от {peer.hex()}: {command}")
if command == "ON":
# Твоя логика, например:
# import machine; machine.Pin(2, machine.Pin.OUT).on()
print("Включаем нагрузку")
elif command == "OFF":
print("Выключаем нагрузку")
Код отправителя (Sender):
python
import network
import espnow
import time
sta = network.WLAN(network.WLAN.IF_STA)
sta.active(True)
sta.disconnect()
e = espnow.ESPNow()
e.active(True)
# !!! ВСТАВЬ СЮДА MAC АДРЕС ТВОЕГО ПРИЕМНИКА !!!
# Узнать его можно выполнив скрипт выше (Receiver) и посмотрев в консоль
peer_mac = b'\xff\xff\xff\xff\xff\xff'
e.add_peer(peer_mac)
print("Отправитель запущен. Отправляю команды...")
while True:
e.send(peer_mac, "ON", True)
print("Sent: ON")
time.sleep(2)
e.send(peer_mac, "OFF", True)
print("Sent: OFF")
time.sleep(2)
Важные советы и нюансы
- Как узнать MAC-адрес: Если у тебя еще нет адреса приемника, залей на него первый скетч из Варианта 1 (C++) или скетч Receiver из Варианта 2 (Python) и открой Serial Monitor (Tools -> Serial Monitor) на скорости 115200.
- Максимальный размер данных: За раз можно передать до 250 байт. Старайся не передавать огромные строки, используй структуры (struct), как в примере на C++.
- Wi-Fi и ESP-NOW одновременно: ESP32 может быть подключен к обычному Wi-Fi роутеру (чтобы слать данные в MQTT) и одновременно общаться по ESP-NOW с другими платами (чтобы дергать светодиодом). У ESP8266 с этим бывают сложности, если роутер меняет канал.
- Каналы связи: Оба устройства должны находиться на одном Wi-Fi канале. Если у тебя роутер "прыгает" по каналам, лучше включить режим "Точка доступа (AP)" на одном из ESP или использовать Broadcast (MAC FF:FF:FF:FF:FF:FF), чтобы сбросить привязку к каналу, но это повлияет на дальность.
ESP-NOW отлично подходит для твоей задачи — он простой и надежный. Напиши, если на каком-то шаге возникнут трудности!