Problems with SD.h - strange output

Hello,
I'm trying to write some logs to an SD card using the example provided with the SD.h library. After few writes the arduino seems freezed.

The output that I receive is :

Initializing SD card...initialization done.
Writing to test.txt...done.
test.txt:
testing 1, 2, 3.
testing 1, 2, 3.
082901
082902
082902100 xxxxxxxxxx476xxxxxxxxxxxxxxxxx100 xxxxxx
082903
082904
082904100 xxxxxxxxxx482xxxxxxxxxxxxxxxxx100 xxxxxx
082905
082906
082906100 xxxxxxxxxx480xxxxxxxxxxxxxxxxx100 xxxxxx

You should post your code. It is difficult to tell what output you wanted, and what you didn't.

Is that output ok except it freezes at the last line?

edit: You might want to specify what device this is. Is it just an SD shield, or an ethernet shield?

:cold_sweat: mhmhm I forgot to copy and paste the details of my platform/devices.

In any case is an Arduino IDE in OSX, Arduino Ethernet Shield with SD and Ethernet, Arduino UNO SMD version and the libraries used are SD.h, TimeAlarms.h, Time.h, SPI.h

The code is:

#include <SD.h>

#include <TimeAlarms.h>
#include <Time.h>

#include <SPI.h>         

String repeatString = "x";
String dataString;

int sensorPin = A0;

String filenameLog = "";

const int chipSelect = 4;

File myFile;

void setup() {
  Serial.begin(9600);

// From http://arduino.cc/en/Tutorial/ReadWrite
Serial.print("Initializing SD card...");
  // On the Ethernet Shield, CS is pin 4. It's set as an output by default.
  // Note that even if it's not used as the CS pin, the hardware SS pin
  // (10 on most Arduino boards, 53 on the Mega) must be left as an output
  // or the SD library functions will not work.
   pinMode(10, OUTPUT);
//  root.close();
//  file.close();

if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");

// open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  myFile = SD.open("test.txt", FILE_WRITE);
 
  // if the file opened okay, write to it:
  if (myFile) {
    Serial.print("Writing to test.txt...");
    myFile.println("testing 1, 2, 3.");
    // close the file:
    myFile.close();
    Serial.println("done.");
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }
 
  // re-open the file for reading:
  myFile = SD.open("test.txt");
  if (myFile) {
    Serial.println("test.txt:");
   
    // read from the file until there's nothing else in it:
    while (myFile.available()) {
        Serial.write(myFile.read());
    }
    // close the file:
    myFile.close();
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }

  
  syncDateTime();

  Alarm.timerRepeat(1, printTimer);            // timer for every 5 seconds    
  Alarm.timerRepeat(2, setActuators);            // timer for every 2 seconds    
  Alarm.timerRepeat(2, readSensors);            // timer for every 5 seconds    

  Alarm.timerRepeat(20, sendDataHub);            // timer for every 20 seconds

  Alarm.alarmRepeat(8,30,0, syncDateTime);  // 8:30am every day
  Alarm.alarmRepeat(20,30,0, syncDateTime);  // 8:30am every day
  
}

void loop() {
  Alarm.delay(100);
}

void lsMemoryCard() {
}

void formatMemoryCard() {
}

String getFilename() {
  String tmpValue = "";
  
  tmpValue = getDigits(month());
  tmpValue += getDigits(day());
  tmpValue += getDigits(hour());
  tmpValue += getDigits(minute());
  tmpValue += ".";
  
  if (second() < 30) {
   tmpValue += "000";
  } else {
   tmpValue += "001";
  }
  
 return tmpValue;
}

void printTimer() {
  Serial.println(getTime());
}

void setActuators() {

}

void readSensors() {
  String valueSD = "";
  String sensorValue = "";

  sensorValue = (String) analogRead(sensorPin);
  
  valueSD += setString(getTime(), 6); // DateTime
  valueSD += setString("100 ", 14); // id sensor
  valueSD += setString(sensorValue, 20); // Value sensor
  valueSD += setString("100 ", 10); // Future usage

  writeSD((String) valueSD);
}

void sendDataHub() {

}

String readFile(String fileSend) {
 String tmpString = "";
 
 return tmpString;
}

void deleteFile(String fileDelete) {
 // Delete the file
}

boolean sendData(String valueRecords){
 // Should be sent the data and the CRC of the data
}

void sendRecords(String fileSend) {
 String dataFile = readFile(fileSend); // // Read the file content
 
 if (sendData(dataFile) == true) {
  deleteFile(fileSend);
 }
}

String listFileSend() {
 // Get the file that shold be read and send to the hub
 
}

String setString(String Value, int length) {
  String tmpValue = "";
  
  tmpValue = Value + repeat(repeatString, length - Value.length());
  
  return tmpValue;
}

String repeat(String value, int nValues) {
  String tmpValue = "";
  int iCount = 0;
  
  for (iCount = 0; iCount < nValues; iCount++) {
   tmpValue += value;
  }

 return tmpValue;
}
  
void dumpFile (String filename) {

}

void writeSD(String dataString) {
  Serial.println(dataString);

  dumpFile("D.TXT");
  
}
  
String getTime() {
  String tmpValue = "";
  
  tmpValue = getDigits(hour());
  tmpValue += getDigits(minute());
  tmpValue += getDigits(second());
  
 return tmpValue;
}

String getDigits(int digits)
{
  if(digits < 10) {
   return "0" + ( (String) digits);
  } else {
     return (String) digits;
  }
}

void syncDateTime() {
  setTime(8,29,0,1,1,11); // set time to Saturday 8:29:00am Jan 1 2011

}

void printDirectory() {
}

In your setup routine, you are enabling the w5100 SPI. That will cause garbage on the SPI bus.

   // after this
   pinMode(10, OUTPUT);
   // disable w5100 SPI before setting up the SD
   digitalWrite(10,HIGH);

  // rest of your setup

Does that help?

No, seems not working in the same way.

This is the output:

Initializing SD card...initialization done.
Writing to test.txt...done.
test.txt:
testing 1, 2, 3.
testing 1, 2, 3.
testing 1, 2, 3.
testing 1, 2, 3.
testing 1, 2, 3.
testing 1, 2, 3.
testing 1, 2, 3.
082901
082902
082902100 xxxxxxxxxx474xxxxxxxxxxxxxxxxx100 xxxxxx
082903
082904
082904100 xxxxxxxxxx475xxxxxxxxxxxxxxxxx100 xxxxxx
082905
082906
082906100 xxxxxxxxxx472xxxxxxxxxxxxxxxxx100 xxxxxx
+.
+2
0829

I tried to post before but the last three lines where with a special character like [A]

Did you notice the extra lines are the time from your clock? You initialized the clock at 082900, and those are incrementing from there, with additional characters at the 2 second alarm time.

Are you certain you are not running out of SRAM?

SurferTim:
Did you notice the extra lines are the time from your clock? You initialized the clock at 082900, and those are incrementing from there, with additional characters at the 2 second alarm time.

Are you certain you are not running out of SRAM?

The line :

Alarm.timerRepeat(1, printTimer); // timer for every 5 seconds

Setup the print of the time every second. So is correct.

The additional lines are the output from the function that is reading from sensors and writing in the Serial.

I don't know how to check if I'm out of RAM, How can I check it ? For sure the code compiled is close to 21 Kb.

Luca

That looks like a problem with the clock, not the SD. The SD part of the output looks ok. This is the SD output:

Initializing SD card...initialization done.
Writing to test.txt...done.
test.txt:
testing 1, 2, 3.
testing 1, 2, 3.
testing 1, 2, 3.
testing 1, 2, 3.
testing 1, 2, 3.
testing 1, 2, 3.
testing 1, 2, 3.

The rest is the clock.

I will try to use an Arduino Mega and check if I have the same error. I will let you know.

Arduino Mega has same probs, I tried to check the memory available and I discovered that the function setString (or it seems) after a while crash the board. It happen that the memory is constant and after a while has more free memory and then stops.

I'm quite lost.

This code that is calling testSensor function every 5 secs it crashes the arduino.

The function itself seems correct, what is it the problem? The code compiled is close to 14 K

#include <MemoryFree.h>

#include <SD.h>

#include <TimeAlarms.h>
#include <Time.h>

#include <SPI.h>         

String repeatString = "x";
String dataString;

int sensorPin = A0;

String filenameLog = "";

const int chipSelect = 4;

File myFile;

void setup() {
  Serial.begin(9600);

// From http://arduino.cc/en/Tutorial/ReadWrite
Serial.print("Initializing SD card...");
  // On the Ethernet Shield, CS is pin 4. It's set as an output by default.
  // Note that even if it's not used as the CS pin, the hardware SS pin
  // (10 on most Arduino boards, 53 on the Mega) must be left as an output
  // or the SD library functions will not work.
  
 /*
   pinMode(10, OUTPUT);
//  root.close();
//  file.close();
 digitalWrite(10,HIGH);

if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");

// open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  myFile = SD.open("test.txt", FILE_WRITE);
 
  // if the file opened okay, write to it:
  if (myFile) {
    Serial.print("Writing to test.txt...");
    myFile.println("testing 1, 2, 3.");
    // close the file:
    myFile.close();
    Serial.println("done.");
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }
 
  // re-open the file for reading:
  myFile = SD.open("test.txt");
  if (myFile) {
    Serial.println("test.txt:");
   
    // read from the file until there's nothing else in it:
    while (myFile.available()) {
        Serial.write(myFile.read());
    }
    // close the file:
    myFile.close();
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }
*/
  syncDateTime();

  Alarm.timerRepeat(1, printTimer);            // timer for every 5 seconds    
  Alarm.timerRepeat(5, testSensor);            // timer for every 5 seconds    
//  Alarm.timerRepeat(2, setActuators);            // timer for every 2 seconds    
//  Alarm.timerRepeat(2, readSensors);            // timer for every 5 seconds    

//  Alarm.timerRepeat(20, sendDataHub);            // timer for every 20 seconds

//  Alarm.alarmRepeat(8,30,0, syncDateTime);  // 8:30am every day
//  Alarm.alarmRepeat(20,30,0, syncDateTime);  // 8:30am every day
  
}

void testSensor() {
  String valueSD;
  String sensorValue;

  sensorValue = "";
  valueSD = "";
//  sensorValue = (String) analogRead(sensorPin);
  sensorValue = "ciaooo";
  
  valueSD += "123456"; // DateTime
//  valueSD += setString(getTime(), 6); // DateTime
  valueSD += "1234567890"; // id sensor
  valueSD += sensorValue; // Value sensor
  valueSD += "1234567890"; // Future usage
}

void readSensors() {
  String valueSD = "";
  String sensorValue = "";

//  sensorValue = (String) analogRead(sensorPin);
  sensorValue = "ciaooo";
  
//  valueSD += "123456"; // DateTime
//  valueSD += setString(getTime(), 6); // DateTime
  valueSD += "1234567890"; // id sensor
  valueSD += sensorValue; // Value sensor
  valueSD += "1234567890"; // Future usage

//  valueSD += setString("100 ", 14); // id sensor
//  valueSD += setString(sensorValue, 20); // Value sensor
//  valueSD += setString("100 ", 10); // Future usage

//  writeSD((String) valueSD);
}

  
void dumpFile (String filename) {

}

void writeSD(String dataString) {
  Serial.println(dataString);

  dumpFile("D.TXT");
  
}

void loop() {
  Alarm.delay(100);
}

void lsMemoryCard() {
}

void formatMemoryCard() {
}

String getFilename() {
  String tmpValue = "";
  
  tmpValue = getDigits(month());
  tmpValue += getDigits(day());
  tmpValue += getDigits(hour());
  tmpValue += getDigits(minute());
  tmpValue += ".";
  
  if (second() < 30) {
   tmpValue += "000";
  } else {
   tmpValue += "001";
  }
  
 return tmpValue;
}

void printTimer() {
  String valueSD = "";
  
  Serial.println(getTime());
  Serial.print("freeMemory()=");
  Serial.println(freeMemory());


//  valueSD += setString(getTime(), 6); // DateTime
//  valueSD += setString(getTime(), 6); // id sensor
  valueSD += getTime(); // id sensor
//  valueSD += repeat("H", 10); 
  
  
//  valueSD += "aaa"; // Value sensor
//  valueSD += "1234567890"; // Future usage

  Serial.println(valueSD); // DateTime

}

void setActuators() {

}


void sendDataHub() {

}

String readFile(String fileSend) {
 String tmpString = "";
 
 return tmpString;
}

void deleteFile(String fileDelete) {
 // Delete the file
}

boolean sendData(String valueRecords){
 // Should be sent the data and the CRC of the data
}

void sendRecords(String fileSend) {
 String dataFile = readFile(fileSend); // // Read the file content
 
 if (sendData(dataFile) == true) {
  deleteFile(fileSend);
 }
}

String listFileSend() {
 // Get the file that shold be read and send to the hub
 
}

String setString(String Value, int length) {
  String tmpValue = "";
  
  tmpValue = Value + repeat(repeatString, length - Value.length() );
  
  return tmpValue;
}

String repeat(String value, int nValues) {
  String tmpValue = "";
  int iCount = 0;
  
  for (iCount = 0; iCount < nValues; iCount++) {
   tmpValue += value;
  }

 return tmpValue;
}
  
String getTime() {
  String tmpValue = "";
  
  tmpValue = getDigits(hour());
  tmpValue += getDigits(minute());
  tmpValue += getDigits(second());
  
 return tmpValue;
}

String getDigits(int digits)
{
  if(digits < 10) {
   return "0" + ( (String) digits);
  } else {
     return (String) digits;
  }
}

void syncDateTime() {
  setTime(8,29,0,1,1,11); // set time to Saturday 8:29:00am Jan 1 2011

}

void printDirectory() {
}

Are you running out of SRAM? You have included the MemoryFree.h file, but I don't see where you check it.
I would put these lines of code at the end of your setup() function to see how much SRAM you have after all is set up.

  Serial.print("Memory free = ");
  Serial.println(freeMemory());

The problems seems:

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1294392281

And in my code is caused to an heavy usage of String, probably.

Quite possible. I use character arrays for that reason. freeMemory stays constant if all is working well.

BTW, I see where you were checking your memory now.

SurferTim:
Quite possible. I use character arrays for that reason. freeMemory stays constant if all is working well.

BTW, I see where you were checking your memory now.

Ok, I will try to write a code for that, but I'm more used in PHP than C (too long not used! :slight_smile: )

The memory remain constant, has only a spike at the end and after crashes.

Character arrays are easy if you use sprintf. A simple example:

char outBuf[64];
int test1 = 24;
int test2 =3864;

void setup() {
  Serial.begin(9600);
  sprintf(outBuf,"test1 = %d and test2 = %d",test1,test2);
  Serial.println(outBuf);
}

void loop() {
}