Adding a RTC to Arduino DataLogger (Solved with code posted) ongoing project.

Project includes
(2) 30amp current sensors
(2) voltage sensors
(1) Light detector sensor
(1) SD card
(1) 20x4 LCD
Arduino Mega
Arduino Mega Sensor shield

I took the DataLogger example and tweaked it to what i am looking for. it's not perfect and that might be part of my problem but the bigger part of the problem is knowing where and how to insert the info into the datastring is my biggest problem.

The LCD portion is very rough. when i get 4 digit values and they return to lower values i have ghost characters that do not clear out but that is a different issue all together.

Below is the modified code.
Please note this works perfectly i just want to add a date and time to the end when the reading was taken.

#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
const int chipSelect = 10;
LiquidCrystal_I2C lcd(0x27,20,4);

void setup()
{
 pinMode(10, OUTPUT);
 digitalWrite(10, HIGH);
 pinMode(53, OUTPUT);
 lcd.init(); 
 lcd.backlight();
 Serial.begin(9600);
 Serial.print("Initializing SD card...");
 lcd.setCursor(0, 0);
 lcd.print("Prepare SD card");
 delay(2000);
 if (!SD.begin(chipSelect)) {
 Serial.println("Card failed, or not present");
 lcd.setCursor(0,1);
 lcd.print("Card Failed");
 while (1);
 }
 Serial.println("card initialized.");
 lcd.setCursor(0,1);
 lcd.print("Card Ready");
 delay(3000);
 lcd.init();
 delay(2000);
}

void loop() {
  // make a string for assembling the data to log:
  String dataString = "";

  // read three sensors and append to the string:
  for (int analogPin = 0; analogPin < 5; analogPin++) {
    int sensor = analogRead(analogPin);
    dataString += String(sensor);
    if (analogPin < 4) {
      dataString += ",";
    }
  }

  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  File dataFile = SD.open("datalog.txt", FILE_WRITE);

  // if the file is available, write to it:
  if (dataFile) {
    dataFile.println(dataString);
    dataFile.close();
    // print to the serial port too:
    Serial.println(dataString);
    lcd.setCursor(0,0);
    lcd.print(dataString);
  }
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening datalog.txt");
    lcd.setCursor(0,0);
    lcd.print("Error datalog.txt");
    
  }
  delay(500);
}

I am trying to incorporate RTClib DS3231 into the code but i do not think that is what i need to do. that code is.

// Date and time functions using a DS3231 RTC connected via I2C and Wire lib
#include <Wire.h>
#include "RTClib.h"

RTC_DS3231 rtc;

char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

void setup () {

#ifndef ESP8266
  while (!Serial); // for Leonardo/Micro/Zero
#endif

  Serial.begin(9600);

  delay(3000); // wait for console opening

  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }

  if (rtc.lostPower()) {
    Serial.println("RTC lost power, lets set the time!");
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
  }
}

void loop () {
    DateTime now = rtc.now();
    
    Serial.print(now.year(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.day(), DEC);
    Serial.print(" (");
    Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
    Serial.print(") ");
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println();
    
    Serial.print(" since midnight 1/1/1970 = ");
    Serial.print(now.unixtime());
    Serial.print("s = ");
    Serial.print(now.unixtime() / 86400L);
    Serial.println("d");
    
    // calculate a date which is 7 days and 30 seconds into the future
    DateTime future (now + TimeSpan(7,12,30,6));
    
    Serial.print(" now + 7d + 30s: ");
    Serial.print(future.year(), DEC);
    Serial.print('/');
    Serial.print(future.month(), DEC);
    Serial.print('/');
    Serial.print(future.day(), DEC);
    Serial.print(' ');
    Serial.print(future.hour(), DEC);
    Serial.print(':');
    Serial.print(future.minute(), DEC);
    Serial.print(':');
    Serial.print(future.second(), DEC);
    Serial.println();
    
    Serial.println();
    delay(3000);
}

Will I be able to merge these 2 codes and get them to do what I want or do I need to be looking else where?

Using cut and paste to get the RTC code into the first code You ought to manage. Start cut/paste the #include and defining statements, compile and run the code. Then do the same for Setup(). Apply the RTC code the same way.
Some more experienced member needs to tell if any pin changes are needed.

you are right i should have done that.

here is the code that is close to what i am looking for.
however i want it all on one line and to be written to the SD card.

A0,A1,A2,A3,A4,Date,Time

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

RTC_DS3231 rtc;
const int chipSelect = 10;
LiquidCrystal_I2C lcd(0x27,20,4);

void setup()
{
 pinMode(10, OUTPUT);
 digitalWrite(10, HIGH);
 pinMode(53, OUTPUT);
 lcd.init(); 
 lcd.backlight();
 Serial.begin(9600);
 Serial.print("Initializing SD card...");
 lcd.setCursor(0, 0);
 lcd.print("Prepare SD card");
 delay(2000);
 if (!SD.begin(chipSelect)) {
 Serial.println("Card failed, or not present");
 lcd.setCursor(0,1);
 lcd.print("Card Failed");
 while (1);
 }
 Serial.println("card initialized.");
 lcd.setCursor(0,1);
 lcd.print("Card Ready");
 delay(3000);
 lcd.init();
 delay(2000);
}

void loop() {
  DateTime now = rtc.now();
    
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.day(), 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.println();
    delay(500);

  
  // make a string for assembling the data to log:
  String dataString = "";

  // read three sensors and append to the string:
  for (int analogPin = 0; analogPin < 5; analogPin++) {
    int sensor = analogRead(analogPin);
    dataString += String(sensor);
    if (analogPin < 4) {
      dataString += ",";
    }
  }

  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  File dataFile = SD.open("datalog.txt", FILE_WRITE);

  // if the file is available, write to it:
  if (dataFile) {
    dataFile.println(dataString);
    dataFile.close();
    // print to the serial port too:
    Serial.println(dataString);
    lcd.setCursor(0,0);
    lcd.print(dataString);
  }
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening datalog.txt");
    lcd.setCursor(0,0);
    lcd.print("Error datalog.txt");
    
  }
  delay(500);
}

You should have done….. and You have this code now. Does the handling of the analog I/O work all the way?

If it does just go on adding the date-time info to dataString before writing the string to the SD card.

yes the data records perfectly i just wanted to add a date and time.

Adding the string data is where i am getting lost.

I think this is where the code generates the datastring

dataString += String(sensor);

so breaking this line up.

dataString is where my sensors present their data.

+= is throwing me for a loop

String(sensor) is where the values of my 5 analog sensors reside.

So I need to find a way to add something like String(sensor,time) to this line and somehow define the proper layout of my time?

dataString += String(sensor) is the short way for dataString = String(sensor) + dataString.
There is a special manipulation to awoid adding a comma "," after the last analog data. Change that line.
You need to dig a little in the info about the RTC and how the data is represented.

I assume You have played with the RTC code You attached earlier. Look at this:

DateTime now = rtc.now();
    
    Serial.print(now.year(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.day(), DEC);
    Serial.print(" (");
    Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
    Serial.print(") ");
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println();

The varable "now" carries the info You need. Now it is "only" to add the now.year, now.month, now.day, now.hour, now.minute, now.seconds and the delimiting character You need to dataString. I searched the Arduino refernce to find the function that converts now.year to ASCII that can be added to dataString.
I hope there is a member that can step in and tell what that function is. I would guess IntToAsc if it exists.

Sorry. Correction: dataString = dataString + String(sensor).

What about this:

dataString+= String(now.year);
dataString+= '/';
dataString+= String(now.month);
dataString+= '/';
dataString+= String(now.day);
dataString+= ',';


dataString+= String(now.hour);
dataString+= ':';
dataString+= String(now.minute);
dataString+= ':';
dataString+= String(now.second);

Thank you for helping me understand the dataString += and the (now.whatever(),DEC); The secret to me was learning what the DEC was for and taking a step back to look at the project as a whole. Now I wonder what it would take to fix the LCD display and get rid of the ghost characters when it updates.

finalized code

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

RTC_DS3231 rtc;
const int chipSelect = 10;
LiquidCrystal_I2C lcd(0x27,20,4);

void setup()
{
 pinMode(10, OUTPUT);
 digitalWrite(10, HIGH);
 pinMode(53, OUTPUT);
 lcd.init(); 
 lcd.backlight();
 Serial.begin(9600);
 Serial.print("Initializing SD card...");
 lcd.setCursor(0, 0);
 lcd.print("Prepare SD card");
 delay(2000);
 if (!SD.begin(chipSelect)) {
 Serial.println("Card failed, or not present");
 lcd.setCursor(0,1);
 lcd.print("Card Failed");
 while (1);
 }
 Serial.println("card initialized.");
 lcd.setCursor(0,1);
 lcd.print("Card Ready");
 delay(3000);
 lcd.init();
 delay(2000);
}

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

  // make a string for assembling the data to log:
  String dataString = "";

  // read three sensors and append to the string:
  for (int analogPin = 0; analogPin < 5; analogPin++) {
    int sensor = analogRead(analogPin);
    dataString += String(sensor);
    if (analogPin < 4) {
      dataString += ",";
    }
  }
      dataString += ",";
      dataString += String(now.month(), DEC);
      dataString += "/";
      dataString += String(now.day(), DEC);
      dataString += "/";
      dataString += String(now.year(), DEC);
      dataString += ",";
      dataString += String(now.hour(), DEC);
      dataString += ":";
      dataString += String(now.minute(), DEC);
      dataString += ":";
      dataString += String(now.second(), DEC);


      
  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  File dataFile = SD.open("datalog.txt", FILE_WRITE);

  // if the file is available, write to it:
  if (dataFile) {
    dataFile.println(dataString);
    dataFile.close();
    // print to the serial port too:
    Serial.println(dataString);
    lcd.setCursor(0,0);
    lcd.print(dataString);
  }
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening datalog.txt");
    lcd.setCursor(0,0);
    lcd.print("Error datalog.txt");
    
  }
  delay(500);
}

I will give you kudos. Thank you so much Railroader

I don't know the function of DEC. Skip it in one place and see what You get, as a test.
Ghost charaters on LCD.... Clear the LCD, partly or totally, before You start writing. I use lcd.clear to clear the entire display. Else I use set cursor, write spaces and set cursor in the position for the message.

A small and not important suggestion:

Tidy up the code to this:

  for (int analogPin = 0; analogPin < 5; analogPin++) {
    int sensor = analogRead(analogPin);
    dataString += String(sensor);
//    if (analogPin < 4) {                   the comma sign is now needed, date/ time is added to string
      dataString += ",";
//    }                                              not needed
  }
//      dataString += ",";                                already done above
      dataString += String(now.month(), DEC);

Railroader:
A small and not important suggestion:

Tidy up the code to this:

  for (int analogPin = 0; analogPin < 5; analogPin++) {

Or better yet (imo) put all those {'s on their own lines:

  for (int analogPin = 0; analogPin < 5; analogPin++)
 {

Got my first real world data off the project this morning, WORKED LIKE A CHAMP!!! Thank you good sir (Railroader)for your pushing me in the right direction.

I will do my best to tidy the code up I really need to learn the standard of proper formatting as well. I have now come across my next add on to this code.

I would like to see it write a new file at the start of a new day so I don't get 7 days of data in a single file i would have 7 files.

So first problem is to have it make the filename as a date. then have it check to see if the file in use is current to the day if not create a new file.

I will start researching and see if this is possible.

It could clever to add some kind of end marker to rhe SD printed record. '/n', nill or someting.

Fine You got hold of things and it works.

Been looking at this for sometime today to the point i am nearing cross-eyed. I have read so many different approaches and so many people bickering that you should have done it this way and that way. So let me get an opinion on how I should approach this.

The above code works flawlessly,

Now I would like to take it to the next level.

I would like to have the day broken down 15 min intervals. I would like to continuously record data to the file like it does but create a new file every 15 mins and it's name would be the current year,month,day,hour,min.

So my options are I create a string that holds the file name and then called to create the file.

I think I will try to get this to work first.

I have noticed the same. Sometimes half a doussin members bombards You with more or less good advices, more or less important or relavant.

Go on with Your project. You know how to build text strings so building file names shouldn't be any problem. You also have time so picking the 15 minute moment to registrate shouldn't be a problem.

easier said than done :smiley: , so I've created the string and i can display and it looks correct. I stumbled upon an issue 8.3 but that is resolved as i can manually create large file names now. So no comes the hard part of how to use the string to fill in the blank on the datalog.txt file. any directional tips?

#include <SPI.h>
//#include <SD.h>
#include "SdFat.h"
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "RTClib.h"
SdFat SD;
RTC_DS3231 rtc;
const int chipSelect = 10;
LiquidCrystal_I2C lcd(0x27,20,4);

void setup()
{
 pinMode(10, OUTPUT);
 digitalWrite(10, HIGH);
 pinMode(53, OUTPUT);
 lcd.init(); 
 lcd.backlight();
 Serial.begin(9600);
 Serial.print("Initializing SD card...");
 lcd.setCursor(0, 0);
 lcd.print("Prepare SD card");
 delay(000);
 if (!SD.begin(chipSelect)) {
 Serial.println("Card failed, or not present");
 lcd.setCursor(0,1);
 lcd.print("Card Failed");
 while (1);
 }
 Serial.println("card initialized.");
 lcd.setCursor(0,1);
 lcd.print("Card Ready");
 delay(3000);
 lcd.clear();
 delay(2000);
}

void loop() {
  DateTime now = rtc.now();
  lcd.clear();
  // make a string for assembling the data to log:
  String dataString = "";
  String filename = "";

  // read three sensors and append to the string:
  for (int analogPin = 0; analogPin < 5; analogPin++) {
    int sensor = analogRead(analogPin);
    dataString += String(sensor);
    if (analogPin < 4) {
      dataString += ",";
    }
  }
      dataString += ",";
      dataString += String(now.month(), DEC);
      dataString += "/";
      dataString += String(now.day(), DEC);
      dataString += "/";
      dataString += String(now.year(), DEC);
      dataString += ",";
      dataString += String(now.hour(), DEC);
      dataString += ":";
      dataString += String(now.minute(), DEC);
      dataString += ":";
      dataString += String(now.second(), DEC);

      filename += ",";
      filename += String(now.year(), DEC);
      filename += String(now.month(), DEC);
      filename += String(now.day(), DEC);
      filename += String(now.hour(), DEC);
      filename += String(now.minute(), DEC);
      




      
  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  File dataFile = SD.open("123456789abcd.txt", FILE_WRITE);

  // if the file is available, write to it:
  if (dataFile) {
    dataFile.println(dataString);
    dataFile.close();
    // print to the serial port too:
    Serial.println(dataString);
    lcd.setCursor(0,0);
    lcd.print(dataString);
    lcd.setCursor(3,0);
    Serial.println(filename);
  }
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening datalog.txt");
    lcd.setCursor(0,0);
    lcd.print("Error datalog.txt");
    
  }
  delay(500);
}

here we go!!! This code will create a file on the SD card with the Year, Month, Day, Hour, and .txt as the file name. It will record 5 analog sensor inputs every half second and record them, it will also display them crudely on a 20x4 LCD. Every hour change a new file will be created and the next hours data will be recorded. I appriciate if someone could teach me the simplification process and point me in the right direction of how to properly format the code so it doesn't "hurt" the more advanced authors eyes.

thank you,

#include <SD.h>

#include "RTClib.h"

#include <Wire.h>

#include <string.h>



RTC_DS1307 RTC;

char filename[] = "00000000.CSV";

File myFile;



void setup()

{

Serial.begin(9600);

Wire.begin(); //Important for RTClib.h

RTC.begin();


if (! RTC.isrunning()) {

Serial.println("RTC is NOT running!");

// following line sets the RTC to the date & time this sketch was compiled

// RTC.adjust(DateTime(__DATE__, __TIME__));

return;

}


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);



if (!SD.begin(4)) {

Serial.println("initialization failed!");

return;

}

Serial.println("initialization done.");



}



void loop()

{

getFileName();

createFileName();

delay(3000);

}



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()

Serial.println(filename);

}



void createFileName(){

//Check file name exist?

if (SD.exists(filename)) {

Serial.println("exists.");

}

else {

Serial.println("doesn't exist.");

Serial.println("Creating new file");

Serial.println(filename);

myFile = SD.open(filename, FILE_WRITE);

myFile.close();

}

}

Any solution is a solution. Well done!
I made a short test, for Your Project.....

  int year, month;
  year = 19;
  month = 01;
 String test = "";
 test = String(year);
 test += '/';
 test+=String(month);
 test += '/';

Serial.println gives this:
19/1/

Okey if You accept that 1 - 9 only comes like a one digit char.

will that auto update to the next month and year?