Deleting the contents of a file in the SD Card

Hey,
I am building a datalogger which also has a place for ID so that I can count the number of datapoints I have. To prevent the ID from rolling back to 0, which happens when the Arduino is either reset or the power cable is unplugged, I created another text file called Number_ID to read the current ID so that it doesn’t start over. Whenever the ID is incremented after logging in the datapoints to another textfile called log.txt, I store the new ID in the Number_ID file.
The problem, or possibly, the ignorance I’m facing is regards to storing the new ID in the text file and deleting the old ID. How do I possibly delete the contents of “Number_ID” while retaining the file so as to allow for imprinting the new ID ?
Here’s the code for the logger :-

#include<Wire.h>
#include<SD.h>
#include<dht.h>
dht DHT;
const int flux=A0; //LDR
const int temp_humid=6; //DHT sensor
const int CS=10; //Chip Select for SD Module
const int power=2; //Power pin for SD Module
long id=0; //for ID purpose
#define address 0x68
int decToBcd(int val)
{
  return( (val/10*16) + (val%10) );
}
int bcdToDec(int val)
{
  return( (val/16*10) + (val%16) );
}
void setup()
{
  Wire.begin();
  pinMode(flux,INPUT_PULLUP); //for light
  pinMode(CS,OUTPUT); //chip select
  pinMode(power,OUTPUT); //power for SD card
  pinMode(temp_humid,INPUT); //DHT sensor
  digitalWrite(power,HIGH); //setting power pin to high for SD card
  Serial.begin(9600); //initializing Serial communication
  if(!SD.begin(CS))
  {
    Serial.println("Card failed");
  }
  else
  {
    Serial.println("Card loaded !");
  }
  File numberfile=SD.open("Number_ID.txt");
  if(numberfile)
  {
   Serial.println("Fetching last ID");
   float power=pow(10,numberfile.available()-1); 
   while(numberfile.available())
   {
    int number=numberfile.read()-'0';
    id=power*number+id;
    power/=10;
   }
   if(id==0)
   {
    Serial.println("ID=0");
   }
   else
   {
    Serial.print("ID=");
    Serial.println(id);
   }
  }
  File datafile=SD.open("log.csv",FILE_WRITE);
  if(datafile)
  {
    if(id==0)
    {
    datafile.println("#,Temperature,Humidity,Light,Date,Month,Year,Hour,Minute,Second,Day");
    }
    datafile.close();
  }
 //setDS3231time(30,42,21,4,26,11,14);
}
void setDS3231time(int second, int minute, int hour, int dayOfWeek, int dayOfMonth, int month, int year)
{
  // sets time and date data to DS3231
  Wire.beginTransmission(address);
  Wire.write(0); // set next input to start at the seconds register
  Wire.write(decToBcd(second)); // set seconds
  Wire.write(decToBcd(minute)); // set minutes
  Wire.write(decToBcd(hour)); // set hours
  Wire.write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday)
  Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31)
  Wire.write(decToBcd(month)); // set month
  Wire.write(decToBcd(year)); // set year (0 to 99)
  Wire.endTransmission();
}
void readDS3231time(int *second, int *minute, int *hour, int *dayOfWeek, int *dayOfMonth, int *month, int *year)
{
  Wire.beginTransmission(address);
  Wire.write(0); // set DS3231 register pointer to 00h
  Wire.endTransmission();
  Wire.requestFrom(address, 7);
  // request seven bytes of data from DS3231 starting from register 00h
  *second = bcdToDec(Wire.read() & 0x7f);
  *minute = bcdToDec(Wire.read());
  *hour = bcdToDec(Wire.read() & 0x3f);
  *dayOfWeek = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month = bcdToDec(Wire.read());
  *year = bcdToDec(Wire.read());
}
void Weekday(int l,char s[10]) //for converting number to Day of Week
{
  if(l==1)
  strcpy(s,"Sunday");
  else if(l==2)
  strcpy(s,"Monday");
  else if(l==3)
  strcpy(s,"Tuesday");
  else if(l==4)
  strcpy(s,"Wednesday");
  else if(l==5)
  strcpy(s,"Thursday");
  else if(l==6)
  strcpy(s,"Friday");
  else if(l==7)
  strcpy(s,"Saturday");
}
float ldrsensor() //function for retrieving light percentage
{
  float val;
  val=analogRead(flux);
  val=map(val,15,1005,100,0);
  return val;
}
void loop()
{
 float light; //variable for retrieving light value
 light=ldrsensor();
 char s[10];
 DHT.read11(temp_humid); //reading DHT sensor data
 int second, minute, hour, dayOfWeek, dayOfMonth, month, year; //variables for retrieving RTC data
 readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year); //reading RTC data
 File datafile=SD.open("log.csv",FILE_WRITE);
 Weekday(dayOfWeek,s);
 String rawdata=String(id)+", "+String(DHT.temperature)+", "+String(DHT.humidity)+", "+String(light)+", "+String(dayOfMonth)+", "+String(month)+", "+String(year)+", "+String(hour)+", "+String(minute)+", "+String(second)+", "+String(s);
 String disdata=String(id)+", "+String(DHT.temperature)+" C "+String(DHT.humidity)+"% "+String(light)+"% "+String(dayOfMonth)+"/"+String(month)+"/"+String(year)+" "+String(hour)+":"+String(minute)+":"+String(second)+" "+String(s);
 if(datafile)
 {
   id++;
   Serial.println(disdata);
   datafile.println(rawdata);
   datafile.close();
 }
 else
 {
   Serial.println("Can't save to card");
 }
 delay(1000);
}

Ignore any errors and goofs as I’m still working on the code.

Why don't you just check to see if the file exists first? if exists then $create=0

  File numberfile=SD.open("Number_ID.txt");

There are optional arguments to the open() method, that define how the file is opened. You can open for write, appending data, open for write, truncating existing data, open for read, etc.

There are optional arguments to the open() method, that define how the file is opened. You can open for write, appending data, open for write, truncating existing data, open for read, etc.

How do I open a file in “trunc” mode ?
“FILE_TRUNC” ?

How do I open a file in "trunc" mode ?
"FILE_TRUNC" ?

These are the values that you can use:

// use the gnu style oflag in open()
/** open() oflag for reading */
uint8_t const O_READ = 0X01;
/** open() oflag - same as O_READ */
uint8_t const O_RDONLY = O_READ;
/** open() oflag for write */
uint8_t const O_WRITE = 0X02;
/** open() oflag - same as O_WRITE */
uint8_t const O_WRONLY = O_WRITE;
/** open() oflag for reading and writing */
uint8_t const O_RDWR = (O_READ | O_WRITE);
/** open() oflag mask for access modes */
uint8_t const O_ACCMODE = (O_READ | O_WRITE);
/** The file offset shall be set to the end of the file prior to each write. */
uint8_t const O_APPEND = 0X04;
/** synchronous writes - call sync() after each write */
uint8_t const O_SYNC = 0X08;
/** create the file if nonexistent */
uint8_t const O_CREAT = 0X10;
/** If O_CREAT and O_EXCL are set, open() shall fail if the file exists */
uint8_t const O_EXCL = 0X20;
/** truncate the file to zero length */
uint8_t const O_TRUNC = 0X40;

PaulS, I'm having a bit of a trouble comprehending the code.
Could you decipher it for me ? :confused:

If you want to truncate the file, use O_TRUNC as the 2nd argument.

Hey !
Continuing on the topic, PaulS, I made the adjustments to the code and combined it with the code you provided, yet I’ve reached an impasse.
Here’s the code :-

#include<Wire.h>
#include<SD.h>
#include<dht.h>
dht DHT;
long id=0; //default ID number
int flag=0; //for debugging
const int flux=A0; //LDR
const int temp_humid=6; //DHT sensor
const int moisture=A3; //Soil moisture sensor
const int CS=10; //Chip Select for SD Module
const int power=2; //Power pin for SD Module
#define address 0x68
int decToBcd(int val)
{
  return( (val/10*16) + (val%10) );
}
int bcdToDec(int val)
{
  return( (val/16*10) + (val%16) );
}
void setup()
{
  Wire.begin();
  pinMode(flux,INPUT_PULLUP); //for light
  pinMode(CS,OUTPUT); //chip select
  pinMode(power,OUTPUT); //power for SD card
  pinMode(temp_humid,INPUT); //DHT sensor
  pinMode(moisture,INPUT); //Soil Moisture sensor
  digitalWrite(power,HIGH); //setting power pin to high for SD card
  Serial.begin(9600); //initializing Serial communication
  if(!SD.begin(CS))
  {
    Serial.println("Card failed");
  }
  else
  {
    Serial.println("Card loaded !");
  }
  File numberfile=SD.open("NUMBER_ID.txt",FILE_READ);
    if(numberfile)
    {
      Serial.println("Fetching Last ID");
      float decade=pow(10,(numberfile.available() - 1));
      while(numberfile.available())
      {
       float number=(numberfile.read()-'0');
       id=id+number*decade;
       decade=decade/10;
      }
       Serial.print("Last ID = ");
       Serial.println(id);
       !flag;
  }
  else
  {
    Serial.println("Couldn't fetch last ID");
    return;
  }
  File datafile=SD.open("log.csv",FILE_WRITE);
  if(datafile)
  {
    if(id==0 & flag==1)
    {
    String header="#,Temperature,Humidity,Light,Moisture,Date,Month,Year,Hour,Minute,Second,Day";
    datafile.println(header);
    datafile.close();
    }
  }
  else
  {
    Serial.println("Couldn't open Log file");
  }
 //setDS3231time(30,42,21,4,26,11,14);
}
void setDS3231time(int second, int minute, int hour, int dayOfWeek, int dayOfMonth, int month, int year)
{
  // sets time and date data to DS3231
  Wire.beginTransmission(address);
  Wire.write(0); // set next input to start at the seconds register
  Wire.write(decToBcd(second)); // set seconds
  Wire.write(decToBcd(minute)); // set minutes
  Wire.write(decToBcd(hour)); // set hours
  Wire.write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday)
  Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31)
  Wire.write(decToBcd(month)); // set month
  Wire.write(decToBcd(year)); // set year (0 to 99)
  Wire.endTransmission();
}
void readDS3231time(int *second, int *minute, int *hour, int *dayOfWeek, int *dayOfMonth, int *month, int *year)
{
  Wire.beginTransmission(address);
  Wire.write(0); // set DS3231 register pointer to 00h
  Wire.endTransmission();
  Wire.requestFrom(address, 7);
  // request seven bytes of data from DS3231 starting from register 00h
  *second = bcdToDec(Wire.read() & 0x7f);
  *minute = bcdToDec(Wire.read());
  *hour = bcdToDec(Wire.read() & 0x3f);
  *dayOfWeek = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month = bcdToDec(Wire.read());
  *year = bcdToDec(Wire.read());
}
void Weekday(int l,char s[10]) //for converting number to Day of Week
{
  if(l==1)
  strcpy(s,"Sunday");
  else if(l==2)
  strcpy(s,"Monday");
  else if(l==3)
  strcpy(s,"Tuesday");
  else if(l==4)
  strcpy(s,"Wednesday");
  else if(l==5)
  strcpy(s,"Thursday");
  else if(l==6)
  strcpy(s,"Friday");
  else if(l==7)
  strcpy(s,"Saturday");
}
float ldrsensor() //function for retrieving light percentage
{
  float val;
  val=analogRead(flux);
  val=map(val,15,1005,100,0);
  return val;
}
void loop()
{
 float light; //variable for retrieving light value
 light=ldrsensor();
 char s[10];
 int moisturelevel=map(analogRead(moisture),0,1023,100,0);
 DHT.read11(temp_humid); //reading DHT sensor data
 int second, minute, hour, dayOfWeek, dayOfMonth, month, year; //variables for retrieving RTC data
 readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year); //reading RTC data
 File datafile=SD.open("log.csv",FILE_WRITE);
 Weekday(dayOfWeek,s);
 if(datafile)
 {
   id++;
   String carddata=String(id)+", "+String(DHT.temperature)+", "+String(DHT.humidity)+", "+String(light)+", "+String(moisturelevel)+", "+String(dayOfMonth)+", "+String(month)+", "+String(year)+", "+String(hour)+", "+String(minute)+", "+String(second)+", "+String(s);
   String metadata=String(id)+", "+String(DHT.temperature)+" C "+String(DHT.humidity)+"% "+String(light)+"% "+String(moisturelevel)+"% "+String(dayOfMonth)+"/"+String(month)+"/"+String(year)+" "+String(hour)+":"+String(minute)+":"+String(second)+" "+String(s);
   Serial.println(metadata);
   datafile.println(carddata);
   datafile.close();
   File numberfile=SD.open("NUMBER_ID.txt",O_TRUNC);
   if(numberfile);
   {
    numberfile.println(id);
    numberfile.close();
   }
 }
 else
 {
   Serial.println("Can't save to card");
 }
 delay(1000);
}

I created a flag variable for debugging purposes, so as to see whether or not the Arduino was even able to read the last ID from the NUMBER_ID.txt file. So as to create the file header only if the last ID has been read successfully, I made an if statement before publishing the header onto the log.csv file. But the problem is that the Arduino is not able to read the last ID, and yet publishes the header. Another problem I’m encountering is that the ID is not being replaced in the NUMBER.txt file even after using the “truncation” argument as provided.So basically, the ID always remains 0 in the file. How on earth is that possible ? Can anyone look into it please ?

  File numberfile=SD.open("NUMBER_ID.txt",FILE_READ);

How many letters are in that name? How many letters are allowed?

      float decade=pow(10,(numberfile.available() - 1));

pow() is crappy way to raise 10 to the nth power. pow() performs floating point arithmetic, crudely, and returns a float. Why do you need a float? It is not difficult to create a function that multiplies a value (10 initially) by another value (10 always) n times.

       !flag;

This is about as useful as:

      10 + 7;
    String header="#,Temperature,Humidity,Light,Moisture,Date,Month,Year,Hour,Minute,Second,Day";
    datafile.println(header);

What a f**king waste of resources.

   datafile.println(F("#,Temperature,Humidity,Light,Moisture,Date,Month,Year,Hour,Minute,Second,Day"));

Hey,
PaulS, I rectified the goofs I made in the code and uploaded it.
This instance, the last ID is fetched from “ID.txt” and displayed on the Serial Monitor before starting the datalogging. However, even though I had set the default ID to 0 in the file, I get a -387 as the last ID. How is this possible ?

Here’s the updated code:-

#include<Wire.h>
#include<SD.h>
#include<dht.h>
dht DHT;
long id=0; //default ID number
int flag=1; //for debugging
const int flux=A0; //LDR
const int temp_humid=6; //DHT sensor
const int moisture=A3; //Soil moisture sensor
const int CS=10; //Chip Select for SD Module
const int power=2; //Power pin for SD Module
#define address 0x68
int decToBcd(int val)
{
  return( (val/10*16) + (val%10) );
}
int bcdToDec(int val)
{
  return( (val/16*10) + (val%16) );
}
void setup()
{
  Wire.begin();
  pinMode(flux,INPUT_PULLUP); //for light
  pinMode(CS,OUTPUT); //chip select
  pinMode(power,OUTPUT); //power for SD card
  pinMode(temp_humid,INPUT); //DHT sensor
  pinMode(moisture,INPUT); //Soil Moisture sensor
  digitalWrite(power,HIGH); //setting power pin to high for SD card
  Serial.begin(9600); //initializing Serial communication
  if(!SD.begin(CS))
  {
    Serial.println("Card failed");
  }
  else
  {
    Serial.println("Card loaded !");
  }
  File numberfile=SD.open("ID.txt",FILE_READ);
    if(numberfile)
    {
      Serial.println("Fetching Last ID");
      float decade=pow(10,(numberfile.available() - 1));
      while(numberfile.available())
      {
       float number=(numberfile.read()-'0');
       id=id+number*decade;
       decade=decade/10;
      }
      Serial.print("Last ID = ");
      Serial.println(id);
      flag=flag-1;
      numberfile.close();   
   }
  else
  {
    Serial.println("Couldn't fetch last ID.");
    return;
  }
  File datafile=SD.open("log.csv",FILE_WRITE);
  if(datafile)
  {
    if(id==0 & flag==0)
    {
    datafile.println("#,Temperature,Humidity,Light,Moisture,Date,Month,Year,Hour,Minute,Second,Day");
    datafile.close();
    }
  }
  else
  {
    Serial.println("Couldn't open Log file");
  }
 //setDS3231time(30,42,21,4,26,11,14);
}
void setDS3231time(int second, int minute, int hour, int dayOfWeek, int dayOfMonth, int month, int year)
{
  // sets time and date data to DS3231
  Wire.beginTransmission(address);
  Wire.write(0); // set next input to start at the seconds register
  Wire.write(decToBcd(second)); // set seconds
  Wire.write(decToBcd(minute)); // set minutes
  Wire.write(decToBcd(hour)); // set hours
  Wire.write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday)
  Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31)
  Wire.write(decToBcd(month)); // set month
  Wire.write(decToBcd(year)); // set year (0 to 99)
  Wire.endTransmission();
}
void readDS3231time(int *second, int *minute, int *hour, int *dayOfWeek, int *dayOfMonth, int *month, int *year)
{
  Wire.beginTransmission(address);
  Wire.write(0); // set DS3231 register pointer to 00h
  Wire.endTransmission();
  Wire.requestFrom(address, 7);
  // request seven bytes of data from DS3231 starting from register 00h
  *second = bcdToDec(Wire.read() & 0x7f);
  *minute = bcdToDec(Wire.read());
  *hour = bcdToDec(Wire.read() & 0x3f);
  *dayOfWeek = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month = bcdToDec(Wire.read());
  *year = bcdToDec(Wire.read());
}
void Weekday(int l,char s[10]) //for converting number to Day of Week
{
  if(l==1)
  strcpy(s,"Sunday");
  else if(l==2)
  strcpy(s,"Monday");
  else if(l==3)
  strcpy(s,"Tuesday");
  else if(l==4)
  strcpy(s,"Wednesday");
  else if(l==5)
  strcpy(s,"Thursday");
  else if(l==6)
  strcpy(s,"Friday");
  else if(l==7)
  strcpy(s,"Saturday");
}
float ldrsensor() //function for retrieving light percentage
{
  float val;
  val=analogRead(flux);
  val=map(val,15,1005,100,0);
  return val;
}
void loop()
{
 float light; //variable for retrieving light value
 light=ldrsensor();
 char s[10];
 int moisturelevel=map(analogRead(moisture),0,1023,100,0);
 DHT.read11(temp_humid); //reading DHT sensor data
 int second, minute, hour, dayOfWeek, dayOfMonth, month, year; //variables for retrieving RTC data
 readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year); //reading RTC data
 File datafile=SD.open("log.csv",FILE_WRITE);
 Weekday(dayOfWeek,s);
 if(datafile)
 {
   id++;
   String carddata=String(id)+", "+String(DHT.temperature)+", "+String(DHT.humidity)+", "+String(light)+", "+String(moisturelevel)+", "+String(dayOfMonth)+", "+String(month)+", "+String(year)+", "+String(hour)+", "+String(minute)+", "+String(second)+", "+String(s);
   String metadata=String(id)+", "+String(DHT.temperature)+" C "+String(DHT.humidity)+"% "+String(light)+"% "+String(moisturelevel)+"% "+String(dayOfMonth)+"/"+String(month)+"/"+String(year)+" "+String(hour)+":"+String(minute)+":"+String(second)+" "+String(s);
   Serial.println(metadata);
   datafile.println(carddata);
   datafile.close();
   File numberfile=SD.open("ID.txt",O_TRUNC);
   if(numberfile);
   {
    numberfile.println(id);
    numberfile.close();
   }
 }
 else
 {
   Serial.println("Can't save to card");
 }
 delay(1000);
}

And the worst part is, the datalogging doesn’t take place. The Serial Monitor, after fetching the last ID, looks like this :-
Card loaded !
Fetching Last ID
Last ID = -387

After this, no data is logged to the SD card.
Any leads on this ?

      float decade=pow(10,(numberfile.available() - 1));

10 * 10 * 10 * ... * 10 does NOT produce a float. So, why are you storing the value in a float?

       float number=(numberfile.read()-'0');

You read a character from the file. A character is an integral type. You subtract '0' (another integral value) from that. Then, you store the result in a float. Why?

Just what is in the file?

Have you printed the stuff read from the file?

What do you get when you subtract '0' from carriage return?
What do you get when you subtract '0' from line feed?

Does your file contain carriage returns or line feeds?

Hey !
PaulS, if I remember correctly, the numberfile.read() function returns the ASCII value of the number, so I used the ‘0’ to subtract that from the ASCII value, which then returns the original number. I have replaced the datatype of the ‘number’ variable to int, bearing in mind what you told me.
The numberfile (“ID.txt”) contains the number of datapoints stored in the “log.csv” file. See, the program reads the last ID of the datapoints, which by default is 0. When it reads the last ID, it starts measuring the temperature, humidity, luminous intensity, moisture level, and reads the time. It increments the value of the last ID, makes a string of the datapoints, and stores it in the “log.csv” function. The program opens the “ID.txt” file to store the last ID, so that in case the Arduino is reset or the power interrupted, the ID doesn’t roll back to 0 and create a mess of the number of datapoints I have. So whenever the data string is made, it opens the “ID.txt” file in TRUNC mode, truncates the file, stores the new ID, and closes it. The whole process is repeated, as evident by the code.
Now, the problem which I’m having is related to reading the “ID.txt” file. The program incorrectly reports the last ID as -387, which had a default vale of 0. So instead of spitting 0, it’s giving me a gibberish value of -387. The problem is further accentuated by the fact that after printing the last ID to the Serial Monitor, no datalogging takes place. I’m addled by this problem. So here’s the point at which nothing new is displayed. And no, the numberfile just contains a number.
Here’s the updated code:-

#include<Wire.h>
#include<SD.h>
#include<dht.h>
dht DHT;
long int id=0; //default ID number
int flag=1; //for debugging
const int flux=A0; //LDR
const int temp_humid=6; //DHT sensor
const int moisture=A3; //Soil moisture sensor
const int CS=10; //Chip Select for SD Module
const int power=2; //Power pin for SD Module
#define address 0x68
int decToBcd(int val)
{
  return( (val/10*16) + (val%10) );
}
int bcdToDec(int val)
{
  return( (val/16*10) + (val%16) );
}
void setup()
{
  Wire.begin();
  pinMode(flux,INPUT_PULLUP); //for light
  pinMode(CS,OUTPUT); //chip select
  pinMode(power,OUTPUT); //power for SD card
  pinMode(temp_humid,INPUT); //DHT sensor
  pinMode(moisture,INPUT); //Soil Moisture sensor
  digitalWrite(power,HIGH); //setting power pin to high for SD card
  Serial.begin(9600); //initializing Serial communication
  if(!SD.begin(CS))
  {
    Serial.println("Card failed");
  }
  else
  {
    Serial.println("Card loaded !");
  }
  File numberfile=SD.open("ID.txt");
    if(numberfile)
    {
      Serial.println("Fetching Last ID");
      int decade=pow(10,(numberfile.available() - 1));
      int number;
      while(numberfile.available())
      {
       number=(numberfile.read()-'0');
       id=(number*decade)+id;
       decade=decade/10;
      }
      Serial.print("Last ID = ");
      Serial.println(id);
      flag=flag-1;
      numberfile.close();   
   }
  else
  {
    Serial.println("Couldn't fetch last ID.");
    return;
  }
  File datafile=SD.open("log.csv",FILE_WRITE);
  if(datafile)
  {
    if(id==0 & flag==0)
    {
    datafile.println("#,Temperature,Humidity,Light,Moisture,Date,Month,Year,Hour,Minute,Second,Day");
    datafile.close();
    }
  }
  else
  {
    Serial.println("Couldn't open Log file");
  }
 //setDS3231time(30,42,21,4,26,11,14);
}
void setDS3231time(int second, int minute, int hour, int dayOfWeek, int dayOfMonth, int month, int year)
{
  // sets time and date data to DS3231
  Wire.beginTransmission(address);
  Wire.write(0); // set next input to start at the seconds register
  Wire.write(decToBcd(second)); // set seconds
  Wire.write(decToBcd(minute)); // set minutes
  Wire.write(decToBcd(hour)); // set hours
  Wire.write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday)
  Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31)
  Wire.write(decToBcd(month)); // set month
  Wire.write(decToBcd(year)); // set year (0 to 99)
  Wire.endTransmission();
}
void readDS3231time(int *second, int *minute, int *hour, int *dayOfWeek, int *dayOfMonth, int *month, int *year)
{
  Wire.beginTransmission(address);
  Wire.write(0); // set DS3231 register pointer to 00h
  Wire.endTransmission();
  Wire.requestFrom(address, 7);
  // request seven bytes of data from DS3231 starting from register 00h
  *second = bcdToDec(Wire.read() & 0x7f);
  *minute = bcdToDec(Wire.read());
  *hour = bcdToDec(Wire.read() & 0x3f);
  *dayOfWeek = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month = bcdToDec(Wire.read());
  *year = bcdToDec(Wire.read());
}
void Weekday(int l,char s[10]) //for converting number to Day of Week
{
  if(l==1)
  strcpy(s,"Sunday");
  else if(l==2)
  strcpy(s,"Monday");
  else if(l==3)
  strcpy(s,"Tuesday");
  else if(l==4)
  strcpy(s,"Wednesday");
  else if(l==5)
  strcpy(s,"Thursday");
  else if(l==6)
  strcpy(s,"Friday");
  else if(l==7)
  strcpy(s,"Saturday");
}
float ldrsensor() //function for retrieving light percentage
{
  float val;
  val=analogRead(flux);
  val=map(val,15,1005,100,0);
  return val;
}
void loop()
{
 float light; //variable for retrieving light value
 light=ldrsensor();
 char s[10];
 int moisturelevel=map(analogRead(moisture),0,1023,100,0);
 DHT.read11(temp_humid); //reading DHT sensor data
 int second, minute, hour, dayOfWeek, dayOfMonth, month, year; //variables for retrieving RTC data
 readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year); //reading RTC data
 File datafile=SD.open("log.csv",FILE_WRITE);
 Weekday(dayOfWeek,s);
 if(datafile)
 {
   id++;
   String carddata=String(id)+", "+String(DHT.temperature)+", "+String(DHT.humidity)+", "+String(light)+", "+String(moisturelevel)+", "+String(dayOfMonth)+", "+String(month)+", "+String(year)+", "+String(hour)+", "+String(minute)+", "+String(second)+", "+String(s);
   String metadata=String(id)+", "+String(DHT.temperature)+" C "+String(DHT.humidity)+"% "+String(light)+"% "+String(moisturelevel)+"% "+String(dayOfMonth)+"/"+String(month)+"/"+String(year)+" "+String(hour)+":"+String(minute)+":"+String(second)+" "+String(s);
   Serial.println(metadata);
   datafile.println(carddata);
   datafile.close();
   File numberfile=SD.open("ID.txt",O_TRUNC);
   if(numberfile);
   {
    numberfile.println(id);
    numberfile.close();
   }
 }
 else
 {
   Serial.println("Can't save to card");
 }
 delay(1000);
}

I need a shot in the arm, folks ! PaulS, any leads on this ?

PaulS, if I remember correctly, the numberfile.read() function returns the ASCII value of the number, so I used the '0' to subtract that from the ASCII value, which then returns the original number. I have replaced the datatype of the 'number' variable to int, bearing in mind what you told me.

The read() method returns a character. If the character is a digit, you can get the numeric value by subtracting '0'.

If you read a '7', and subtract '0' from it, you get 7. Great.

But, what happens if you read a ' ' or a '\n' or a '\r'? You need to check that the value that you read is between '0' and '9' BEFORE you use the value that you read.

The numberfile ("ID.txt") contains the number of datapoints stored in the "log.csv" file.

Just one record?

Now, the problem which I'm having is related to reading the "ID.txt" file.

I don't think that it is. I think that the problem is that you are trying to create a csv file that has a column that contains a number that is equal to the row number when you open the file in Excel. And, that is useless. Excel KNOWS what row the data is on. It really does not need your help to figure that out.

But, if you insist on doing that, you still need to explain what that mess of code that reads the ID file is doing. It is far too complicated.

You KNOW that the data file will not contain more than records than can be represented in an unsigned long (4,294,967,295). Without the commas, there are 10 digits in the number. An array of 12 characters is plenty to hold all the digits and the terminating NULL.

Read the data in the file. Store each character in the next position of the array. When you reach the end of the file, call strtoul() to convert the array to a numeric value.

Look at your code for dealing with writing the header to log file. If id is 0, you write to the file and close it.

If the id is not 0, you do not close the file. Oops.

Hey !
Sorry, I was AFK for a while !
PaulS, I'm having some trouble comprehending the remedies you're suggesting.
See, the first problem is regarding the usage of O_TRUNC. PaulS, you said that it truncates the file, rendering it empty. But the thing is, I tried truncating the file and writing a new number, but that doesn't happen. The original number stays there, and the new number doesn't replace it. Could it be possible that this function doesn't work ? Or could it be a bug in the code.
Any light over this, guys ?

Any light over this, guys ?

Without seeing your code? No.

Without seeing your code? No.

Hey PaulS !
The code is the same as contained in the previous posts.
The O_TRUNC argument is raising some eyebrows.
The thing is, I checked and rechecked the SD card file after every operation. The O_TRUNC argument isn't working the way it's supposed to be, and isn't truncating the file.
Please, any light over this would be helpful.

Why not write some SHORT sketch to test the SD functionality? It is NOT necessary to have valid data to assure that you can open a file for write, truncating the contents, and write a new value.

I do not see where you open a file using O_TRUNC in the last code you posted.

Hey PaulS !
I’ll post the code again to clear the air regarding the supposedly missing TRUNC mode.
Here :-

#include<Wire.h>
#include<SD.h>
#include<dht.h>
dht DHT;
long int id=0; //default ID number
int flag=1; //for debugging
const int flux=A0; //LDR
const int temp_humid=6; //DHT sensor
const int moisture=A3; //Soil moisture sensor
const int CS=10; //Chip Select for SD Module
const int power=2; //Power pin for SD Module
#define address 0x68
int decToBcd(int val)
{
  return( (val/10*16) + (val%10) );
}
int bcdToDec(int val)
{
  return( (val/16*10) + (val%16) );
}
void setup()
{
  Wire.begin();
  pinMode(flux,INPUT_PULLUP); //for light
  pinMode(CS,OUTPUT); //chip select
  pinMode(power,OUTPUT); //power for SD card
  pinMode(temp_humid,INPUT); //DHT sensor
  pinMode(moisture,INPUT); //Soil Moisture sensor
  digitalWrite(power,HIGH); //setting power pin to high for SD card
  Serial.begin(9600); //initializing Serial communication
  if(!SD.begin(CS))
  {
    Serial.println("Card failed");
  }
  else
  {
    Serial.println("Card loaded !");
  }
  File numberfile=SD.open("ID.txt");
    if(numberfile)
    {
      Serial.println("Fetching Last ID");
      int decade=pow(10,(numberfile.available() - 1));
      int number;
      while(numberfile.available())
      {
       number=(numberfile.read()-'0');
       id=(number*decade)+id;
       decade=decade/10;
      }
      Serial.print("Last ID = ");
      Serial.println(id);
      flag=flag-1;
      numberfile.close();   
   }
  else
  {
    Serial.println("Couldn't fetch last ID.");
    return;
  }
  File datafile=SD.open("log.csv",FILE_WRITE);
  if(datafile)
  {
    if(id==0 & flag==0)
    {
    datafile.println("#,Temperature,Humidity,Light,Moisture,Date,Month,Year,Hour,Minute,Second,Day");
    datafile.close();
    }
  }
  else
  {
    Serial.println("Couldn't open Log file");
  }
 //setDS3231time(30,42,21,4,26,11,14);
}
void setDS3231time(int second, int minute, int hour, int dayOfWeek, int dayOfMonth, int month, int year)
{
  // sets time and date data to DS3231
  Wire.beginTransmission(address);
  Wire.write(0); // set next input to start at the seconds register
  Wire.write(decToBcd(second)); // set seconds
  Wire.write(decToBcd(minute)); // set minutes
  Wire.write(decToBcd(hour)); // set hours
  Wire.write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday)
  Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31)
  Wire.write(decToBcd(month)); // set month
  Wire.write(decToBcd(year)); // set year (0 to 99)
  Wire.endTransmission();
}
void readDS3231time(int *second, int *minute, int *hour, int *dayOfWeek, int *dayOfMonth, int *month, int *year)
{
  Wire.beginTransmission(address);
  Wire.write(0); // set DS3231 register pointer to 00h
  Wire.endTransmission();
  Wire.requestFrom(address, 7);
  // request seven bytes of data from DS3231 starting from register 00h
  *second = bcdToDec(Wire.read() & 0x7f);
  *minute = bcdToDec(Wire.read());
  *hour = bcdToDec(Wire.read() & 0x3f);
  *dayOfWeek = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month = bcdToDec(Wire.read());
  *year = bcdToDec(Wire.read());
}
void Weekday(int l,char s[10]) //for converting number to Day of Week
{
  if(l==1)
  strcpy(s,"Sunday");
  else if(l==2)
  strcpy(s,"Monday");
  else if(l==3)
  strcpy(s,"Tuesday");
  else if(l==4)
  strcpy(s,"Wednesday");
  else if(l==5)
  strcpy(s,"Thursday");
  else if(l==6)
  strcpy(s,"Friday");
  else if(l==7)
  strcpy(s,"Saturday");
}
float ldrsensor() //function for retrieving light percentage
{
  float val;
  val=analogRead(flux);
  val=map(val,15,1005,100,0);
  return val;
}
void loop()
{
 float light; //variable for retrieving light value
 light=ldrsensor();
 char s[10];
 int moisturelevel=map(analogRead(moisture),0,1023,100,0);
 DHT.read11(temp_humid); //reading DHT sensor data
 int second, minute, hour, dayOfWeek, dayOfMonth, month, year; //variables for retrieving RTC data
 readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year); //reading RTC data
 File datafile=SD.open("log.csv",FILE_WRITE);
 Weekday(dayOfWeek,s);
 if(datafile)
 {
   id++;
   String carddata=String(id)+", "+String(DHT.temperature)+", "+String(DHT.humidity)+", "+String(light)+", "+String(moisturelevel)+", "+String(dayOfMonth)+", "+String(month)+", "+String(year)+", "+String(hour)+", "+String(minute)+", "+String(second)+", "+String(s);
   String metadata=String(id)+", "+String(DHT.temperature)+" C "+String(DHT.humidity)+"% "+String(light)+"% "+String(moisturelevel)+"% "+String(dayOfMonth)+"/"+String(month)+"/"+String(year)+" "+String(hour)+":"+String(minute)+":"+String(second)+" "+String(s);
   Serial.println(metadata);
   datafile.println(carddata);
   datafile.close();
   File numberfile=SD.open("ID.txt",O_TRUNC);
   if(numberfile)
   {
    numberfile.println(id);
    numberfile.close();
   }
 }
 else
 {
   Serial.println("Can't save to card");
 }
 delay(1000);
}

As you can see, I’ve already incorporated the TRUNC mode as you’d suggested. Here :-

 File numberfile=SD.open("ID.txt",O_TRUNC);
   if(numberfile)
   {
    numberfile.println(id);
    numberfile.close();
   }

As you were suggesting, I decided to test the TRUNC functionality in a standalone mode.
Bottom line, it didn’t work. Could it be that the TRUNC mode doesn’t work ?
I used this code, which deletes and recreates a file to overwrite the number onto the file. The code works smoothly, albeit with a few hitches. Sometimes, when I try to read the file on the computer, I get an “Invalid MS-DOS” error, whatever that means.
Here’s the code for the aforementioned scenario :-

#include<SD.h>
const int CS=10; // Chip select pin 
const int power=2; // Power pin
int id=0; // numbering purpose
int rate=300; //refresh rate for overwriting
void setup()
{
  Serial.begin(9600);
  pinMode(CS,OUTPUT);
  pinMode(power,OUTPUT);
  digitalWrite(power,HIGH);
  if(!SD.begin(CS))
  {
    Serial.println("Couldn't Start card loading");
  }
  Serial.println("Card loaded and set to go!");
  File datafile=SD.open("ID.txt",FILE_WRITE);
  if(datafile)
  {
    datafile.print(id);
    datafile.close();
    Serial.print(id);
    Serial.println(" saved to SD card ");
  }
  else
  {
    Serial.println("Couldn't save the number");
  }
}
void loop()
{
  if(SD.exists("ID.txt"))
  {
  Serial.println("ID.txt exists in the SD Card");
  id++;
  }
  else
  {
  Serial.println("ID.txt doesn't exist in the SD Card");
  }
  SD.remove("ID.txt"); // remove the existing file
  File datafile=SD.open("ID.txt",FILE_WRITE); // create a new file
  if(datafile) 
  {
    datafile.print(id); // creates the same file and overwrites the number
    datafile.close();
    Serial.print("Number overwritten is");
    Serial.println(id);
  }
  delay(rate);
}

So, as I was saying, isn’t there a way to using the TRUNC mode ?
I’m really eager to use it rather than deleting and recreating a file each instance.
Any help on this, PaulS ?

O_TRUNC is not meant to be used alone. It is meant to be used in conjunction with O_WRITE and O_CREAT.

Hey, PaulS !
I’ve tweaked the code as you’ve suggested, and made a test sketch which will write a new number to the file ID.txt.
Check it out :-

#include<SD.h>
const int CS=10;
const int power=2;
int id=0;
int rate=1000;
void setup()
{
  Serial.begin(9600);
  pinMode(CS,OUTPUT);
  pinMode(power,OUTPUT);
  digitalWrite(power,HIGH);
  if(!SD.begin(CS))
  {
    Serial.println("Card not loaded");
  }
  else
  Serial.println("Card ready");
  File datafile=SD.open("ID.txt",FILE_WRITE);
  if(datafile)
  {
    datafile.print(id);
    datafile.close();
    Serial.print(id);
    Serial.println(" saved to SD card ");
  }
  else
  {
    Serial.println("Couldn't save the number");
  }
}
void loop()
{
  id++;
  File datafile=SD.open("ID.txt",O_WRITE & O_TRUNC);
  if(datafile)
  {
    datafile.print(id);
    datafile.close();
    Serial.print("Number overwritten is ");
    Serial.println(id);
  }
  delay(rate);
}

However, I’m eyeing an anomaly. This code isn’t working. The truncation and the writing of the new number isn’t happening.
What could be the problem, PaulS?