Couldn't create file

Hi guys,

don’t know what I’m doing wrong. I write small program for logging current, voltage, time, … but I’m stucked on creating new file :cold_sweat:

I used Adafruit manual for datalogging which is perfectly working but when I try to incorporate their code into mine I got “Couldn’t create file” message after uploading and start serial monitor :~

Please could someone help me?

/*
   
            ,/
          ,'/
        ,' /
      ,'  /_____,
    .'____    ,'    P O W E R   C O N S U M P T I O N   M O D U L E
         /  ,'     (based on ATMega 328P, DS1307, 16x2 LCD & ACS712)
        / ,'
       /,'
      /'
    
    I've created this module for my diploma thesis oriented to using
    alternative energy sources (i.e. solar panel and Stirling generator)
    for charging backup battery in alarm systems.
    I used this module for measuring power consumption of different
    alarm systems such as Paradox and Jablotron.
    
*/

// Libraries
#include <SD.h>                     // Standard Arduino lib
#include <Wire.h>                   // Standard Arduino lib
#include <LiquidCrystal.h>          // Standard Arduino lib
#include <RTClib.h>                 // Adafruit lib     	- https://github.com/adafruit/RTClib
#include <AnalogSmooth.h>           // MichaelThessel lib	- https://github.com/MichaelThessel/arduino

// LED pins
#define redLEDpin 8
#define greenLEDpin 9

// Voltage divider
#define voltageInPin A1     	    // Voltage divider analog input pin
#define voltageDiv 3.13             // Output voltage from divider [depends on ratio]
uint16_t voltageRAW = 0;    	    // Value read from voltage divider
float voltagePin = 0;               // Voltage on analog input pin A1
float outputVolts = 0;              // Output value in V [volts]
float ratio = 6.6667;               // Change to your desired value  [R1 = 10k & R2 = 1.5k @ Vin = 24V & Vout = 3.13V]

// ACS712 hall-effect current sensor    - http://goo.gl/eAqpsX
#define sensorInPin A0      	    // ACS712 analog input pin
#define voltageSupply 3.3           // Supply voltage [3.3 or 5]
uint16_t sensorRAW = 0;     	    // Value read from ACS712
float currentPin = 0;               // Voltage on analog input pin A0
float outputAmps = 0;               // Output value in A [amps]

// Smoothing analog inputs
AnalogSmooth as = AnalogSmooth();   // Defaults to window size 10

// Define the Real Time Clock object [I²C - pins A4 & A5]
RTC_DS1307 RTC;

// Initialize the library with the numbers of the interface pins
// LCD pins (RS, E, D4, D5, D6, D7)
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);
#define ECHO_TO_LCD 1

// SD card
#define chipSelect 10               // SD card CS [chip select] pin
#define LOG_INTERVAL 1000           // Time between grabbing data and logging it [ms]
                                    // set it to the LOG_INTERVAL to write each time (safest)
                                    // set it to 10*LOG_INTERVAL to write all data every 10 datareads, you could lose up to 
                                    // the last 10 reads if power is lost but it uses less power and is much faster!
#define SYNC_INTERVAL 1000          // mills between calls to flush() - to write data to the card
uint32_t syncTime = 0;              // time of last sync()

// the logging file
File logfile;

// If we couldn't write to the SD card or open it program prints out the error to the Serial Monitor,
// turns on the red error LED and then sits in a while(1); loop forever, also known as a HALT.
void error(char *str) {
    Serial.print("error: ");
    Serial.println(str);
  
    // red LED indicates error
    digitalWrite(redLEDpin, HIGH);
  
    while(1);
}

void setup(void)
{
    Serial.begin(9600);
    lcd.begin(16, 2);
    Serial.println();
    
    // use debugging LEDs
    pinMode(redLEDpin, OUTPUT);
    pinMode(greenLEDpin, OUTPUT);

    // initialize the SD card
    Serial.print("Initializing SD card...");
    #if ECHO_TO_LCD
        lcd.print("Initializing SD card ...");
    #endif // ECHO_TO_LCD
    
    delay(1000);
    
    // make sure that the default chip select pin is set to
    // output, even if you don't use it:
    pinMode(10, OUTPUT);
  
    // see if the card is present and can be initialized:
    if (!SD.begin(chipSelect)) {
        error("Card failed, or not present");
    }
    Serial.println("card initialized.");
    #if ECHO_TO_LCD
        lcd.clear();
        lcd.print("card initialized.");
    #endif // ECHO_TO_LCD
  
    // create a new file
    char filename[] = "LOGGER00.CSV";
    for (uint8_t i = 0; i < 100; i++)
    {
        filename[6] = i/10 + '0';
        filename[7] = i%10 + '0';
        if (! SD.exists(filename)) {
            // only open a new file if it doesn't exist
            logfile = SD.open(filename, FILE_WRITE); 
            break;  // leave the loop!
        }
    }
    
    if (! logfile) {
        error("couldnt create file");
    }
  
    Serial.print("Logging to: ");
    Serial.println(filename);
    #if ECHO_TO_LCD
            lcd.print("Logging to: ");
            lcd.println(filename);
    #endif // ECHO_TO_LCD
    
    // connect to RTC
    Wire.begin();  
    if (!RTC.begin()) {
        logfile.println("RTC failed");
        #if ECHO_TO_SERIAL
            Serial.println("RTC failed");
        #endif  //ECHO_TO_SERIAL
        #if ECHO_TO_LCD
            lcd.println("RTC failed");
        #endif // ECHO_TO_LCD
    }
    
    logfile.println("stamp,datetime,voltage,current");    
    #if ECHO_TO_SERIAL
        Serial.println("stamp,datetime,voltage,current");
    #endif //ECHO_TO_SERIAL
 
    // If you want to set the aref to something other than 5v
    // analogReference(EXTERNAL);
}

void loop(void) {
    DateTime now;

    // delay for the amount of time we want between readings
    delay((LOG_INTERVAL -1) - (millis() % LOG_INTERVAL));
  
    digitalWrite(greenLEDpin, HIGH);
  
    // log milliseconds since starting
    uint32_t m = millis();
    logfile.print(m);               // milliseconds since start
    logfile.print(", ");    
    #if ECHO_TO_SERIAL
        Serial.print(m);            // milliseconds since start
        Serial.print(", ");  
    #endif
    #if ECHO_TO_LCD
        lcd.print(m);               // milliseconds since start
        lcd.print(", ");
    #endif // ECHO_TO_LCD

    // fetch the time
    now = RTC.now();
    
    // log time
    logfile.print(now.year(), DEC);
    logfile.print("/");
    logfile.print(now.month(), DEC);
    logfile.print("/");
    logfile.print(now.day(), DEC);
    logfile.print(" ");
    logfile.print(now.hour(), DEC);
    logfile.print(":");
    logfile.print(now.minute(), DEC);
    logfile.print(":");
    logfile.print(now.second(), DEC);
    logfile.print('"');
    #if ECHO_TO_SERIAL
        Serial.print(now.year(), DEC);
        Serial.print("/");
        Serial.print(now.month(), DEC);
        Serial.print("/");
        Serial.print(now.day(), DEC);
        Serial.print(" ");
        Serial.print(now.hour(), DEC);
        Serial.print(":");
        Serial.print(now.minute(), DEC);
        Serial.print(":");
        Serial.print(now.second(), DEC);
        Serial.print('"');
    #endif //ECHO_TO_SERIAL

    
    uint16_t voltageRAW = as.analogReadSmooth(voltageInPin);  
    float voltagePin = voltageRAW * (voltageDiv / 1024);
    float outputVolts = voltagePin * ratio;
    
    uint16_t sensorRAWS = as.analogReadSmooth(sensorInPin);
    float currentPin = sensorRAW * (voltageSupply / 1024);
    float outputAmps = currentPin / 0.185;
    
    logfile.print(", ");    
    logfile.print(voltageRAW);
    logfile.print(", ");    
    logfile.print(outputVolts);
    logfile.print(", ");
    logfile.print(sensorRAW);
    logfile.print(", ");
    logfile.print(outputAmps);
    #if ECHO_TO_SERIAL
        Serial.print(", ");    
        Serial.print(voltageRAW);
        Serial.print(", ");    
        Serial.print(outputVolts);
        Serial.print(", ");
        Serial.print(sensorRAW);
        Serial.print(", ");
        Serial.print(outputAmps);
    #endif //ECHO_TO_SERIAL

    digitalWrite(greenLEDpin, LOW);

    // Now we write data to disk! Don't sync too often - requires 2048 bytes of I/O to SD card
    // which uses a bunch of power and takes time
    if ((millis() - syncTime) < SYNC_INTERVAL) return;
    syncTime = millis();
  
    // blink LED to show we are syncing data to the card & updating FAT!
    digitalWrite(redLEDpin, HIGH);
    logfile.flush();
    digitalWrite(redLEDpin, LOW);
  
}

Many many thanks

Can you post your debugging output please? Also indicate the file name you are creating, eg.

      Serial.print ("Opening file name: ");
      Serial.println (filename);
      logfile = SD.open(filename, FILE_WRITE);

@nick: it appears the code is using fat16lib's auto namer, which supports 99 files.

Are you sure you haven't used all the 99 files testing the adafruit code, your code will not overwrite old files ( easy to upload and test a large app more than 99 times ).

Probably isn't this but, when an Arduino has a serious error ( memory corruption ), it can reset. If the code that does run writes a file, then it will reach the 99 file limit quickly if not noticed.

Also you should try using the newer/improved SD lib: https://code.google.com/p/sdfatlib/

Thanks for your advices :wink:
I checked card and it didn't reach 99 files. Error appears every time when I reset Arduino.
But I think that I found the problem - AnalogSmooth library from Michael Thessel. I remove it from project and now everything is working OK. I want to make my life easier with library and simple command but contrary is the case :roll_eyes:

Here is edited program:

/*
   
            ,/
          ,'/
        ,' /
      ,'  /_____,
    .'____    ,'    P O W E R   C O N S U M P T I O N   M O D U L E
         /  ,'     (based on ATMega 328P, DS1307, 16x2 LCD & ACS712)
        / ,'
       /,'
      /'
    
    I've created this module for my diploma thesis oriented to using
    alternative energy sources (i.e. solar panel and Stirling generator)
    for charging backup battery in alarm systems.
    I used this module for measuring power consumption of different
    alarm systems such as Paradox and Jablotron.
    
*/

// Libraries
#include <SD.h>                     // Standard Arduino lib
#include <Wire.h>                   // Standard Arduino lib
#include <LiquidCrystal.h>          // Standard Arduino lib
#include <RTClib.h>                 // Adafruit lib     	- https://github.com/adafruit/RTClib

// LED pins
#define redLEDpin 8
#define greenLEDpin 9

// Define the Real Time Clock object [I²C - pins A4 & A5]
RTC_DS1307 RTC;

// Initialize the library with the numbers of the interface pins
// LCD pins (RS, E, D4, D5, D6, D7)
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);
#define ECHO_TO_LCD 1

// SD card
#define chipSelect 10               // SD card CS [chip select] pin
#define LOG_INTERVAL 1000           // Time between grabbing data and logging it [ms]
                                    // set it to the LOG_INTERVAL to write each time (safest)
                                    // set it to 10*LOG_INTERVAL to write all data every 10 datareads, you could lose up to 
                                    // the last 10 reads if power is lost but it uses less power and is much faster!
#define SYNC_INTERVAL 1000          // mills between calls to flush() - to write data to the card
uint32_t syncTime = 0;              // time of last sync()

// the logging file
File logfile;

// Voltage divider
#define voltageInPin A1     	    // Voltage divider analog input pin
#define voltageDiv 3.13             // Output voltage from divider [depends on ratio]
uint16_t voltageRAW = 0;    	    // Value read from voltage divider
float voltagePin = 0;               // Voltage on analog input pin A1
float outputVolts = 0.0;              // Output value in V [volts]
float ratio = 6.6667;               // Change to your desired value  [R1 = 10k & R2 = 1.5k @ Vin = 24V & Vout = 3.13V]

// ACS712 hall-effect current sensor    - http://goo.gl/eAqpsX
#define sensorInPin A0      	    // ACS712 analog input pin
#define voltageSupply 3.3           // Supply voltage [3.3 or 5]
uint16_t sensorRAW = 0;     	    // Value read from ACS712
float currentPin = 0;               // Voltage on analog input pin A0
float outputAmps = 0.0;               // Output value in A [amps]

// If we couldn't write to the SD card or open it program prints out the error to the Serial Monitor,
// turns on the red error LED and then sits in a while(1); loop forever, also known as a HALT.
void error(char *str)
{
    Serial.print("error: ");
    Serial.println(str);
  
    // red LED indicates error
    digitalWrite(redLEDpin, HIGH);
  
    while(1);
}

void setup(void)
{
    Serial.begin(9600);
    lcd.begin(16, 2);
    Serial.println();
    
    // use debugging LEDs
    pinMode(redLEDpin, OUTPUT);
    pinMode(greenLEDpin, OUTPUT);

    // initialize the SD card
    Serial.print("Initializing SD card...");
    #if ECHO_TO_LCD
        lcd.print("Initializing SD");
    #endif // ECHO_TO_LCD
    
    delay(2000);
    
    // make sure that the default chip select pin is set to
    // output, even if you don't use it:
    pinMode(10, OUTPUT);
  
    // see if the card is present and can be initialized:
    if (!SD.begin(chipSelect))
    {
        error("Card failed, or not present");
    }
    Serial.println("card initialized.");
    #if ECHO_TO_LCD
        lcd.setCursor(4, 1);
        lcd.print("All DONE!");
    #endif // ECHO_TO_LCD
  
    // create a new file
    char filename[] = "LOGGER00.CSV";
    for (uint8_t i = 0; i < 100; i++)
    {
        filename[6] = i/10 + '0';
        filename[7] = i%10 + '0';
        if (! SD.exists(filename))
        {
            // only open a new file if it doesn't exist
            logfile = SD.open(filename, FILE_WRITE); 
            break;  // leave the loop!
        }
    }
    
    if (! logfile) {
        error("couldn't create file");
    }
    
    delay(4000);
    
        Serial.print("Logging to: ");
        Serial.println(filename);
    
    
    #ifdef ECHO_TO_LCD
        lcd.clear();
        lcd.print("Logging to file:");
        lcd.setCursor(0, 1);
        lcd.print(filename);
    #endif // ECHO_TO_LCD
    
    delay(5000);
    
    // connect to RTC
    Wire.begin();  
    if (! RTC.begin())
    {
        logfile.println("RTC failed");
        #if ECHO_TO_SERIAL
            Serial.println("RTC failed");
        #endif  //ECHO_TO_SERIAL
    }
    
    logfile.println("stamp,datetime,voltage,current");
    #if ECHO_TO_SERIAL
        Serial.println("stamp,datetime,voltage,current");
    #endif //ECHO_TO_SERIAL
    #if ECHO_TO_LCD
        lcd.clear();
        lcd.print("Volts|");
        lcd.setCursor(6, 0);
        lcd.print("Amps|");
        lcd.setCursor(11, 0);
        lcd.print("Watts");
    #endif 
 
    // If you want to set the aref to something other than 5v
    // analogReference(EXTERNAL);
}

void loop(void) {
    DateTime now;

    // delay for the amount of time we want between readings
    delay((LOG_INTERVAL -1) - (millis() % LOG_INTERVAL));
  
    digitalWrite(greenLEDpin, HIGH);
  
    // fetch the time
    now = RTC.now();
    
    // log time
    logfile.print('"');
    logfile.print(now.year(), DEC);
    logfile.print("/");
    logfile.print(now.month(), DEC);
    logfile.print("/");
    logfile.print(now.day(), DEC);
    logfile.print(" ");
    logfile.print(now.hour(), DEC);
    logfile.print(":");
    logfile.print(now.minute(), DEC);
    logfile.print(":");
    logfile.print(now.second(), DEC);
    logfile.print('"');
    #if ECHO_TO_SERIAL
        Serial.print('"');
        Serial.print(now.year(), DEC);
        Serial.print("/");
        Serial.print(now.month(), DEC);
        Serial.print("/");
        Serial.print(now.day(), DEC);
        Serial.print(" ");
        Serial.print(now.hour(), DEC);
        Serial.print(":");
        Serial.print(now.minute(), DEC);
        Serial.print(":");
        Serial.print(now.second(), DEC);
        Serial.print('"');
    #endif //ECHO_TO_SERIAL

    uint16_t voltageRAW = analogRead(voltageInPin);  
    float voltagePin = voltageRAW * (voltageDiv / 1024);
    float outputVolts = voltagePin * ratio;
    
    uint16_t sensorRAWS = analogRead(sensorInPin);
    float currentPin = sensorRAW * (voltageSupply / 1024);
    float outputAmps = currentPin / 0.185;
    
    logfile.print(", ");    
    logfile.print(voltageRAW);
    logfile.print(", ");    
    logfile.print(outputVolts);
    logfile.print(", ");
    logfile.print(sensorRAW);
    logfile.print(", ");
    logfile.print(outputAmps);
    #if ECHO_TO_SERIAL
        Serial.print(", ");    
        Serial.print(voltageRAW);
        Serial.print(", ");    
        Serial.print(outputVolts);
        Serial.print(", ");
        Serial.print(sensorRAW);
        Serial.print(", ");
        Serial.print(outputAmps);
    #endif //ECHO_TO_SERIAL
    #if ECHO_TO_LCD
        lcd.print(voltageRAW);
        lcd.setCursor(6, 1);
        lcd.print(outputVolts);
        lcd.setCursor(11, 1);
        lcd.print(outputAmps);
    #endif

    logfile.println();
    #if ECHO_TO_SERIAL
        Serial.println();
    #endif // ECHO_TO_SERIAL
    
    digitalWrite(greenLEDpin, LOW);

    // Now we write data to disk! Don't sync too often - requires 2048 bytes of I/O to SD card
    // which uses a bunch of power and takes time
    if ((millis() - syncTime) < SYNC_INTERVAL) return;
    syncTime = millis();
  
    // blink LED to show we are syncing data to the card & updating FAT!
    digitalWrite(redLEDpin, HIGH);
    logfile.flush();
    digitalWrite(redLEDpin, LOW);
  
}

I have problem with this part

 logfile.println("stamp,datetime,voltage,current");
    #if ECHO_TO_SERIAL
        Serial.println("stamp,datetime,voltage,current");
    #endif //ECHO_TO_SERIAL
    #if ECHO_TO_LCD
        lcd.clear();
        lcd.print("Volts|");
        lcd.setCursor(6, 0);
        lcd.print("Amps|");
        lcd.setCursor(11, 0);
        lcd.print("Watts");
    #endif

Output to serial monitor is not working but writing to logfile and LCD is fully functional :~

Where is ECHO_TO_SERIAL defined?

Good question :cold_sweat:
What can I say ... my eyes faulty :astonished: :grin:

Thank you! 8)