Why is my Uno+Ethernet shield hanging / requiring power cycling?

Hi everyone! In an installation I'm using an Arduino Uno with an Ethernet shield as a physical network-attached proxy between a computer (Mac Mini) and a secondary Arduino. The Uno needs to be power cycled every so many days (~ 1 week) and I'm not sure what the issue might be.

The Uno receives UDP packets from the Mac Mini and passes it on via serial (SoftSerial) to the secondary Arduino. Vice versa too: receives serial from the secondary Arduino and passes it to the Mac Mini via UDP. SoftSerial lib is being used via pins 6 and 7. The Uno is powered by a 9V/1A power adapter through the barrel jack.

When testing I thought I had a stable solution but the Uno first needed to be power cycled after a month of use, after that it appears as though it needs to be power cycled every week. There's not really much going on in the sketch yet it appears to become unresponsive and needs to be power cycled to work again for a few days. I haven't worked with the Ethernet shield before, is it prone to particular oddities when in use?

I'm open for tips to troubleshoot this, much thanks! If you need to see the sketch itself, let me know.

Can You try some debugging printouts telling where in the loop the sketch is, what it is doing, waiting for etc.? The last printout might tell something. Attach Your code, using code brackets. Is there any counter can wrap around, like from +32767 to -32768, or similiar, that tricks the code?

Thanks for the reply! Sorry I missed it, forgot alerts.
Doing debugging things is a bit of a challenge since the device is in production already. But if I won’t be able to ascertain what might help I’ll be going over there soon anyway…
As for counters, no such thing. The sketch essentially just converts UDP packets to serial and vice versa. But maybe you see something odd in the sketch anyway?

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

SoftwareSerial ESPserial(6, 7); // RX | TX

#define DEBUG false

/*
**************************************************************************************
  ** Serial protocol **
  5 bytes -> [start_byte] [command] [identifier] [value] [end_byte]
**************************************************************************************
*/
// Start/Stop byte
#define START_BYTE            93
#define END_BYTE              84


/*
**************************************************************************************
  ** ETHERNET AND UDP **
**************************************************************************************
*/
// 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(192, 168, 1, 200); // IP address @Singletons
IPAddress ip(192, 168, 0, 200); // IP address on location

unsigned int localPort = 8888;      // local port to listen on

// buffers for receiving and sending data
char packetBuffer[UDP_TX_PACKET_MAX_SIZE];  // buffer to hold incoming packet,
char ReplyBuffer[] = "acknowledged";        // a string to send back
char ValueBuffer[] = "got val  ";       // a string to send back

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

bool ledPinState = false;

IPAddress remoteIP = { 192, 168, 0, 150 }; // will be populated as soon as we receive a message
uint16_t remotePort = 7777;
bool remoteUDPSettingsInitted = false;


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

  Ethernet.init(10);  // Most Arduino shields
  // start the Ethernet
  Ethernet.begin(mac, ip);

  // disable SD card if one in the slot
  pinMode(4, OUTPUT);
  digitalWrite(4, HIGH);

  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  // Check for Ethernet hardware present
  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.");
  }

  // start UDP
  Udp.begin(localPort);

  ESPserial.begin(38400);

  pinMode(LED_BUILTIN, OUTPUT);
}


void loop() {
  udpToSoftSerial();
  softSerialToUdp();

  delay(1000 / 50);
}


void udpToSoftSerial() {
  // if there's data available, read a packet
  int packetSize = Udp.parsePacket();
  if (packetSize) {
    //        Serial.print("Received packet of size ");
    //        Serial.println(packetSize);
    remoteIP = Udp.remoteIP();
    remotePort = Udp.remotePort();

#if DEBUG == true
    Serial.print("From ");
    for (int i = 0; i < 4; i++) {
      Serial.print(remoteIP[i], DEC);
      if (i < 3) {
        Serial.print(".");
      }
    }
    Serial.print(", port ");
    Serial.println(remotePort);
#endif


    remoteUDPSettingsInitted = true;

    // read the packet into packetBufffer
    memset(packetBuffer, 0, sizeof packetBuffer);
    Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
    //    Serial.print("Contents: ");
    //    Serial.println(packetBuffer);

#if DEBUG == true
    if ((String)packetBuffer == "#1!") {
      // send serial 1
      Serial.println("send a 1");
      Serial.write(1);
      ESPserial.write((byte)1);
    }
    // DEBUG
    if ((String)packetBuffer == "#0!") {
      // send serial 0
      Serial.println("send a 0");
      Serial.write(0);
      ESPserial.write((byte)8);
    }
#endif

    // WE ASSUME THAT 5 BYTES IS THE CORRECT PACKET SIZE
    if (packetSize == 5) {
      // just a double-check: is the packet consistency delineated by our start/end byte?
      if ((uint8_t)packetBuffer[0] == START_BYTE && (uint8_t)packetBuffer[4] == END_BYTE) {
        //        Serial.println("correct packet consistency");

        // DEBUG feedback
        //        Serial.write((uint8_t)packetBuffer[0]);
        //        Serial.write((uint8_t)packetBuffer[1]);
        //        Serial.write((uint8_t)packetBuffer[2]);
        //        Serial.write((uint8_t)packetBuffer[3]);
        //        Serial.write((uint8_t)packetBuffer[4]);

        // To the arduino
        ESPserial.write((uint8_t)packetBuffer[0]);
        ESPserial.write((uint8_t)packetBuffer[1]);
        ESPserial.write((uint8_t)packetBuffer[2]);
        ESPserial.write((uint8_t)packetBuffer[3]);
        ESPserial.write((uint8_t)packetBuffer[4]);
      }
    }

#if DEBUG == true
    if (packetSize == 4) {
      if (packetBuffer[0] == '#' && packetBuffer[3] == '!') {
        Serial.println("packetsize 4 -> start/end bytes are correct");
        if (packetBuffer[1] == 'z') {
          Serial.print("command is 'z' >> char: ");
          Serial.print((char)packetBuffer[2]);
          Serial.print("\t, uint8_t: ");
          Serial.println((uint8_t)packetBuffer[2]);
        }
      }
    }
#endif
    // 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();
  }
}

void softSerialToUdp() {
  if (ESPserial.available() >= 4 ) {
    if ((byte)ESPserial.peek() == START_BYTE) {

      // do blinky blinky activity feedback
      ledPinState = !ledPinState;
      digitalWrite(LED_BUILTIN, ledPinState);

      byte _buffer[4];
      ESPserial.readBytes(_buffer, 4);

      if (_buffer[0] == START_BYTE && _buffer[3] == END_BYTE) {
        // now form and send UDP packet back to Unity
        if (remoteUDPSettingsInitted) {
          Udp.beginPacket(remoteIP, remotePort);
          byte buf[] = { START_BYTE, _buffer[1], _buffer[2], END_BYTE };
          Udp.write(buf, 4); // write buffer to UDP
          Udp.endPacket();
        }
      }
    } else {
      // if first item wasn't START_BYTE then bump it out
      ESPserial.read();
    }

    // while (ESPserial.available() > 0) {
    //   ESPserial.read();
    // }
  }
}

In production or not, You ought to assume that this trouble likely will appear in the units being sold/used, so cracking the nut is neccessary.

Not being familiar with SD and Ethernet stuff I can't any precise advice.

I saw this code

  // disable SD card if one in the slot
  pinMode(4, OUTPUT);
  digitalWrite(4, HIGH);

I suggest this:

  // disable SD card if one in the slot
  digitalWrite(4, HIGH);//      Make sure output will be high when declared/set as output.
  pinMode(4, OUTPUT);

However I can't say whether this causes any trouble after several days..

Check that no unexpected high temperature anywhere. Check for error messages from Ethernet- and SD- devices. Any glitch, electrical noice etc. might trick the communication. Check for lost messages, time overrun etc..

Thanks for the suggestion for disabling the sd card slot. I’m not sure what changing the order of those two lines does internally though, but can’t help trying.
You’re right that ultimately I’ll have to do more measuring / logging to be able to really know what’s going on. Sometimes specific hardware is known to have issues with some "oh yeah, you should always do ", I was hoping that some obvious gotchas might emerge here. If not, it’s down to getting into the thick of it.

Thanks for the help!