Crashing during a basic timing loop.

I am trying to make a basic automation sketch, but for some reason the Arduino crashes when it hits 98 iterations. I am positive that my code is not optimized, but it should be stable. Right now I just have it performing the timing loop and sending the count to the Serial Monitor.

Model: Arduino Mega 2560 R3
Source:

int FAN_INTERVAL = 30;
int FAN_DURATION = 5;
int LIGHT_INTERVAL = 200;
int LIGHT_DURATION = 50;
int FIcount = 0;
int FDcount = 0;
int LIcount = 0;
int LDcount = 0;
boolean lstatus = false;
boolean fstatus = false;
String output_str = "";
String foutput_str = "";
void setup(){
  Serial.begin(19200);
  pinMode(13,OUTPUT); // we flash the LED each second
}

void  loop(){
  String fresult = CheckFans(); // Check Fan status
  String lresult = CheckLights(); // Check light status
  Serial.println(fresult + lresult);
  delay(1000); 
}

String CheckFans(){
foutput_str = "";
if (FIcount < FAN_INTERVAL && fstatus == false)
{
  FIcount++;
  foutput_str = foutput_str + "| FIcount: " + FIcount + " ";
}
else if (FIcount == FAN_INTERVAL && fstatus == false){
  fstatus = true;
  FIcount = 0;
  foutput_str = "| Fan On ";
}
else if (FDcount == FAN_DURATION && fstatus == true){
  fstatus = false; 
  FDcount = 0;
  foutput_str = "| Fan Off ";
}
else if(FDcount < FAN_DURATION && fstatus == true){
  FDcount++; 
  foutput_str = foutput_str + "| FDcount: " + FDcount + " ";
}
return foutput_str;
}

String CheckLights(){
output_str = "";
if (LIcount < LIGHT_INTERVAL && lstatus == false)
{
  LIcount++;
  output_str = output_str + "| LIcount: " + LIcount + " ";
}
else if (LIcount == LIGHT_INTERVAL && lstatus == false){
  lstatus = true;
  LIcount = 0;
  output_str = "| Light On ";
}
else if (LDcount == LIGHT_DURATION && lstatus == true){
  lstatus = false; 
  LDcount = 0;
  output_str = "| Light Off ";
}
else if(LDcount < LIGHT_DURATION && lstatus == true){
  LDcount++; 
  output_str = output_str + "| LDcount: " + LDcount + " ";
}
return output_str;
}

Expected Serial Output:

| Fan On | LIcount: 34 
| FDcount: 1 | LIcount: 35 
| FDcount: 2 | LIcount: 36 
| FDcount: 3 | LIcount: 37 
| FDcount: 4 | LIcount: 38 
| FDcount: 5 | LIcount: 39 
| Fan Off | LIcount: 40 
| FIcount: 1 | LIcount: 41 
| FIcount: 2 | LIcount: 42 
| FIcount: 3 | LIcount: 43 
... etc over and over without stopping.

However the 98th iteration, it just stops. I added a serial output that just displays a smiley emote every loop and it goes to 100 iterations before it outputs a couple random extended characters then stops.

Ok, so I next installed this same code on my Teensy++ 2.0 I had lying around and it works with no issues. Is there something I am missing?

String CheckFans(){

My money is on memory fragmentation :wink:

me too, try using an array where every element is a pointer to String.

but then i think you'll have problem with ram overflow during CheckLights()

Hi

me too, try using an array where every element is a pointer to String.

Not sure how that would help ?

Duane B

Lose the String class.

DuaneB:
Hi

me too, try using an array where every element is a pointer to String.

Not sure how that would help ?

Duane B

it is because with this code the string is in a single big array, and array have to use contiguos byte in ram, but because fragmentation you don't have so much space in ram withouth some other variable in the way.

but breaking your big array int smaller array you have more possibilities to find a place to put it.

Lose the String class

?? i don't understand, but if it is because i've said to use the String class, i know the char array is better, but also harder, try to explain double pointer to someone who maybe don't even know what is a pointer...

lesto:
i know the char array is better ...

QFT.

lesto:
try to explain double pointer to someone who maybe don't even know what is a pointer...

Do you want it to work, or be easy to code?

Anyway, you rarely need to use double pointers. Maybe a reference to a pointer.

ah, sorri, using the array of String class, not an array of pointer to String class (they do the malloc/free inside), i midex with the sentence:
an array of pointer to the array of char (c ansi string) but as you can read it is not easy to understand as "use an array of String, one for every row")

ps. i want it to work in the easyer way, then the he can complicate his code if he like to get crazy :slight_smile:

Have not tested this as arduino tied up doing RTC stuff but I have moved strings to PROGMEM and use combination of strcpy, strcat & itoa to construct message. I

#include <avr/pgmspace.h>

// Default Fan Strings
prog_uchar fanSting00[] PROGMEM = {
    "| FIcount: \0"};
prog_uchar fanSting01[] PROGMEM = {
    " | Fan On \0"};
prog_uchar fanSting02[] PROGMEM = {
    " | Fan Off \0"};
prog_uchar fanSting03[] PROGMEM = {
    " | FDcount: \0"};
//Month String Pointer Table
prog_uchar *fanSting_table[] PROGMEM ={
    fanSting00,
    fanSting01,
    fanSting02,
    fanSting03,
};

// Default Light Strings
prog_uchar lightSting00[] PROGMEM = {
    " | LIcount: \0"};
prog_uchar lightSting01[] PROGMEM = {
    " | Light On \0"};
prog_uchar lightSting02[] PROGMEM = {
    " | Light Off \0"};
prog_uchar lightSting03[] PROGMEM = {
    " | LDcount: \0"};
//Month String Pointer Table
prog_uchar *lightSting_table[] PROGMEM ={
    lightSting00,
    lightSting01,
    lightSting02,
    lightSting03,
};

char chrBuffer[101];

int FAN_INTERVAL = 30;
int FAN_DURATION = 5;
int LIGHT_INTERVAL = 200;
int LIGHT_DURATION = 50;
int FIcount = 0;
int FDcount = 0;
int LIcount = 0;
int LDcount = 0;
boolean lstatus = false;
boolean fstatus = false;
String output_str = "";
String foutput_str = "";
void setup(){
    Serial.begin(19200);
    pinMode(13,OUTPUT); // we flash the LED each second
}

void  loop(){

    //Need to clear old messages from string buffer
    for (int x=0; x<101; x++){
        chrBuffer[x]=0;
    }

    CheckFans(); // Check Fan status
    CheckLights(); // Check light status
    Serial.println(chrBuffer);
    delay(1000); 
}

void CheckFans(){
    if (FIcount < FAN_INTERVAL && fstatus == false)
    {
        FIcount++;
        strlcpy_P(chrBuffer, (char*)pgm_read_word(&(fanSting_table[0])), sizeof(chrBuffer));
        itoa(FIcount,chrBuffer+strlen(chrBuffer),10);
    }
    else if (FIcount == FAN_INTERVAL && fstatus == false){
        fstatus = true;
        FIcount = 0;
        strlcat_P(chrBuffer, (char*)pgm_read_word(&(fanSting_table[1])), sizeof(chrBuffer));
    }
    else if (FDcount == FAN_DURATION && fstatus == true){
        fstatus = false; 
        FDcount = 0;
        strlcat_P(chrBuffer, (char*)pgm_read_word(&(fanSting_table[2])), sizeof(chrBuffer));
    }
    else if(FDcount < FAN_DURATION && fstatus == true){
        FDcount++; 
        strlcat_P(chrBuffer, (char*)pgm_read_word(&(fanSting_table[3])), sizeof(chrBuffer));
        itoa(FDcount,chrBuffer+strlen(chrBuffer),10);
    }
}

void CheckLights(){
    output_str = "";
    if (LIcount < LIGHT_INTERVAL && lstatus == false)
    {
        LIcount++;
        strlcat_P(chrBuffer, (char*)pgm_read_word(&(lightSting_table[0])), sizeof(chrBuffer));
        itoa(LIcount,chrBuffer+strlen(chrBuffer),10);
    }
    else if (LIcount == LIGHT_INTERVAL && lstatus == false){
        lstatus = true;
        LIcount = 0;
        strlcat_P(chrBuffer, (char*)pgm_read_word(&(lightSting_table[1])), sizeof(chrBuffer));
    }
    else if (LDcount == LIGHT_DURATION && lstatus == true){
        lstatus = false; 
        LDcount = 0;
        strlcat_P(chrBuffer, (char*)pgm_read_word(&(lightSting_table[2])), sizeof(chrBuffer));
    }
    else if(LDcount < LIGHT_DURATION && lstatus == true){
        LDcount++; 
        strlcat_P(chrBuffer, (char*)pgm_read_word(&(lightSting_table[3])), sizeof(chrBuffer));
        itoa(LDcount,chrBuffer+strlen(chrBuffer),10);
    }
}

That fixed it. I really need to learn how to properly deal with string arrays.

Thanks for the advice. I appreciate the information everyone has given me.

madz:
That fixed it. I really need to learn how to properly deal with string arrays.

Thanks for the advice. I appreciate the information everyone has given me.

Up until 3 days ago I had no idea about constructing string arrays with strcpy & strcat and a week previous nothing about PROGMEM strings. Glad my new found knowledge was of help.

My programming skills are generally geared towards web based applications, so I don't usually have to worry about how strings work. This will definitely be a learning experience :smiley:

you'll learn a lot of what is going under the scene. And this will help you to optimize your code.