• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

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

Yasha

New member
Здравствуйте! В наличии 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:
Код:
#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);
}
 

Yasha

New member
Скетч ESP-12E:
Код:
#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);
}
 
Сверху Снизу