Question of Logic (probably...)

Dear,

Got some problems in my recent code modification. The program hang after few call of a particular function and it look like Memory overflow or memory full error. But, this should not happen as I use local Variables.

Sometimes, the program may let me call 4-5 times the functions, other times, hang in the first call.

Symptoms : Everything freeze! not more processing nor LCD refresh.

This function is used to build a data string to be sent over Serial Port. The inputs are taken from an Array of String (Sensors Name) and an Array of Double (Data Value). The string is build in a "CSV" style to be received from the computer or my Internet Gateway.

I added lot of communications over serial to identify where the program hang and it's ALWAYS in this function. Mostly in the loop that build the string from the Sensors array. I suspect a memory full error but I don't understand why. Maybe I don't use correctly the String variables...

Any help, comment or suggestions would be really appreciated!.

Function in problem : BuildSensorString()

thanks!!

Mathieu

CODE (I removed not important code):

double Sensors[50];
String SENSORS_POINTNAME[NB_SENSORS] = {"TEMP1",
"TEMP2",
"TEMP3",
"TEMP4",
"TEMP5",
"TEMP6",
"TEMP7",
"TEMP8",
"LIGHTSENSOR",
"FLOWSENSOR",
"MAINVOLTAGESENSOR",
"MAINWATERVALVE",
"SECONDWATERVALVE",
"RELAY1",
"RELAY2",
"RELAY3",
"RELAY4",
"RELAY5",
"RELAY6",
"RELAY7",
"RELAY8",
"ALARM",
"STATUS",
"WATERPUMPAC"};

// BUILD a CSV Style string to send over Serial
// Format : $[String SensorName1];[String SensorValue1];[String SensorName2];[String SensorValue2]...#[CheckSum]#
String BuildSensorsString(){
Serial.print("Building Sensors DATASTRING.");
Buffer += '$';
for (int IDX = 0; IDX < NB_SENSORS; IDX ++) {
Serial.print('|');
Buffer = Buffer + SENSORS_POINTNAME[IDX] + ';' + DoubleToStr(Sensors[IDX],100);
Serial.print('-');
if (IDX < NB_SENSORS-1) Buffer = Buffer + ';';
Serial.print('.');
}
Buffer = Buffer + '#';
Serial.println(" DONE!");
Serial.print("Calculating Checksum... ");
Buffer = Buffer + String(Checksum(Buffer),DEC);
Buffer = Buffer + '#';
Serial.println("DONE!");
return Buffer;
}

// Function got from a forum to convert DOUBLE to STRING.
String DoubleToStr( double val, unsigned int precision){
// prints val with number of decimal places determine by precision
// NOTE: precision is 1 followed by the number of zeros for the desired number of decimial places
// example: printDouble( 3.1415, 100); // prints 3.14 (two decimal places)

//Serial1.print (int(val)); //prints the int part
String tmpStr = String(int(val));
if (precision > 0) {
//Serial1.print("."); // print the decimal point
tmpStr += ".";
unsigned int frac;
if(val >= 0)
frac = (val - int(val)) * precision;
else
frac = (int(val)- val ) * precision;
//Serial1.print(frac,DEC) ;
tmpStr += String(frac,DEC);
}
return tmpStr;
}

//Used to calculate a simple checksum for the string
byte Checksum(String tmpString) {
byte _CS = 0;
for (int idx=0; idx<tmpString.length(); idx++) {
_CS += tmpString[idx];
}
return _CS;
}

Without full code it is difficult to tell for sure, but it looks like you are probably exhausting your RAM. If you're using an ATmega328, you only have 2k. Strings consume that quickly.

Way too quickly when you do string1=string1+"#" or some other "innocent" operations that don't seem to "cost much memory". Stop using String class and use the good old c-strings and sprintf:

Yes I probably should use c-String. I came back to C after years, i don't remember all the concepts. I used the easy way as Strings was supported with all functions and features.

I use an arduino MEGA1280, I tought that I would have plenty of RAM as I don't use much in the rest of the code. This string shouldn't be more that 500 characters in size and I use at most 1k additionnal ram. I suppose that Serial communication need somes for buffering but I should be far less that the 8k limit.

It's look like the "Buffer" variable isn't flushed after function exit and add up in ram. But, in some case, I don't even goes thru the function one time. That is odd as I may let the program run for 2-3 days without problem but as soon as I start this function, it may hang. My memory leak doesn't come from the rest of the code. This is probably a lack of experience of myself with low level comprehension of C.

I will try do change to Char Array and look at sprintf that I didn't knew.

Thanks for this hint.

Mathieu

I saw plenty of problems surrounding string class. I don't know how garbage is collected but not well, not well. Atmega2560 has 8 K ram so if you run the look a few times and each time do string = string +'stuff". The original spaces would not fit and new spaces would have to be allocated. With a leaky bucket, you're heading towards the wall.

Liudr : Wow, Thanks for the link of your blog! How can I have lived without this!!! ;p. So much lines of code spent to only format strings due to my lack of C experience!.

Thanks a LOT for this, I will look for further informations and adjust my code. I will keep informed of any success... or not.