Freezing after sometime

I created a program to run an indoor garden that is sending and receiving data using UDP to a Raspberry Pi running a Node.js server. Everything functions great for sometime and then the Arduino will randomly freeze. The program sends data every 5 seconds, about how long the loop takes, to the PI. I also have pulses being sent between the two of them to verify connection. My original plan was to run this on a Uno, but then started seeing the device freeze after a couple of hours. I switched over to a Mega 256 and I get more hours but not sustainable communication yet.

My communication is in the form of JSON so I'm using a lot of string manipulation in my code. My first thought was a memory leak so I added in some code to show me what the SRAM is doing and I'm not seeing any change in that from loop to loop. I'm really at a loss as to what is causing the freeze.

Here is the code that communicates to the Pi. I'm guessing that's where the issue lies. I still have a lot of my debugging code in there too.

//Handles all of the communication between Server and Arduino

//||||||||||||||| Handle Incoming UDP Messages |||||||||||||||
void readUDPfromPI(){
  int packetSize = Udp.parsePacket();
  if (packetSize)
  {
    /*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());*/

    // read the packet into packetBufffer
    Udp.read(packetBuffer,UDP_TX_PACKET_MAX_SIZE);
    Serial.println("Contents:");
    Serial.println(packetBuffer);
  }
  
  String jsonString = String(packetBuffer);
  for(int i=0;i<UDP_TX_PACKET_MAX_SIZE;i++) packetBuffer[i] = 0;
  int colonPosition = jsonString.indexOf(':');
  int jsonStringLength = jsonString.length();
  String jsonValue;
  
  if (!ReceiverReady){
    jsonValue = jsonString.substring(colonPosition+2, jsonStringLength-2);
    messageFromPi(jsonString, jsonValue);
  }
  else if (ReceiverReady){
    jsonValue = jsonString.substring(colonPosition+1, jsonStringLength-1);
    if (!TimeBool){
      timeFromPi(jsonString, jsonValue);
    }
    if (TimeBool & !SettingsReceived){
      receiveSettings(jsonString, jsonValue);
    }
    if (TimeBool & SettingsReceived){
      //Find something!!!!
      jsonValue = jsonString.substring(colonPosition+2, jsonStringLength-2);
      messageFromPi(jsonString, jsonValue);
    }
  }
}

void timeFromPi(String jsonString, String jsonValue){
  if(jsonString.substring(2,6) == "Hour"){
    Hour = jsonValue.toInt();
    Serial.print("Hour ");
    Serial.println(Hour);
  }
  else if(jsonString.substring(2,5) == "Min"){
    Min = jsonValue.toInt();
    Serial.print("Min ");
    Serial.println(Min);
  }
  else if(jsonString.substring(2,5) == "Sec"){
    Sec = jsonValue.toInt();
    Serial.print("Sec ");
    Serial.println(Sec);
  }
  else if(jsonString.substring(2,5) == "Day"){
    Day = jsonValue.toInt();
    Serial.print("Day " );
    Serial.println(Day);
  }
  else if(jsonString.substring(2,7) == "Month"){
    Month = jsonValue.toInt();
    Serial.print("Month ");
    Serial.println(jsonValue);
  }
  else if(jsonString.substring(2,6) == "Year"){
    Year = jsonValue.toInt();
    Serial.print("Year ");
    Serial.println(Year);
  }
  else {
    Serial.println("******Failing to get time******");
  }
  
  if (Hour != NULL & Min != NULL & Sec != NULL & Day != NULL & Month != NULL & Year != NULL){
    TimeBool = true;
    setTime(Hour,Min,Sec,Day,Month,Year);
    LastHeartBeatSent = now();
    LastHeartBeatRec = now();
    Serial.print(hour(now()));
    Serial.print(":");
    Serial.print(minute(now()));
    Serial.print(":");
    Serial.print(second(now()));
    Serial.print(" ");
    Serial.print(month(now()));
    Serial.print(" - ");
    Serial.print(day(now()));
    Serial.print(" - ");
    Serial.println(year(now()));
    timeReceived();
  }
}

void messageFromPi(String jsonString, String jsonValue){
 if(jsonString.substring(2,4) == "PI"){
    if (jsonValue == "Ready" & !ReceiverReady){
      Serial.println("PI Ready");
      i_am_awake();
      ReceiverReady = true;
    }
    else if(jsonValue == "Pulse" & ReceiverReady){
      LastHeartBeatRec = now();
      Serial.println("******Heartbeat Received******");
    }
    else if(jsonValue == "TimeUpdate"){
      Serial.println("Time Update Coming");
      Hour = NULL;
      Min = NULL;
      Sec = NULL;
      Day = NULL;
      Month = NULL;
      Year = NULL;
      TimeBool = false;
    }
  }
  else if(jsonString != NULL){
    Serial.println(".......Fail...... ");
  } 
}

void receiveSettings(String jsonString, String jsonValue){
  if (jsonString.substring(2,8) == "hourOn") {
    LightOn[0] = jsonValue.toInt();
    PiLightOn = true;
  }
  else if(jsonString.substring(2,7) == "minOn"){
    LightOn[1] = jsonValue.toInt();
    PiLightOff = true;
  }
  else if(jsonString.substring(2,12) == "LightHours"){
    LightOnHours = jsonValue.toInt(); //Needs to be float
    PiLightHours = true;
  }
  else if(jsonString.substring(2,14) == "MoistureMin1"){
    DrySoilMoistureThres1 = jsonValue.toInt();
    PiMMin1 = true;
  }
  else if(jsonString.substring(2,14) == "MoistureMax1"){
    WetSoilMoistureThres1 = jsonValue.toInt();
    PiMMax1 = true;
  }
  else if(jsonString.substring(2,14) == "MoistureMin2"){
    DrySoilMoistureThres2 = jsonValue.toInt();
    PiMMin2 = true;
  }
  else if(jsonString.substring(2,14) == "MoistureMax2"){
    WetSoilMoistureThres2 = jsonValue.toInt();
    PiMMax2 = true;
  }
  else {
    //Serial.println("******Failing to get settings******");
  }
  
  LastHeartBeatRec = now();
 
  if (PiLightOn & PiLightOff & PiLightHours & PiMMin1 & PiMMax1 & PiMMin2 & PiMMax2){
    SettingsReceived = true;
    settingsReceived();
  }
}

//||||||||||||||| Handle Incoming UDP Messages End |||||||||||||||


//||||||||||||||| Send UDP Messages |||||||||||||||
void sendUDPMessage(String json){
  Udp.beginPacket(receiverIP, receiverPort); //start udp packet
  Udp.print(json);
  Udp.endPacket();
}

void SensorUDP(float temp, float humidity, float soilOne, float soilTwo, boolean outputStatus[6]){
  char tempArr[7];
  char humArr[7];
  char soil1Arr[7];
  char soil2Arr[7];
  char ioStatus[7];

  dtostrf(temp,6,2,tempArr);
  dtostrf(humidity,6,2,humArr);
  dtostrf(soilOne,6,2,soil1Arr);
  dtostrf(soilTwo,6,2,soil2Arr);
  
  String jsonString = "{\"Temp\":\"";
  jsonString += tempArr;
  jsonString +="\",\"Humidity\":\"";
  jsonString += humArr;
  jsonString +="\",\"soilOne\":\"";
  jsonString += soil1Arr;
  jsonString +="\",\"soilTwo\":\"";
  jsonString += soil2Arr;
  for (int i = 0; i < 6; i++){
    jsonString +="\",\"IO";
    jsonString += i;
    jsonString += "\":\"";
    jsonString += outputStatus[i];
  }
  jsonString +="\"}";
 
  sendUDPMessage(jsonString);
  
}

void i_am_awake(){
  sendUDPMessage("{\"Status\":\"Awake\"}");
  Serial.println("I am awake sent");
}

void requestSync(){
  sendUDPMessage("{\"Arduino\":\"Lost Sync\"}");
  Serial.println("Sync Request Sent");
}

void settingsReceived(){
  sendUDPMessage("{\"Settings\":\"Complete\"}");
  Serial.println("Settings complete Sent");
}

void timeReceived(){
  sendUDPMessage("{\"Time\":\"Set\"}");
  Serial.println("Time has been set");
}

void serverHeartBeat(){
  sendUDPMessage("{\"Arduino\":\"Pulse\"}");
  Serial.println("******Heartbeat Sent******");
}

void activityNotify(String activity){
  
  String jsonString = "{\"Arduino\":\"";
  jsonString += activity;
  jsonString +="\"}";
  
  Serial.println(jsonString);
  
  sendUDPMessage(jsonString);
}
//||||||||||||||| Send UDP Messages End |||||||||||||||

What shield are you using? I have tested my code on a Mega and the RPi with no fails. I do not use the String data type. It has always caused me grief in the long run. Here are my basic sketches and Linux code. I have tested these at UDP packet rates of 10 per second. Run the one appropriate for your shield for a while and see how they do, just as a test.

Ethernet shield + RPi code
http://forum.arduino.cc/index.php?topic=198259.msg1462983#msg1462983

Wifi shield + RPi code
http://forum.arduino.cc/index.php?topic=210151.msg1543236#msg1543236

I'm using the W5100 Ethernet shield. Currently the code has been up and running for 6 hours without a problem. I'm hoping that when it freezes I can see on the console what ram usage was at that time.

Warning: The ram usage may show there is memory remaining when it crashes if the String variable type causes the crash. I believe it is the way it releases memory that causes the fail. It appears to me it releases memory it shouldn't. It has been reported that this has been fixed, but every time I have heard that, it still causes crashes.

I have run my ethernet shield udp code for days without a fail as long as I use character arrays instead of Strings.

You were correct, the ram usage did not change when it crashed. I got 16 hours of continuous use before it crashed. The serial monitor doesn't have anything weird in it other than that program locks up and I cannot close it after it crashes. I also have to kill the Arudino IDE from the task manager to actually get the serial port to reconnect again. That seems really odd to me.

I have pinpointed that it is the exact time each day that the Arduino freezes. 00:29:02 to be exact. Very odd that it is always this time. I also do not start the program at the same time each day so that really makes it odd.

I tried my Mega2560/ethernet shield and wifi shield with udp every 5 seconds. So far, it went 180,000 packets and never failed. That took several days. I discontinued the test because I needed to test another sketch.

There must be an external reason it fails at that time. The Arduino does not have an internal clock, neither does the RPi.

Correct on the time. I am passing the time from my Pi code which is running on Raspbain to the Arduino every hour to keep it consistent.

I tested the RPi with C code and a wifi shield all night without a fail after over 11,000 packets, so it does not appear to be the RPi failing. Maybe it is the Node.js code? Here is the wifi shield and Linux code I use. I use the same Linux code with my ethernet shield.
http://forum.arduino.cc/index.php?topic=210151.msg1543236#msg1543236

edit: The ethernet shield code I use gets its ip from a dhcp server and calls Ethernet.maintain() to renew the ip. If you are using dhcp to get the Arduino's ip, are you renewing the lease?

The wifi shield does not require calling any function to renew its lease. It is apparently built into the firmware.