[SOLVED] SD card data logger power cut

Hi there.

What I'd like to do is reading temperature values from a sensor and write it to a file.

Here is my program so far.

#include <Arduino.h>

#include <SD.h>
#include <Wire.h>
#include "RTClib.h"

const int chipSelect = 10;
const int sensorPin = 0;

RTC_DS1307 RTC;

void setup()
{

    Serial.begin(57600);
    Wire.begin();
    RTC.begin();

    if (!RTC.isrunning()) {
        Serial.println("RTC is not running!");
        // set RTC
        RTC.adjust(DateTime(__DATE__, __TIME__));
    }

    while (!Serial) {
        ;
    }

    Serial.print("\ninitializing SD card...");

    pinMode(10, OUTPUT);

    //see if the card is present and can be initialized:

    if(!SD.begin(chipSelect)) {
        Serial.println("Card failed, or not present");
        return;
    }

    Serial.println("card initialized");
}

void loop()
{
    DateTime now = RTC.now();

    // print date and time
    Serial.print(now.day(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.year(), DEC);
    Serial.print(' ');
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.print(' ');

    String dataString = "";
    dataString += String(now.day());
    dataString += '/';
    dataString += String(now.month());
    dataString += '/';
    dataString += String(now.year());
    dataString += ' ';
    dataString += String(now.hour());
    dataString += ':';
    dataString += String(now.minute());
    dataString += ':';
    dataString += String(now.second());
    dataString += ' ';


    float temperature = analogRead(sensorPin);
    temperature = (5 * temperature * 100.0) / 1024.0;
    char temp[10];


    // read sensor value and append to dataString
    dtostrf(temperature,1,2,temp);
    dataString += String(temp);

    File dataFile = SD.open("datalog.txt", FILE_WRITE);

    if (dataFile) {
        dataFile.println(dataString);
        dataFile.close();
        Serial.println(dataString);
    } else {
        // back up

        /*
          What if there is a power cut?
        */
        //
        //setup();
        Serial.println("error opening datalog.txt");
    }

    delay(5000);
}

Well, the program works fine if everything goes well.

But what if there is a power cut. To test the power cut I simply plug out USB cable. After that when I plug in the program doesn't continue to record data anymore.

If I reset the Arduino manually it works again as expected.

What should I do, so that when there is a power failure I do not need to reset Arduino manually.

Any help would be appreciated. Thanks.

What do your debugging prints show? Also shouldn't you close the file each time around the loop?

I changed the else loop like this.

    } else {
        Serial.println("error opening datalog.txt");
        dataFile.close();
        /*
          What if there is a power cut?
        */

    }

If I unplug USB cable still it doesn't work as expected.

After plugging out and in USB cable if I use serial monitor it starts to record values again. Here is the output of serial monitor.

initializing SD card...card initialized
3/8/2013 1:3:56 3/8/2013 1:3:56 25.88
3/8/2013 1:4:1 3/8/2013 1:4:1 25.39
3/8/2013 1:4:6 3/8/2013 1:4:6 25.39
3/8/2013 1:4:11 3/8/2013 1:4:11 25.39
3/8/2013 1:4:16 3/8/2013 1:4:16 25.39

I think I should reset arduino in software in the else loop.

Should I use 1 wire method or use only software reset function.

After plugging out and in USB cable if I use serial monitor it starts to record values again.

Doing this RESETs the Arduino

LarryD:

After plugging out and in USB cable if I use serial monitor it starts to record values again.

Doing this RESETs the Arduino

Do you mean only plugging out and in USB cable or plugging out and in USB cable and starting serial monitor resets Arduino.

Anyway I think, I found a solution. I used software method to reset Arduino. Here is my code so far.

include <Arduino.h>

#include <SD.h>
#include <Wire.h>
#include "RTClib.h"
#include <avr/wdt.h>

const int chipSelect = 10;
const int sensorPin = 0;

RTC_DS1307 RTC;

void setup()
{
    wdt_enable(WDTO_500MS);
    Serial.begin(57600);
    Wire.begin();
    RTC.begin();

    if (!RTC.isrunning()) {
        Serial.println("RTC is not running!");
        // set RTC
        RTC.adjust(DateTime(__DATE__, __TIME__));
    }

    while (!Serial) {
        ;
    }

    Serial.print("\ninitializing SD card...");

    pinMode(10, OUTPUT);

    //see if the card is present and can be initialized:

    if(!SD.begin(chipSelect)) {
        Serial.println("Card failed, or not present");
        return;
    }

    Serial.println("card initialized");
}

void loop()
{
    DateTime now = RTC.now();

    // print date and time
    Serial.print(now.day(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.year(), DEC);
    Serial.print(' ');
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.print(' ');

    String dataString = "";
    dataString += String(now.day());
    dataString += '/';
    dataString += String(now.month());
    dataString += '/';
    dataString += String(now.year());
    dataString += ' ';
    dataString += String(now.hour());
    dataString += ':';
    dataString += String(now.minute());
    dataString += ':';
    dataString += String(now.second());
    dataString += ' ';


    float temperature = analogRead(sensorPin);
    temperature = (5 * temperature * 100.0) / 1024.0;
    char temp[10];


    // read sensor value and append to dataString
    dtostrf(temperature,1,2,temp);
    dataString += String(temp);

    File dataFile = SD.open("datalog.txt", FILE_WRITE);

    if (dataFile) {
        dataFile.println(dataString);
        dataFile.close();
        Serial.println(dataString);
    } else {
        Serial.println("error opening datalog.txt");
        dataFile.close();

        /*
          What if there is a power cut?
        */
        wdt_reset();

    }

    delay(5000);
}

Now the program works as expected.

Many thanks.

akuz:
Anyway I think, I found a solution. I used software method to reset Arduino.

But there was a problem with this method. It was continuously resetting Arduino in half second. So that it was recording values in half seconds instead of 5 seconds.

3/8/2013 2:10:44 25.88
3/8/2013 2:10:44 25.88
3/8/2013 2:10:45 25.39
3/8/2013 2:10:46 25.88
3/8/2013 2:10:46 25.88
3/8/2013 2:10:47 25.88
3/8/2013 2:10:47 25.88

WDTTO_8S is a constant that means threshold interval of 8 seconds. (It is defined inside header file). If Watchdog receive no "pat" signal for this period, it will "bite" back - reboot the MCU.

I think what I was doing was exactly the opposite :slight_smile:

Here is the corrected program.

#include <Arduino.h>

#include <SD.h>
#include <Wire.h>
#include "RTClib.h"
#include <avr/wdt.h>

const int chipSelect = 10;
const int sensorPin = 0;

RTC_DS1307 RTC;

void setup()
{
    wdt_enable(WDTO_500MS);
    Serial.begin(57600);
    Wire.begin();
    RTC.begin();

    if (!RTC.isrunning()) {
        Serial.println("RTC is not running!");
        // set RTC
        RTC.adjust(DateTime(__DATE__, __TIME__));
    }

    while (!Serial) {
        ;
    }

    Serial.print("\ninitializing SD card...");

    pinMode(10, OUTPUT);

    //see if the card is present and can be initialized:

    if(!SD.begin(chipSelect)) {
        Serial.println("Card failed, or not present");
        return;
    }

    Serial.println("card initialized");
}

void loop()
{
    DateTime now = RTC.now();

    // print date and time
    Serial.print(now.day(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.year(), DEC);
    Serial.print(' ');
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.print(' ');

    String dataString = "";
    dataString += String(now.day());
    dataString += '/';
    dataString += String(now.month());
    dataString += '/';
    dataString += String(now.year());
    dataString += ' ';
    dataString += String(now.hour());
    dataString += ':';
    dataString += String(now.minute());
    dataString += ':';
    dataString += String(now.second());
    dataString += ' ';


    float temperature = analogRead(sensorPin);
    temperature = (5 * temperature * 100.0) / 1024.0;
    char temp[10];


    // read sensor value and append to dataString
    dtostrf(temperature,1,2,temp);
    dataString += String(temp);

    File dataFile = SD.open("datalog.txt", FILE_WRITE);

    if (dataFile) {
        dataFile.println(dataString);
        dataFile.close();
        Serial.println(dataString);

        // tell watchdog that everything is ok
        wdt_reset();

    } else {
        Serial.println("error opening datalog.txt");
        dataFile.close();

        /*
          What if there is a power cut?
        */
        for (;;) {
        }


    }

    // tell watchdog that everything is ok
    wdt_reset();

    delay(5000);
}

http://tushev.org/electronics/arduino/item/46-arduino-and-watchdog-timer