How to get only the latest UDP packet from a broadcast?

Hi, I'm trying to write a program which listens for UDP packets and transforms them into various string commands. I have Arduino Uno with an Ethernet shield.

My UDP broadcaster is a C# program which sends 25 packets per second via a timer.
Let's say I run my C# program for 4 seconds, which will result in 100 packets sent.

I've put a large delay at the end of the Arduino loop to simulate heavy processing of the incoming message and I've encountered a problem.

Arduino takes (X + 1000) ms to process a single packet, which means that while it processes the first packet, there are 24 more sent.

The problem is that after processing packet 1 it doesn't get the newest packet from the broadcast, instead it continues with processing packet 2.

My question is if there is any way to flush/delete all of the incoming UDP packets and just wait for the next one (or get the last incoming one)? This way I will be sure that the processed data is always a fresh string command.


My code is a standard EthernetUdp example, the only modifications I've made are the attached buzzer and the increased delay.

#include <SPI.h>         // needed for Arduino versions later than 0018
#include <Ethernet.h>
#include <EthernetUdp.h>         // UDP library from: bjoern@cs.stanford.edu 12/30/2008

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 0, 199);
unsigned int localPort = 8888;      // local port to listen on

char packetBuffer[UDP_TX_PACKET_MAX_SIZE];  //buffer to hold incoming packet,
char ReplyBuffer[] = "seen";       // a string to send back

EthernetUDP Udp;

void setup() {
  Ethernet.begin(mac, ip);
  Udp.begin(localPort);
  Serial.begin(9600);

  pinMode(8, OUTPUT); // buzzer
}

void loop() {
  digitalWrite(8, LOW);
  
  int packetSize = Udp.parsePacket();
  if (packetSize) {
    digitalWrite(8, HIGH);

    //DisplayInfo(packetSize);

    // read the packet into packetBufffer
    Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
    Serial.println(packetBuffer);

    // send a reply to the IP address and port that sent us the packet we received
    Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
    Udp.write(ReplyBuffer);
    Udp.endPacket();
  }
  delay(1000);
}

Since I've wrote here I've managed to resolve my problem so I'm posting the code in case anyone else is having the same issue in the future

I noticed that Udp.parsePacket() is a relatively cheap operation so with the help of two flags I've managed to implement the following logic:

  • Get the next packet
  • Save data from packet if any
  • Repeat until an empty packet is encountered
  • If the current packet is empty but there is saved data for processing - continue with the program

This way after receiving 25 UDP packets, the program just discards the first 24 and gets only the newest one, resulting in a more up-to-date connection.

Code:

#include <SPI.h>         // needed for Arduino versions later than 0018
#include <Ethernet.h>
#include <EthernetUdp.h>         // UDP library from: bjoern@cs.stanford.edu 12/30/2008

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 0, 199);
unsigned int localPort = 8888;      // local port to listen on

char packetBuffer[UDP_TX_PACKET_MAX_SIZE];  //buffer to hold incoming packet,
char ReplyBuffer[] = "seen";       // a string to send back

EthernetUDP Udp;

bool thisPacketIsNotEmpty = false;
bool previousPacketIsLoaded = false;

void setup() {
  Ethernet.begin(mac, ip);
  Udp.begin(localPort);
  Serial.begin(9600);

  pinMode(8, OUTPUT); // buzzer
}

void loop() {
  while (true) {
    thisPacketIsNotEmpty = (Udp.parsePacket() > 0);

    if (thisPacketIsNotEmpty) { // raise flag that a packet is loaded and read it in the buffer
      previousPacketIsLoaded = true;
      Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
    }
    else if (!thisPacketIsNotEmpty && previousPacketIsLoaded) { // if the current packet is empty, but a loaded packet exists, break out of the loop
      previousPacketIsLoaded = false;
      break;
    }
    else { // you should never reach this spot
      DisplayDebugInfo(false); // show UDP packet and values of bools
    }
  }

  ParsePacket();

  thisPacketIsNotEmpty = false;
  previousPacketIsLoaded = false;
}

void ParsePacket() {
  digitalWrite(8, HIGH);
  delay(3);
  digitalWrite(8, LOW);
  Serial.println(packetBuffer);

  // send a reply to the IP address and port that sent us the packet we received
  Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
  Udp.write(ReplyBuffer);
  Udp.endPacket();

  DisplayDebugInfo(false);
  delay(200);
}

int DisplayDebugInfo(bool longInfo) {
  if (longInfo) {

    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.println(packetBuffer);
}