4

I have created a data logger that writes to a MicroSD on a user defined interval. The data logger also has the ability to use an xBee unit to transmit the data received to a base station.

This is a link to the code and pictures of the data logger.

I use Arduino IDE for prototyping and coding. After compiling the code, I use the temp HEX file and upload it to the boards using AVR Studio 4.

The problem I am experiencing is the data loggers will stop running after a random number of recordings. This can be days or weeks of running before the problem is experienced. This issue rarely occurs when the logger is running in local mode, but occurs often when running with an XBee unit.

A temporary fix I have found for the problem is to add delay(10); before and after the SD card writes. I do not know why this fixes the problem and would like to find a more appropriate solution.

  • Do you have any info on the memory foot-print (data, program, etc)? You are using String and that may end up with heap fragmentation. – Mikael Patel Dec 14 '15 at 20:33
2

This use of String is dangerous. You are growing and shrinking the String in a loop and hoping the memory manager prevents any holes from forming:

void clockResetcheck() {

  char clkset[] = "CLKSET.TXT";
  if  (myFile.open(clkset, O_READ)) {

    uint16_t newYr;
    uint8_t  newDay;
    uint8_t  newMo;
    uint8_t  newHr;
    uint8_t  newMin;
    uint8_t  newSec;
    char data;
    String temp;
    int place = 0;

    while ((data = myFile.read()) > 0) {

    if (data == '/' || data == ':' || data == ',') {
      if (place == 0) {
        newDay = temp.toInt();
        temp = "";
      }
      if (place == 1) {
      newMo = temp.toInt();
      temp = "";
      }
      if (place == 2) {
        newYr = temp.toInt();
        temp = "";
      }
      if (place == 3) {
        newHr = temp.toInt();
        temp = "";
      }
      if (place == 4) {
        newMin = temp.toInt();
        temp = "";
      }
      if (place == 5) {
        newSec = temp.toInt();
        temp = "";
      }
      place++;
      if (place == 6) {
        myFile.close();
        break;
      }
    }
    else {
      temp = temp + data;
    }
  }
...

The line

temp = temp + data

is a danger flag. This sort of concatenation is going to reallocate the buffer used by String to make it fit the result. The reallocate will leave behind a hole with the previous smaller string.

String has logic to reuse the buffer if possible. So if you start big, it should not have to reallocate. Something like:

String temp("12345678");  // allocates the buffer at largest needed size
temp = ""; // clear out

That is a less likely to fragment memory. You have a few other concatenates in code that are similar danger.

The best advice to long running programs I ever received:

Stay off the heap.

You are using String inside functions. That means that buffers are allocated and freed again and again.

A better pattern is to remove all the local String's in functions. Instead use one global String as a temp buffer.

String g_temp("                        ");
void function1() {
   g_temp = "";
   g_temp += char
}
void functionB() {
   g_temp = "";
   // do stuff with g_temp
}

With this pattern, the allocate happens once when the program starts. If the size is setup large enough, if will never need to reallocate. This means your high water mark for memory use is established at the time the program starts. You don't have to monitor for a week to see if some corner case will run out of memory.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.