Ir al contenido

Comunicación UDP mediante Ethernet en un ESP32 PLC

17 de enero de 2024 por
Comunicación UDP mediante Ethernet en un ESP32 PLC
Boot & Work Corp. S.L, Francesc Nosàs Moliner

Introducción

En este artículo veremos cómo montar una aplicación sencilla con comunicación Ethernet UDP entre cualquier dispositivo y un PLC ESP32.

Explicaremos cómo crear una instancia EthernetUDP en tu PLC ESP32 a la que podrán acceder todos los dispositivos de la misma subred. Leyendo y utilizando el código siguiente aprenderás fácilmente a enviar mensajes a tu PLC ESP32 desde otro dispositivo, con uno de los protocolos de comunicación más sencillos que se usan en la transferencia de datos industriales.


Aplicación UDP sencilla

Hemos escrito el siguiente código:

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


Este código es totalmente escalable y permite añadir fácilmente nuevos comandos UDP y respuestas. Todos los mensajes entrantes se analizan en la función responseUdp(), que devuelve una cadena de respuesta que después se puede enviar por el mismo puerto por el que se recibió o por uno fijo (el predeterminado).


Ejemplo

Hay muchas formas de enviar un paquete UDP a un dispositivo, pero aquí usaremos el siguiente comando:

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

Para escuchar la respuesta usaremos este otro comando:

	​$ netcat -ul 8889

Ten en cuenta que 8888 y 8889 son los puertos por los que se realiza la comunicación, tal como se declara en el código. Si enviamos algunos mensajes por el puerto 8888:

Mensajes de eco UDP

Obtenemos las siguientes respuestas en el puerto 8889, mientras parpadea el LED Q0_0:

Respuestas de netcat UDP

Buscar en nuestro blog

Comunicación UDP mediante Ethernet en un ESP32 PLC
Boot & Work Corp. S.L, Francesc Nosàs Moliner 17 de enero de 2024
Compartir esta publicación
Etiquetas

¿Estás buscando tu Controlador Lógico Programable ideal?

Echa un vistazo a esta comparativa de producto de varios controladores industriales basados en Arduino.

Comparamos entradas, salidas, comunicaciones y otras especificaciones con las de los equipos de otras marcas destacadas.

Comparativa de PLCs