ESP-NOW и Wi-Fi, и OTA одновременно на Отправителе и Получателе
Я пытаюсь настроить два ESP32, чтобы их можно было обновлять через OTA и в то же время отправлять показания датчиков с помощью ESP-NOW с платы отправителя на плату приемника.
Для этого обе платы должны подключиться к Wi-Fi и одновременно отправлять сообщения через ESP-NOW.
Я не возражаю против использования режима, в котором нажата кнопка и только тогда включен Wi-Fi, но включение и выключение Wi-Fi, похоже, имеет прерывистый успех.
Я попытался установить каналы одинаково на обеих платах, но это не сработало.
В приведенном ниже примере я удалил весь код OTA и код, необходимый для ESP-NOW, и только строку для включения WI-Fi
WiFi.begin(ssid, пароль);
который при включении приводит к сбою доставки.
Вот мой код отправителя:
#include <esp_now.h>
#include <WiFi.h>
#include <Wire.h>
#define ssid "MYNETWORKSSID"
#define password "mynetworkpassword"
const int sNine = 33;
#define CHAN_AP 2
uint8_t broadcastAddress[] = {0x24, 0x62, 0xAB, 0xDC, 0x70, 0x90};
int hall;
String success;
typedef struct struct_message {
int hall;
} struct_message;
struct_message hallReadings;
// Обратный вызов при отправке данных
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
Serial.print("\r\nLast Packet Send Status:\t");
Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
if (status ==0){
success = "Delivery Success :)";
}
else{
success = "Delivery Fail :(";
}
}
void setup() {
// Init Serial Monitor
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password); // ПРОБЛЕМНАЯ СТРОКА
// Init ESP-СЕЙЧАС
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
// Как только ESPNow будет успешно инициализирован, мы зарегистрируемся для отправки CB в
// получить статус Trasnmitted пакета
esp_now_register_send_cb(OnDataSent);
// Регистровый одноранговый
esp_now_peer_info_t peerInfo;
memcpy(peerInfo.peer_addr, broadcastAddress, 6);
peerInfo.channel = CHAN_AP;
peerInfo.encrypt = false;
// Добавить одноранговый узел
if (esp_now_add_peer(&peerInfo) != ESP_OK){
Serial.println("Failed to add peer");
return;
}
}
void loop() {
// getReadings();
hallReadings.hall = analogRead(sNine);
esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &hallReadings, sizeof(hallReadings));
if (result == ESP_OK) {
Serial.println("Sent with success");
}
else {
Serial.println("Error sending the data");
}
delay(100);
}
Вот мой код приемника:
#include <esp_now.h>
#include <WiFi.h>
#include <Wire.h>
const int sNine = 15;
// Канал Wi-Fi (должен совпадать с каналом Wi-Fi шлюза в качестве точки доступа)
#define CHAN_AP 2
// Определить переменные для хранения входящих показаний
int incomingHall;
//Пример структуры для отправки данных
//Должен соответствовать структуре получателя
typedef struct struct_message {
int hall;
} struct_message;
// Создайте struct_message для хранения входящих показаний датчиков
struct_message incomingReadings;
void updateDisplay(){
Serial.print(incomingReadings.hall);
}
// Обратный вызов при получении данных
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
memcpy(&incomingReadings, incomingData, sizeof(incomingReadings));
incomingHall = incomingReadings.hall;
}
void setup() {
// Init Последовательный монитор
Serial.begin(115200);
// Установить устройство в качестве станции Wi-Fi
WiFi.mode(WIFI_STA);
// Init ESP-СЕЙЧАС
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
// Регистрация функции обратного вызова, которая будет вызываться при получении данных
esp_now_register_recv_cb(OnDataRecv);
}
void loop() {
updateDisplay();
delay(100);
}
3 ответа
Лучший ответ:
Если вы хотите включить / выключить соединение SoftAP, вы можете сделать так, как предлагает StefanL38, и заставить Получателя передать Отправителю сообщение ESP-NOW со значением, но вам не нужна перезагрузка. Например, вы можете отбросить SoftAP и появиться как STA или наоборот.
if(incomingid == 3){
incomingValue = incomingReadings.Value;
// чтобы разрешить OTA, используя Элегантный OTA, не пробовал другие.
if(incomingValue == 1){
WiFi.softAP(ssid,password,6);
Serial.print("Connecting to ESP32 SSID ");
Serial.println(ssid);
IPAddress IP = WiFi.softAPIP();
Serial.print("AP IP address: ");
Serial.println(IP);
WiFi.printDiag(Serial);
}
// отключить и разрешить ESP-NOW через режим станции.
else if(incomingValue == 0){
WiFi.softAPdisconnect(true);
delay(1000);
WiFi.mode(WIFI_STA);
delay(1000);
WiFi.printDiag(Serial); // STA По умолчанию имеет канал 1
esp_wifi_set_promiscuous(true);
esp_wifi_set_channel(6, WIFI_SECOND_CHAN_NONE); // настройка канала 6
esp_wifi_set_promiscuous(false);
WiFi.printDiag(Serial);
}
}
Вы знаете, где вы помещаете этот код. Когда я пытаюсь поместить этот код в любое другое место, кроме настройки, ESP8266 падает, когда загружает прошивку. Можно ли использовать EEPROM в разделе настройки?, @user2067030
Это будет проходить под обратным вызовом, когда данные будут получены функцией ESP NOW, т.е.… void OnDataRecv, @Tony M
Я делаю что-то подобное на ESP8266, извлекая время с NTP-сервера. Хотя это всего лишь "обходной путь".
- Я подключаюсь к маршрутизатору, получая NTP-время.
- хранение информации о времени в RTC-RAM, включая флаг, указывающий "время получено".
- затем выполните сброс программного обеспечения
- функция setup проверяет этот флаг, чтобы решить, должен ли ESP8266 подключаться к маршрутизатору или держать Wi-Fi выключенным и активировать ESP-NOW
если вы хотите использовать это для OTA, это может "работать" следующим образом
отправка специального сообщения ESP-NOW, инициирующего установку флага "do_OTA" в RTC-RAM, а затем повторную загрузку функция setup ищет этот флаг "do_OTA", который будет установлен, делает то, что говорит ее имя, очищая флаг "do_OTA"
Чего я не знаю, так это того, что написание нового кода во flash - это совсем другое дело, чем просто повторная загрузка через сброс программного обеспечения. Так что, возможно, содержимое RTC-RAM теряется в процессе обновления.
Если это так, вы можете записать флаг во flash с помощью LittleFS
с уважением Стефан
Еще один метод, который работает, если вы не возражаете иметь и то, и другое одновременно:
Вместо WiFi.begin(ssid, пароль); Я использую WiFi.SoftAP (ssid, пароль, канал) как для Отправителя, так и для Получателя.
- esp32 Stack canary watchpoint срабатывает
- ESP32S v1.1 NodeMCU vs ESP32 DevKitV1
- esp32-cam публикует изображение в mqtt
- WindowsError(31, "Устройство, подключенное к системе, не функционирует") в arduino
- Как очистить кучу памяти в esp32
- PN532 не обнаруживает RFID-карту при подключении к ESP32 в режиме I2C, но отлично работает с Arduino Uno
- AsyncWebServer дает сброс wdt
- Не удается включить распознавание лиц на esp32 cam : CORRUPT HEAP: Bad head at 0x3ffe2eb4. Expected 0xabba1234 got 0x00000008 abort()
каков ваш конкретный вопрос?, @jsotola
Как я могу включить OTA на обеих платах, а также использовать ESP-now? когда я активирую Wi-Fi, ESPnow перестает работать. Спасибо!, @Jaspal Singh Rathour