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 |||||||||||||||