Can only receive UDP sometimes

I am making a simulator box that pretends to be an industrial pump. We make equipment that interfaces with the pump and don't always have a pump available to test the connection. I used and arduino uno with an ethernet shield 2 to do this. The manufacturer of the pump has a very simple communication scheme. A 10 byte packet is sent to the pump via UDP once a second. The IP address and port on the pump are fixed.

I wrote a simple sketch that looks for the 10 byte UDP packet and then does some bitwise examination, then illuminates some LEDs.

Everything seemed to work great at first. I did my initial testing, I would get the packet, the bits would match, LEDs would illuminate. When I went back and tested it again it would not receive anything. parsePacket() always returns zero. The ethernet link is established, the amber LED on the ethernet shield flashes once a second but nothing shows up.

I have two machines that are in known good working order and neither would work with the arduino. They both worked during the initial testing. We do currently have a pump and both machines will operate the pump with no problems.

On a whim I rebooted one of the machines and packets started to show up again on the arduino when connected to that machine. The other machine still shows nothing on the arduino and both machines will operate the pump.

I tried connecting to them with wire shark. I can see both machines sending a 10 byte UDP packet. The source and destination IPs are correct, the port is correct as well. I bet that if I reboot the other machine that it will start working with arduino again.

I'm using the 2.0.2 Ethernet library.

I'm at a loss as to what to trouble shoot next?

#include <Ethernet.h>
#include <EthernetUdp.h>


#define PUMP_ON 9
#define LOW_PRESSURE 8
#define CUTTING_HEAD_OPEN 7
#define LINK_ESTABLISHED 6
#define HEAERT_BEAT 5

// MAC address and IP.
byte mac[] = { 0xA8, 0x61, 0x0A, 0xAF, 0x01, 0x92 };
IPAddress ip(172, 16, 0, 106);

// The local port to listen for connections on.
unsigned int localPort = 8682;

// The maximum number of characters to receive from an incoming packet
#define MAX_PACKET_LENGTH 100
// Buffer for holding received packets.
char packetReceived[MAX_PACKET_LENGTH];

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

union uint_double_char {
  unsigned int Integer;
  unsigned char Character[2];
};

union BFT_COMMAND_DATA {
  struct {
    bool start : 1;
    bool stop : 1;
    bool reset : 1;
    bool pressure_relief : 1;
    bool adjusting_jet : 1;
    bool enable : 1;
    bool high_low : 1;
    bool valve : 1;
  };
  unsigned char data;
};

enum ESTOP_CHECK_STATE_MACHINE {
  ALL_OFF = 0,
  PAIR_1_ASSERT,
  PHASE_1_CHECK_1,
  PHASE_1_CHECK_2,
  PAIR_2_ASSERT,
  PHASE_2_CHECK_2,
  PHASE_2_CHECK_1
};

enum ESTOP_CHECK_STATE_MACHINE estop_state_machine = ALL_OFF;

enum ESTOP_CHECK_STATE {
  OFF = 0,
  OK,
  CROSS_WIRED_OR_SHORTED
};

enum ESTOP_CHECK_STATE estop_circuit_1 = OFF, estop_circuit_2 = OFF;

union BFT_COMMAND_DATA bft_command_data;

union uint_double_char conversion;

void setup() {
  pinMode(HEAERT_BEAT, OUTPUT);
  pinMode(LINK_ESTABLISHED, OUTPUT);
  digitalWrite(LINK_ESTABLISHED, HIGH);
  pinMode(PUMP_ON, OUTPUT);
  digitalWrite(PUMP_ON, HIGH);
  pinMode(LOW_PRESSURE, OUTPUT);
  digitalWrite(LOW_PRESSURE, HIGH);
  pinMode(CUTTING_HEAD_OPEN, OUTPUT);
  digitalWrite(CUTTING_HEAD_OPEN, HIGH);
  // pinMode(ESTOP_CIRCUIT_ICICATOR_1, OUTPUT);
  // digitalWrite(ESTOP_CIRCUIT_ICICATOR_1, HIGH);
  // pinMode(ESTOP_CIRCUIT_ICICATOR_2, OUTPUT);
  // digitalWrite(ESTOP_CIRCUIT_ICICATOR_2, HIGH);
  // pinMode(ESTOP_CIRCUIT_EXCITE_1, OUTPUT);
  // pinMode(ESTOP_CIRCUIT_EXCITE_2, OUTPUT);

  Serial.begin(9600);
  Ethernet.begin(mac, ip);
}

void loop() {
  static unsigned long time_second = 0;
  if (millis() - time_second > 1000) {
    time_second = millis();
    static bool light = false;
    light ^= 1;
    digitalWrite(HEAERT_BEAT, light);
  }

  static bool Link_Established = false;
  if ((Ethernet.linkStatus() == LinkON) && (Link_Established == false)) {
    // Begin listening on the local port for UDP datagrams
    Udp.begin(localPort);
    Link_Established = true;
    Serial.println("link established");
  }
  if ((Ethernet.linkStatus() == LinkOFF) && (Link_Established == true)) {
    //Udp.stop();
    Link_Established = false;
  }

  if (Link_Established == true) {
    digitalWrite(LINK_ESTABLISHED, LOW);
    // Look for a received packet.
    int packetSize = Udp.parsePacket();
    //Serial.println(packetSize);

    if (packetSize > 0) {
      Serial.print("Received packet of size ");
      Serial.print(packetSize);
      Serial.println(" bytes.");

      Serial.print("Remote IP: ");

      IPAddress remote = Udp.remoteIP();
      for (int i = 0; i < 4; i++) {
        if (i < 3) {
          Serial.print(remote[i], DEC);
          Serial.print(".");
        } else {
          Serial.println(remote[i], DEC);
        }
      }
      Serial.print("Remote port: ");
      Serial.println(Udp.remotePort());

      // Read the packet.
      int bytesRead = Udp.read(packetReceived, MAX_PACKET_LENGTH);
      Serial.print("Packet contents: ");
      Serial.write(packetReceived, bytesRead);
      Serial.println();
      conversion.Character[0] = packetReceived[4];
      conversion.Character[1] = packetReceived[5];
      Serial.println(conversion.Integer, BIN);


      bft_command_data.data = packetReceived[4];
      Serial.print(bft_command_data.valve);
      Serial.print(" ");
      Serial.print(bft_command_data.high_low);
      Serial.print(" ");
      Serial.print(bft_command_data.enable);
      Serial.print(" ");
      Serial.print(bft_command_data.adjusting_jet);
      Serial.print(" ");
      Serial.print(bft_command_data.pressure_relief);
      Serial.print(" ");
      Serial.print(bft_command_data.reset);
      Serial.print(" ");
      Serial.print(bft_command_data.stop);
      Serial.print(" ");
      Serial.println(bft_command_data.start);

      if (bft_command_data.start == 1) {
        digitalWrite(PUMP_ON, LOW);
      } else {
        digitalWrite(PUMP_ON, HIGH);
      }

      if (bft_command_data.high_low == 1) {
        digitalWrite(LOW_PRESSURE, LOW);
      } else {
        digitalWrite(LOW_PRESSURE, HIGH);
      }

      if (bft_command_data.valve == 1) {
        digitalWrite(CUTTING_HEAD_OPEN, LOW);
      } else {
        digitalWrite(CUTTING_HEAD_OPEN, HIGH);
      }
    }
  } else {
    digitalWrite(LINK_ESTABLISHED, HIGH);
  }

}

I don't use Ethernet with Arduino, but usually, begin() methods are not called in loop. I suspect this allocates a buffer every time it is called, and you are running out of memory. Check the Ethernet library docs and examples for how to (re)establish a connection.

  static bool Link_Established = false;
  if ((Ethernet.linkStatus() == LinkON) && (Link_Established == false)) {
    // Begin listening on the local port for UDP datagrams
    if (Udp.begin(localPort) == 1) {
      Link_Established = true;
      Serial.println("socket established");
    }
    Serial.println("link established");
  }
  if ((Ethernet.linkStatus() == LinkOFF) && (Link_Established == true)) {
    Udp.stop();
    Link_Established = false;
  }

I have since updated the code to this.
The begin() method is only called once per connection and returns 1 if successful.
The stop() method is called when a connection is broken to release resources.
It still won't work. :sob:

There are functions that report how much free RAM memory is available. Also check for memory violations, like writing past an array boundary.

One example

// monitor free memory (Adafruit), doesn't give correct result for ATmega32U4
//Arduino free memory .cpp
extern unsigned int __heap_start;
extern void *__brkval;

/*
   The free list structure as maintained by the
   avr-libc memory allocation routines.
*/
struct __freelist {
  size_t sz;
  struct __freelist *nx;
};

/* The head of the free list structure */
extern struct __freelist *__flp;
/* Calculates the size of the free list */
int freeListSize() {
  struct __freelist* current;
  int total = 0;
  for (current = __flp; current; current = current->nx) {
    total += 2; /* Add two bytes for the memory block's header  */
    total += (int) current->sz;
  }
  return total;
}

int freeMemory() {
  int free_memory;
  if ((int)__brkval == 0) {
    free_memory = ((int)&free_memory) - ((int)&__heap_start);
  } else {
    free_memory = ((int)&free_memory) - ((int)__brkval);
    free_memory += freeListSize();
  }
  return free_memory;
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.