Не могу наладить обмен UDP сообщениями между двумя ESP8266

Тема в разделе "ESP8266, ESP32", создана пользователем Yasha, 7 мар 2019.

  1. Yasha

    Yasha Нуб

    Здравствуйте! В наличии ESP-12E и ESP-01S, как первый так и второй модуль должны как принимать так и отправлять UDP сообщения. ESP-01S постоянно подключен к общей точке доступа и имеет личный статически IP-адрес. ESP-12E не всегда может быть включен, так как питается от батарейки, которая садится время от времени. При каждом включении или переподключении к общей точке доступа ESP-12E отправляет UDP-сообщение длиной в 1 байт на ESP-01S, в свою очередь тот считывает сообщение и отправляет ответ в виде строки, записанной в символьном массиве, и ждёт ответа от ESP-12E. ESP-12E постоянно прослушивает порт и при каждом входящем сообщении считывает его. Таких сообщений всего должно быть 9. Если ESP-01S не дождался ответа в течении определенного периода, то отправляет повторно сообщение. Таких попыток всего 3.
    Запрос размером в 1 байт ESP-01S считывает, отправляет ответ в виде строки на ESP-12E, но тот в свою очередь вообще не видит этого сообщения. Пробовал менять порты, IP-адреса, способ отправки ответа, создавал отдельный экземпляр типа WiFiUDP, но ничего не помогло. С помощью Packet Sender отправлял пакеты, ответы от обоих модулей приходили мгновенно. Для написания кода использовал Arduino IDE.

    Скетч ESP-01S:
    Код (C++):
    #include <ESP8266WiFi.h>
    #include <WiFiUdp.h>
    #include <SoftwareSerial.h>
    #define localPort   500
    SoftwareSerial mySerial(2,3);       // RX, TX
    uint8_t count, key = 0, timeAnswer = 0;
    char ssid1[] = "STOP";
    char ssid2[] = "BOBER-FM";
    char pass1[] = "06640664";
    char pass2[] = "99999999";
    char Buffer[4] = {'0'};
    char Packet[9][5];
    char State_of_loom[9][5] = {{'1','7','1','0','\0'},   //Состояние станков
                            {'1','6','0','0','\0'},
                            {'1','5','1','0','\0'},              
                            {'0','1','0','0','\0'},
                            {'0','2','0','0','\0'},
                            {'0','3','0','0','\0'},
                            {'0','4','0','0','\0'},
                            {'0','5','0','0','\0'},
                            {'0','6','1','0','\0'}};
    WiFiUDP Udp;
    void Connect()
    {
      while (WiFi.status()!= WL_CONNECTED)
      {
        WiFi.begin(ssid1, pass1);
        delay(5000);
        if (WiFi.status() != WL_CONNECTED)
        {
          WiFi.begin(ssid2, pass2);
          delay(5000);
          if (WiFi.status() != WL_CONNECTED)
            delay(30000);
        }
      }
      Serial.println(WiFi.SSID());
      Serial.println(WiFi.localIP());
    }
    void Send(char *str)
    {
      Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
      Udp.write(str, sizeof(str));
      Udp.endPacket();
    }
    void UDP_Request()
    {
      int packetSize = Udp.parsePacket();
      if (packetSize == 1)                        //если пришел один байт (запрос), отправить первую строку и ждать ответа
      {
        count = 0;
        Udp.read();
        Serial.println("Request from ESP-12E");
        Send(State_of_loom[count]);
        Serial.println(State_of_loom[count]);
        key = 1;
      }
      else if (packetSize > 1)                    //если пришло больше одного байта, то отправить следующую строку
      {                                           //или очистить Buffer
        Udp.read();
        Serial.println("Answer from ESP-12E");
        if (Buffer[0] != '0')
          memset(Buffer,'0',4);
        else if (count < 8)
        {
          count++;
          Send(State_of_loom[count]);
          Serial.println(State_of_loom[count]);
          timeAnswer = 0;
        }
        key = 0;
      }
      else if (key > 0)
      {
        timeAnswer++;
        if (timeAnswer > 50)                    //после 50 циклов ожидания ответа отправляем сообщение снова
        {
          timeAnswer = 0;
          key++;
          Serial.print("key: ");
          Serial.println(key);
          if (Buffer[0] != '0')
            Send(Buffer);
          else
          {
            Send(State_of_loom[count]);
            Serial.println(State_of_loom[count]);
          }
          if (key == 4)                          //максимум 3 раза отправляем, если нет ответа
            key = 0;
        }
      }
    }
    void setup()
    {
      //mySerial.begin(57600);            // открываем программный серийный порт
      Serial.begin(115200);
      Connect();
      Udp.begin(localPort);             // Начинаем «слушать» клиентов:
    }
    void loop()
    {
      if (WiFi.status() == WL_CONNECTED)
      {
        UDP_Request();
      /*
        if (mySerial.available())
        {
          for (uint8_t i = 0; i < 4; i++)  //Считываем оповещение
            Buffer[i] = mySerial.read();              
          Send(Buffer);                    //отправляем оповещение с ожиданием ответа
          timeAnswer = 0;
          key = 1;
        }
        */

      }
      else
        Connect();
      delay(100);
    }
     
  2. Yasha

    Yasha Нуб

    Скетч для ESP-12E:
    Код (C++):
    #include <ESP8266WiFi.h>
    #include <WiFiUdp.h>
    #include "SH1106.h"
    #include "Frame.h"
    #define OLED_RESET  5   // RESET
    #define OLED_DC     4   // Data/Command
    #define OLED_CS     15  // Chip select
    #define ReplyBuffer "OK"
    #define localPort   5445
    #define interruptPin 2
    #define ASK         '?'
    #define ESP01_port  500
    #define sizeBuffer  9
    SH1106 display(true, OLED_RESET, OLED_DC, OLED_CS);
    IPAddress IP_ESP01(192,168,0,105);
    char ssid1[] = "STOP";
    char ssid2[] = "BOBER-FM";
    char pass1[] = "06640664";
    char pass2[] = "99999999";
    char Buffer[5] = {'0'};
    //char Messege[50];
    char packetBuffer[9][5]; //buffer to hold incoming packet
    WiFiUDP Udp;
    uint8_t i = 1, timeON = 0, Reply = 0;     //счётчик обычный, счётчик работы дисплея включенным
    uint16_t time1 = 0;            //счётчик до оповещенния разряда аккумулятора
    long vcc = 0, rssi, averageVCC;
    volatile byte ON = 0;          //переменная прерываний
    bool On = true;               //переменная обычного цикла
    bool FirstRequest = false;
    void Draw()                                                                 //функция отрисовки таблицы
    {
      display.drawXbm(0,14,Frame_width,Frame_height,(const char*)Frame_bits);
      for (uint8_t j = 0, k1 = 0; j < sizeBuffer; j++, k1 = 0)
      {
        if (j!=0)
        {
          if ((j%2 == 0)&&(j!=0))
            k1=1;
          display.drawString(((j+1)/2)*26, 15+(k1*25), String(packetBuffer[j]));
        }
        else
        {
          display.drawString(1, 15, String(packetBuffer[0]));
        }
        display.display();
      }
    }
    void Signal(long rssi_1 = rssi)                //функция отрисовки батарейки
    {
      display.setColor(BLACK);
      display.drawRect(115, 2, 10, 8);
      display.fillRect(115, 2, 10, 8);
      display.setColor(WHITE);
      Serial.println(rssi_1);
      if (rssi_1 < (-70))
          display.drawXbm(115, 2, W2_width,W2_height,(const char*)W2_bits);
        else if ((rssi_1 >= (-70)) && (rssi_1 < (-60)))
          display.drawXbm(115, 2, W3_width,W3_height,(const char*)W3_bits);
          else if ((rssi_1 >= (-60)) && (rssi_1 < (-50)))
            display.drawXbm(115, 2, W4_width,W4_height,(const char*)W4_bits);
            else if (rssi_1 >= (-50))
              display.drawXbm(115, 2, W5_width,W5_height,(const char*)W5_bits);
      display.display();
    }
    void Battery(long vcc_1 = averageVCC)                       //функция отрисовки уровня сигнала Wi-Fi
    {
      Serial.println(vcc_1);
      if (On)
      {
        display.setColor(BLACK);
        display.drawRect(0, 2, 16, 8);
        display.fillRect(0, 2, 16, 8);
        display.setColor(WHITE);
        if (vcc_1 >= 800)
          display.drawXbm(0, 2, Img_Battery_3_width, Img_Battery_3_height, (const char*)Img_Battery_3);
          else if ((vcc_1 >= 600) && (vcc_1 < 800))
            display.drawXbm(0, 2, Img_Battery_2_width, Img_Battery_2_height, (const char*)Img_Battery_2);
            else if ((vcc_1 >= 400) && (vcc_1 < 600))
              display.drawXbm(0, 2, Img_Battery_1_width, Img_Battery_1_height, (const char*)Img_Battery_1);
              else if (vcc_1 < 400)
                display.drawXbm(0, 2, Img_Battery_0_width, Img_Battery_0_height, (const char*)Img_Battery_0);      
        display.display();
      }
      else if (vcc_1 < 400)
      {
        time1++;
        if (time1 == 60000)
        {
          time1 = 0;
          display.clear();
          display.displayOn();
          display.drawXbm(20, 20, Img_BigBattery_low_width, Img_BigBattery_low_height, (const char*)Img_BigBattery_low);
          display.display();
          delay(2000);
          display.displayOff();
         }  
      }
      i = 1;
    }
    void UDP_chat()
    {
      int packetSize = Udp.parsePacket();
      if (packetSize > 0)
      {
        Serial.println(packetSize);
        int len = Udp.read(Buffer, 4);         //считывание пакета в Buffer
        if (len > 0)
        {
          Serial.println(len);
          Buffer[len] = '0';
        }
        Buffer[4] = '\0';           // записываем в конец признак конца строки для удобной работы с массивом как со строкой
        Udp.read();
        Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); //Отправляем ответ на IP и порт отправителя
        Udp.write(ReplyBuffer);
        Udp.endPacket();
        Serial.print("Contents: ");
        Serial.println(Buffer);
        if (!On)
        {
          display.displayOn();
          On = true;
          Serial.println("ON");
        }
        timeON = 0;
        if (!FirstRequest)                          // если был отправлен запрос на получение данных, то не выводить на дисплей
        {
          display.clear();
          display.setFont(ArialMT_Plain_24);
          display.drawString(30, 20, String(Buffer));
          display.display();
          delay(2000);
          display.clear();
        }
        else
        {
          Reply++;                                   //счётчик для запроса
          if (Reply == 9)                            // если считалось последнее запрошеное сообщение
          {
            Reply == 0;
            FirstRequest = false;
          }
        }
        Signal();
        Battery();
      }
    }
    void Attach()
    {
      static unsigned long millis_prev;
      if (millis() - 100 > millis_prev)            
          ON = 1;                        // меняем значение на противоположное
      millis_prev = millis();
      Serial.println (ON);
    }
    void Connect()
    {
       do
      {
        WiFi.begin(ssid1, pass1);
        delay(10000);
        if (WiFi.status() == WL_CONNECTED)
        {
          display.clear();
          display.drawString(0, 25, "Connect to \"" + String(ssid1) + "\"");
        }
        else
        {
          WiFi.begin(ssid2, pass2);
          delay(10000);
          if (WiFi.status() == WL_CONNECTED)
          {
             display.clear();
             display.drawString(0, 25, "Connect to \"" + String(ssid2) + "\"");
             break;
          }
          display.clear();
          display.drawString(20, 25, "No connection");
          display.display();
          Serial.println("No connection");
          delay(30000);
        }
      }
      while (WiFi.status()!= WL_CONNECTED);
      display.display();
      Request();
    }
    void Request()
    {
      Udp.beginPacket(IP_ESP01, ESP01_port);
      Udp.write(ASK);
      Udp.endPacket();
      FirstRequest = true;
    }
    void setup()
    {
      Serial.begin(115200);
      pinMode(interruptPin, INPUT_PULLUP);
      attachInterrupt(digitalPinToInterrupt(interruptPin), Attach, FALLING);
      Serial.println("");
      display.init();
      display.clear();
      display.setFont(ArialMT_Plain_24);
      display.drawString(17, 20, "SERVER");
      display.display();
      display.setFont(ArialMT_Plain_10);
      Connect();
      Serial.println(WiFi.SSID());
      Serial.println(WiFi.localIP());
      delay(2000);
      display.clear();
      Draw();
      Battery();
      Signal();
      Udp.begin(localPort); // Начинаем «слушать» клиентов:
    }
    void loop()
    {
      if (WiFi.status() == WL_CONNECTED)
      {
        if (ON == 1)
        {
          if (On)
          {
            Serial.println("OFF");
            display.displayOff();
            On = false;
          }
          else
          {
            Serial.println("ON");
            display.displayOn();
            On = true;
          }
          ON = 0;
          timeON = 0;
        }
        UDP_chat();
        i++;
        vcc += analogRead(A0);             //считывание напряжения аккумулятора
        if (i%20==0)
        {
          averageVCC = vcc/20;
          Battery();
          vcc = 0;
        }
        if (On)
        {
          timeON++;
          if (i%19 == 0)
          {
            rssi = WiFi.RSSI();
            Signal();
          }
          if (Buffer[1] != '0')               //если буфер не пуст, то скопировать его содержимое в массив по первой цифре
          {
            int number = atoi(Buffer);
            switch (number/100)
            {
              case 17:
              {
                strcpy(packetBuffer[0],Buffer);
                break;
              }
              case 16:
              {
                strcpy(packetBuffer[1],Buffer);
                break;
              }
              case 15:
              {
                strcpy(packetBuffer[2],Buffer);
                break;
              }
              default:
              {
           
                strcpy(packetBuffer[number+2],Buffer);
              }
            }
            memset(Buffer, '0', 4);
            display.setFont(ArialMT_Plain_10);
            Draw();                                    //вызов функции рисования таблицы и содержимого массива
          }
          if (timeON >= 150)                           //отключение дисплея после 150 циклов loop()
          {
            Serial.println("OFF");
            On = false;
            display.displayOff();
          }
        }
      }
      else
      {
        Connect();
      }
      delay(50);
    }
     
     
  3. Вот тут ошибка. Длину буфера в данном случае нужно передать явно. Функция не знает размера буфера, определенного извне
     
  4. Yasha

    Yasha Нуб

    Изменил на
    Udp.write(str, 5);
    Не помогло