UDP communication using Ethernet on ESP32 PLC

January 17, 2024 by
UDP communication using Ethernet on ESP32 PLC
Boot & Work Corp. S.L., Francesc Nosas

Introduction

In this blog post, we will explore how to setup a simple application using Ethernet UDP communication between any device and an ESP32 PLC.

We will explain how to create an EthernetUDP instance on your ESP32 PLC which will be accessible by all devices on the same sub-net. Reading and using the following code, you will be able to easily learn how to send messages to your ESP32 PLC from another device, using one of the simplest communication protocols used in industrial data transfer.


Simple UDP application

We have written the following code:

// Simple UDP communication for controlling a LED
// Commands: Start, LedON, LedOFF

#include <ethernet.h>
#include <ethernetudp.h>

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
IPAddress ip(10, 42, 0, 20);

unsigned int localPort = 8888;      // local port to listen on
unsigned int replyPort = 8889;      // port to send response to

char packetBuffer[UDP_TX_PACKET_MAX_SIZE];  // buffer for receiving incoming data

EthernetUDP Udp;// An EthernetUDP instance to let us send and receive packets over UDP

bool ledStatus = LOW;

// Response function
String responseUdp(String incoming_message){
  incoming_message = incoming_message.substring(0,incoming_message.length()-1);
  if (incoming_message=="Start"){ledStatus=HIGH; return "ACK0";}
  else if (incoming_message=="LedOn"){ledStatus=HIGH; return "ACK1";}
  else if (incoming_message == "LedOff"){ledStatus=LOW; return "ACK2";}
  else return "Unrecognised Command";
}

void setup() {
  // Serial
  Serial.begin(9600);
  while (!Serial) {;}
  Serial.println("Serial ready");

  // Ethernet
  Ethernet.begin(mac, ip);
  // Check for Ethernet hardware
  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
    while (true) {
      delay(1); // do nothing, no point running without Ethernet hardware
    }
  }
  if (Ethernet.linkStatus() == LinkOFF) {
    Serial.println("Ethernet cable is not connected.");
  }
  Serial.println("Ethernet ready");

  // Start UDP
  Udp.begin(localPort);
  Serial.println("UDP ready");
}

void loop() {
  // if there's data available, read a packet
  int packetSize = Udp.parsePacket();
  if (packetSize) {
    // read the packet into packetBufffer
    Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
    
    // Packet info
    Serial.print("Received packet of size ");
    Serial.println(packetSize);
    Serial.print("From ");
    IPAddress remote = Udp.remoteIP();
    for (int i=0; i < 4; i++) {
      Serial.print(remote[i], DEC);
      if (i < 3) {
        Serial.print(".");
      }
    }
    Serial.print(", port ");
    Serial.println(Udp.remotePort());
    Serial.print("Contents:");
    Serial.println(packetBuffer); //*/

    // Process packet and generate response
    String reply = responseUdp(packetBuffer);
    
    // send a reply to the IP address that sent us the packet we received to a port of our choice
    int reply_port = replyPort;     // Port to send msg back to. Switch to Udp.remotePort() to reply to the transmitting port
    Udp.beginPacket(Udp.remoteIP(), reply_port);
    
    Serial.println("Sending message \""+reply+"\" back to port: "+String(reply_port));
    reply+="\n";
    const char* udp_reply = reply.c_str();
    Udp.write(udp_reply);
    Udp.endPacket();  //*/
  }
  delay(10);
  if (ledStatus) {
    digitalWrite(Q0_0, HIGH);
  }
  else
  {
    digitalWrite(Q0_0, LOW);
  }
}


This code is fully scalable, allowing for easy addition of new UPC orders and responses. All incoming messages are parsed in the responseUdp() function, which returns a response string which can be later sent through the same port it was received or a fixed one (default).


Example

There are many ways to send an UDP packet to a device, but we'll be using the following command:

	​$ echo "msg" > /dev/udp/10.42.0.20/8888

To listen for a response we'll be relying on this other command:

	​$ netcat -ul 8889

Notice 8888 and 8889 are the ports where the communication takes place through, as declared in the code. If we send a few messages through port 8888:

UDP echo messages

We get the following responses on port 8889, while blinking the Q0_0 LED:

UDP_netcat_responses

​Search in our Blog

UDP communication using Ethernet on ESP32 PLC
Boot & Work Corp. S.L., Francesc Nosas January 17, 2024
Share this post

Looking for your ideal Programmable Logic Controller?

Take a look at this product comparison with other industrial controllers Arduino-based. 

We are comparing inputs, outputs, communications and other features with the ones of the relevant brands.


Industrial PLC comparison >>>