Pages: [1]   Go Down
Author Topic: SD card fails to open file to write after a day of use  (Read 4367 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Dear all,

I am sorry that this topic may be discussed a million times already, but i cant still make mine working. so please bear with me.
i have attached my code in the attachment. A pretty long one. Basically i want to "real time logging temperature and voltage in a room" for a week.  I am currently using kingston SD card (4GB, FAT32). I have done an overnight run with the arduino and the data logger.  The program actually still works but the logger has stopped working after 2 hours.  Having done some searching on Google reveals the problem may due to memory leakage.  Is there any way that i could done to solve this?  Please kindly advise.  Thank you very much guys!
« Last Edit: February 14, 2013, 04:08:40 am by camac » Logged

Sydney, Australia
Offline Offline
Edison Member
*
Karma: 33
Posts: 1260
Big things come in large packages
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Use the sdfat library instead of the Arduino sd library. Faster and does not leak memory.
Logged

Arduino libraries http://arduinocode.codeplex.com
Parola hardware & library http://parola.codeplex.com

Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you for the advice!  But i have another issue when using the SdFat library.  I tested the library with the ReadWriteSdFat example.  In the Serial Com, it showed "Writing to test.txt...done.", "error: opening test.txt for read failed", "SD errorCode: 0x13,0x0".  When i used another SD card, same error pops up with a different error code as 0x6,0x1.  Does anyone know what is the meaning about this?  
« Last Edit: January 27, 2013, 08:26:36 pm by camac » Logged

Sydney, Australia
Offline Offline
Edison Member
*
Karma: 33
Posts: 1260
Big things come in large packages
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Try using the utilities in the examples for sdfat to format the sd card.
« Last Edit: January 27, 2013, 09:04:29 pm by marco_c » Logged

Arduino libraries http://arduinocode.codeplex.com
Parola hardware & library http://parola.codeplex.com

Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you for your help and replies, Marco_C!  I have used Sdfat.lib while the card can now be used.  However, this time when i run the program for like 24 hours with a 5 second time interval between logging, the card has stopped after 14 hours of operations, recording about 28281 data.  Is this happening still related to memory leak? Or my program is too long and there isn't any memory left for the data logging stuff? Thank you guys in advice!
Logged

Sydney, Australia
Offline Offline
Edison Member
*
Karma: 33
Posts: 1260
Big things come in large packages
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hard to tell unless you post your code smiley-wink
Logged

Arduino libraries http://arduinocode.codeplex.com
Parola hardware & library http://parola.codeplex.com

Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello! The code is too long to be quoted in the message box.  Marco_C, i have attached the code.txt in the first post.  Would you mind to check that out?  Thank you very much for your help! smiley-grin
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48556
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

None of your code for reading from the serial port is worth anything. You test that there is at least one byte to read, and then proceed to read as much as you want, assuming that the stupid delay() call will somehow make serial data appear in time.

There are plenty of resources about for reading serial data properly (always test there there is data, stopping when the end of a packet arrives, etc.). You need to find them, and fix your code.
Logged

Dee Why NSW
Offline Offline
Edison Member
*
Karma: 47
Posts: 2204
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I don't understand the memory leakage problem. If you feed the stuff direct to the SD, I can't see where there could be a memory problem. Here is what I have been using of late and it has been working continuously for days. The daily output is about 400k.  Some of it is abit messy but the SD stuff might be useful.


Code:
/*
//  This Arduino sketch reads DS18B20 "1-Wire" digital
 //  temperature sensors.
 //  Copyright (c) 2010 Mark McComb, hacktronics LLC
 //  License: http://www.opensource.org/licenses/mit-license.php (Go crazy)
 //  Tutorial:
 //  http://www.hacktronics.com/Tutorials/arduino-1-wire-tutorial.html
 //  modernised, compacted, and metricated by Nick Pyner
 //  code uses Arduino LCD stuff, for shield on Freetronics EtherTen.
 //  Serial print commands are for PLX-DAQ
 
 From cosm library example and lifts from a lot of others
 particularly from Stanley in Kuala Lumpur.
 Use your own DS18B20 addresses, keys etc.
 Note that the feed id is in line 42, or somewhere nearby...
 */
#include <OneWire.h>
#include <DallasTemperature.h>
#include <SPI.h>                  
#include <Ethernet.h>            // Ethernet
#include <HttpClient.h>          // Cosm lib
#include <Cosm.h>                // Cosm lib
#include <PCD8544.h>             // Nokia 5110
#include <SD.h>                  // SD card
#include <string.h>              // from Date As Filename
#include "RTClib.h"              // from Date As Filename
#include "Wire.h"                // Original RTC lib for LCD disp, SD card, and serial

#define DS1307_ADDRESS 0x68

RTC_DS1307 RTC;
static PCD8544 lcd;

File myFile;
char filename[] = "00000000.CSV";


// Custom symbols
static const byte DEGREES_CHAR = 1;
static const byte degrees_glyph[] = { 0x00, 0x07, 0x05, 0x07, 0x00 };
static const byte SLASH_CHAR = 2;
static const byte slash_glyph[] = {0x00,0x20,0x10,0x08};

byte InThermo[8] =  {
  0x28, 0x69, 0xC2, 0xB0, 0x03, 0x00, 0x00, 0X9F};
byte OutThermo[8] = {
  0x28, 0x7A, 0x8B, 0xC0, 0x03, 0x00, 0x00, 0x2F};
byte DrainThermo[8] = {
  0x28, 0x09, 0xA9, 0xC0, 0x03, 0x00, 0x00, 0x95};

#define ONE_WIRE_BUS 3
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

char cosmKey[] = "l6 tralala Zz0g";

int  second, minute, hour, weekDay, monthDay, month, year;

int k=0;
float InTemp, OutTemp, DrainTemp;    // used for SD write only

// Define the strings for our datastream IDs
char sensorId0[] = "InThermo";
char sensorId1[] = "OutThermo";
char sensorId2[] = "DrainThermo";
char calcId1[] = "diff";

const int bufferSize = 140;
char bufferValue[bufferSize]; // enough space to store the string we're going to send
CosmDatastream datastreams[] = {
  CosmDatastream(sensorId0, strlen(sensorId0), DATASTREAM_FLOAT),
  CosmDatastream(sensorId1, strlen(sensorId1), DATASTREAM_FLOAT),
  CosmDatastream(sensorId2, strlen(sensorId2), DATASTREAM_FLOAT),
  CosmDatastream(calcId1, strlen(calcId1), DATASTREAM_FLOAT),
};
// Finally, wrap the datastreams into a feed
CosmFeed feed(83153, datastreams, 4                                   /*put your number here */);

EthernetClient client;
CosmClient cosmclient(client);

void setup() {
   lcd.begin(84, 48);
     // Register the custom symbols...
  lcd.createChar(DEGREES_CHAR, degrees_glyph);
  lcd.createChar(SLASH_CHAR, slash_glyph);
  Wire.begin();
  Serial.begin(9600);
  Serial.print("    filename   ");
  delay(300);//Wait for newly restarted system to stabilize
  lcd.setCursor (0,0);
  lcd.print("Initializing");
  delay(2000);
  lcd.setCursor (0,1);

  pinMode(10, OUTPUT);

  if (!SD.begin(4))
  {
    lcd.print("failed!");
    delay (2000);
    return;
  }
  lcd.print("init. OK!");
  delay(2000);
      getFileName();
      Serial.println(filename);
  lcd.clear();

  Serial.println("LABEL,Time,InTemp,OutTemp,diff,DrainTemp");

  sensors.setResolution(InThermo, 12);
  sensors.setResolution(OutThermo, 12);
  sensors.setResolution(DrainThermo, 12);

  Serial.println("Starting multiple datastream upload to Cosm...");
  Serial.println();

  while (Ethernet.begin(mac) != 1)
  {
    Serial.println("Error getting IP address via DHCP, trying again...");
    delay(10000);
  }
}

void loop() {
   running();
  GetClock();
  if (hour == 0 && minute == 0 && second <2)
  {
    getFileName();
  }
 Serial.print("DATA,TIME,       ");
  int ret=0;
  //get the values from the DS8B20's
  sensors.requestTemperatures();

  float InTemp = (sensorValue(InThermo));
  float OutTemp = (sensorValue(OutThermo)); 
  float DrainTemp = (sensorValue(DrainThermo));

  float diff = OutTemp - InTemp;

  datastreams[0].setFloat(InTemp);
  datastreams[1].setFloat(OutTemp);
  datastreams[2].setFloat(DrainTemp);
  datastreams[3].setFloat(diff);
  Serial.print(InTemp);
  Serial.print(" ,  ");
  Serial.print(OutTemp);
  Serial.print(" ,  ");
  Serial.print(DrainTemp);
  Serial.println(" ,  ");

  lcd.setCursor(49,0);
  lcd.print(InTemp);
  lcd.setCursor(49,1);
  lcd.print (OutTemp);
  lcd.setCursor(49,2);
  lcd.print(DrainTemp);

  k=k+1; 

  if (k>9 )
  {   
      ret = cosmclient.put(feed, cosmKey);    // SEND FEED TO COSM
     
      myFile = SD.open(filename, FILE_WRITE);//<<<<<<<<<<<<< OPEN
  myFile.print(hour);
  myFile.print(":");
  myFile.print(minute);
  myFile.print(":");
  myFile.print(second);
  myFile.print(",");

  myFile.print(InTemp);
  myFile.print(",");
  myFile.print(OutTemp);
  myFile.print(",");
  myFile.print(DrainTemp);
  myFile.print(",");
  myFile.println();
       myFile.close();//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>CLOSE
       
      k=0;
  }
  delay(850);
}  // loop ends here

//sensorValue function
float sensorValue (byte deviceAddress[])
{
  float tempC = sensors.getTempC (deviceAddress);
  return tempC;
}

byte bcdToDec(byte val)  {
  // Convert binary coded decimal to normal decimal numbers
  return ( (val/16*10) + (val%16) );
}

void GetClock(){
  // Reset the register pointer
  Wire.beginTransmission(DS1307_ADDRESS);
  byte zero = 0x00;
  Wire.write(zero);
  Wire.endTransmission();
  Wire.requestFrom(DS1307_ADDRESS, 7);

  second = bcdToDec(Wire.read());
  minute = bcdToDec(Wire.read());
  hour = bcdToDec(Wire.read() & 0b111111); //24 hour time
  weekDay = bcdToDec(Wire.read()); //0-6 -> sunday - Saturday
  monthDay = bcdToDec(Wire.read());
  month = bcdToDec(Wire.read());
  year = bcdToDec(Wire.read());
}

void getFileName(){

  DateTime now = RTC.now();

  filename[0] = (now.year()/1000)%10 + '0'; //To get 1st digit from year()
  filename[1] = (now.year()/100)%10 + '0'; //To get 2nd digit from year()
  filename[2] = (now.year()/10)%10 + '0'; //To get 3rd digit from year()
  filename[3] = now.year()%10 + '0'; //To get 4th digit from year()
  filename[4] = now.month()/10 + '0'; //To get 1st digit from month()
  filename[5] = now.month()%10 + '0'; //To get 2nd digit from month()
  filename[6] = now.day()/10 + '0'; //To get 1st digit from day()
  filename[7] = now.day()%10 + '0'; //To get 2nd digit from day()

  myFile = SD.open(filename, FILE_WRITE);
  myFile.close();
}
void running(){
  
  lcd.setCursor(0,0);
  lcd.print("In");
  lcd.setCursor(31,0);
  lcd.print("\001C ");
  lcd.setCursor(0,1);
  lcd.print("Out");
  lcd.setCursor(31,1);
  lcd.print("\001C ");
  lcd.setCursor(0,2);
  lcd.print("Drain");
  lcd.setCursor(31,2);
  lcd.print("\001C ");
  lcd.setCursor(0,3);
  lcd.print("F");
  lcd.setCursor(5,3);
  lcd.print("l");
  lcd.setCursor(10,3);
  lcd.print("ow");
  lcd.setCursor(24,3);
  lcd.print("l");
  lcd.setCursor(28,3);
  lcd.print("\002");
  lcd.print("m");
  lcd.setCursor(39,3);
  lcd.print("i");  
  lcd.setCursor(44,3);
  lcd.print("n");
  lcd.setCursor(14,4);
  lcd.print("Conv %");
  lcd.setCursor(21,5);
  lcd.print("kW");

}

void standing(){
 lcd.setCursor(10, 0);
  lcd.print("kWh");
  lcd.setCursor(6,1);
  lcd.print("PREVIOUS DAY");
  lcd.setCursor(0,2);
  lcd.print("kWh");
  lcd.setCursor(0,3);
  lcd.print("kW max");
  lcd.setCursor(0,4);
  lcd.print("max flow");
    lcd.setCursor(0,5);
  lcd.print("max rise");
  lcd.setCursor(66,5);
  lcd.print("54");
  lcd.setCursor(77,5);
  lcd.print(".");
  lcd.setCursor(79,5);
  lcd.print("9");
 }  
« Last Edit: February 27, 2013, 10:54:52 pm by Nick_Pyner » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you Nick for the code you posted.It helped me in a project of mine.Cheers  smiley
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi all,

I am sorry for the late reply.  I have been troubleshooting the SD shield lately and it has continued to work for a week.  I am no programming or Arduino expert.  But here is what i have done in the code to solve it.  I hope it helps even if it may not make sense. smiley-grin

Code:
myFile=SD.open("test.txt");
if(myFile){
Serial.println("test.txt:");
if(myFile.available()){
Serial.write(myFile.read());
}
myFile.close();
}
else {Serial.println("error opening test.txt");}
The code does nothing new but after each write, it reads the SD card.  In doing so, the SD card seems to be able to communicate with Arduino without problems.  Thank you for everyone's inputs!
Logged

Pages: [1]   Go Up
Jump to: