Search code examples
arduinoudpwifiesp8266

ESP8266 UDP parsePacket does not work when doing other stuff


The problem testing my mood for the past few days is that although my ESP8266 chip is perfectly capable of fetching packets with parsePacket in a while loop, it completely misses these when I want BOTH to listen to incoming packets, but also allow my ESP8266 to read out sensors and send these over wifi.

So I cut out everything that has to do with the sensors and pasted the code below, but here is what's happening.

  1. In Setup(), the ESP sets up the wifi, SoftAP node, UDP and configures it.
  2. It then gets to a while loop where it listens for an incoming package over wifi; this tells the ESP to start spitting out data.
  3. When the ESP receives a packet (this is the "A. <<<" comment in my code and works fine), the code moves to the Loop() part and the sensors start spitting out data which is send over wifi

MY PROBLEM IS THIS STEP:

  1. During reading out the sensors and sending data over wifi I want the ESP8266 also to be able to receive incoming packets over wifi (this is the "B. <<<" comment in my code and does not work), the ESP keeps sending sensor data over wifi, but it does not receive any packets

My guess is that A. works fine because the 'while' condition will allow parsePacket to always catch an incoming packet. And because B. is inside the void loop I cannot use a 'while' condition but instead an 'if' statement, the parsePacket command is not requesting for an incoming package on the right moment. I have not been able to implement something that solves this. Quite a bit of searching is not really helping out and I cannot imagine I am alone having this problem.

Some things I found related:

I greatly appreciate your help and feedback!

Here is my code:

#include <Wire.h>
#include <ESP8266WiFi.h>
#include <WiFiUDP.h>

String SendString;
String SendBuffer = "STR ";
boolean SendSuccessful;
char SendChar[32];

// wifi connection variables
const char* password = #########;
boolean wifiConnected = false;
String ssid_string;
char ssid[10];

// UDP variables
unsigned int localPort = 8888;
WiFiUDP UDP;
boolean udpConnected = false;
char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //buffer to hold incoming packet,
char ReplyBuffer[500] = "acknowledged"; // a string to send back

void setup(void) {
  Serial.begin(115200);

  //Setup all my sensors, code not relevant

  //Connect Wifi
  ssid_string = "DRILL_" + String(chip_id);
  ssid_string.toCharArray(ssid, 500);
  SetupWifi(ssid);
}

void loop(void) {

  //B. <<<< SO THIS IS THE PART IN THE LOOP THAT IS NOT WORKING
  int packetSize = UDP.parsePacket();
  packetSize = UDP.parsePacket();  
  if (packetSize) {
    Serial.println("");
    Serial.print("Received packet");

    // read the packet into packetBufffer
    UDP.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
    Serial.println("Contents:");
    int value = packetBuffer[0] * 256 + packetBuffer[1];
    Serial.println(value);
  }

  //Read out all my sensors, code not relevant, paste all sensor data in one string

  //SendString over serial
  Serial.print(SendString);

  SendIntervalUDP(1); // Send SendString over UDP every x measurements (see function below)

  //Listen to serial
  if (Serial.available() > 0) {
    String Received = Serial.readString();
    Serial.println("ESP received: " + Received);
  }
}

Now this are some of the support functions in setting up the wifi and sending data over wifi

unsigned long previousWifiStatMillis;

//Connect wifi during setup
void SetupWifi(char my_ssid[]) {

  // WiFi init
  wifiConnected = createAP(my_ssid);

  udpConnected = connectUDP();

  // Wait for first packet
  Serial.println("Waiting for start");

  //A. <<<< SO THIS IS THE PART IN THE CODE THAT IS ACTUALLY WORKING
  int packetSize = UDP.parsePacket();
  while (packetSize < 1) {
    packetSize = UDP.parsePacket();
    yield(); // Allow the background functions to work
    //Listen to serial
    if (Serial.available() > 0) {
      String Received = Serial.readString();
      Serial.println("I received: " + Received);
      if (Received.substring(0) == "S") {
        Serial.println("Starting..");
        break;
      }
    }

    if (packetSize)
    {
      Serial.println("");
      Serial.print("Received packet");

      // read the packet into packetBufffer
      UDP.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
      Serial.println("Contents:");
      int value = packetBuffer[0] * 256 + packetBuffer[1];
      Serial.println(value);

    }
  }
}


// connect to UDP – returns true if successful or false if not
boolean connectUDP() {
  boolean state = false;

  Serial.println("");
  Serial.println("Connecting to UDP");

  if (UDP.begin(localPort) == 1) {
    Serial.println("Connection successful");
    state = true;
  }
  else {
    Serial.println("Connection failed");
  }

  return state;
}

// connect to wifi – returns true if successful or false if not
boolean createAP(char my_ssid[]) {
  boolean state = true;
  int i = 0;
  WiFi.softAP(my_ssid, password);             // Start the access point
  WiFi.mode(WIFI_AP);
  Serial.print("Access Point \"");
  Serial.print(my_ssid);
  Serial.println("\" started");
  Serial.print("IP address:\t");
  Serial.println(WiFi.softAPIP());         // Send the IP address of the ESP8266 to the computer
  state = true;
  return state;
}


// connect to wifi – returns true if successful or false if not
boolean connectWifi(char my_ssid[]) {
  boolean state = true;
  int i = 0;
  WiFi.begin(my_ssid, password);
  Serial.println("");
  Serial.println("Connecting to WiFi");

  // Wait for connection
  Serial.print("Connecting");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
    if (i > 20) {
      state = false;
      break;
    }
    i++;
  }
  if (state) {
    Serial.println("");
    Serial.print("Connected to ");
    Serial.println(my_ssid);
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());
  }
  else {
    Serial.println("");
    Serial.println("Connection failed.");
  }
  return state;
}

void SendIntervalUDP(int interval) {
  //Send an udp packet every x packets with x the interval
  j++;
  if (j > (interval-1) ) {
    j = 0;
    //SendString over wifi
    if (wifiConnected) {
      if (udpConnected) {
        // send a reply, to predetermined hotspot
        UDP.beginPacket(UDP.remoteIP(), UDP.remotePort());
        SendBuffer.toCharArray(ReplyBuffer, 500);
        UDP.write(ReplyBuffer);
        UDP.endPacket();
      }
    }
    SendBuffer = "";
  }
}

Solution

  • The WiFi events in "Generic Class" are for OSI levels below transport layer. TCP and UDP are transport layer.

    To receive UDP packets you must call UDP.parsePacket(); in loop() (or in a function called from loop()) like with every other Arduino networking library implementing the Arduino UDP base class.

    If packet is available call to parsePacket reads the packet into internal buffer and returns the size of the packet. Next call to parsePacket clears the buffer and fills it with new packet if it is available. You call parsePacket twice and the second always returns nothing.