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

, 👍0

Обсуждение

каков ваш конкретный вопрос?, @jsotola

Как я могу включить OTA на обеих платах, а также использовать ESP-now? когда я активирую Wi-Fi, ESPnow перестает работать. Спасибо!, @Jaspal Singh Rathour


3 ответа


Лучший ответ:

2

Если вы хотите включить / выключить соединение 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


2

Я делаю что-то подобное на 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

с уважением Стефан

,

2

Еще один метод, который работает, если вы не возражаете иметь и то, и другое одновременно:

Вместо WiFi.begin(ssid, пароль); Я использую WiFi.SoftAP (ssid, пароль, канал) как для Отправителя, так и для Получателя.

,