SD Module - Writing timestamp to txt file & data from sensors

Hi everyone,
I need to write timestamp and data from DHT22 to a txt file in ths way:

"timestamp, humidity, temperature"

If possible, I need to create a new file a day named "[timestamp]_dhtData.txt"

I am newbie on Ardiuno and I have just some knowledge in programming languange.

I want solve problems by step.

I wrote code for DHT22 displaying infos for temp and humidity on a I2C 128x64 screen.

Now on a second breadboard I want test writing data on SD using RTC.

I set RTC and I have problem to write a timestamp to a file.

This is my code

#include <DS3231.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>

File myFile;

DS3231 Clock;

bool Century = false;
bool h12;
bool PM;
byte ADay, AHour, AMinute, ASecond, ABits;
bool ADy, A12h, Apm;


void setup() {
  // put your setup code here, to run once:
  Wire.begin();
  Serial.begin(9600);
}

void timestamp(String) {
  int second = Clock.getSecond();
  int minute = Clock.getMinute();
  int hour = Clock.getHour(h12, PM);
  int date = Clock.getDate();
  int month = Clock.getMonth(Century);
  int year = Clock.getYear();


  Serial.print("20");
  Serial.print(year, DEC);
  Serial.print('-');
  Serial.print(month, DEC);
  Serial.print('-');
  Serial.print(date, DEC);
  Serial.print(' ');
  Serial.print(hour, DEC);
  Serial.print(':');
  Serial.print(minute, DEC);
  Serial.print(':');
  Serial.print(second, DEC);
  Serial.print('\n');
}


void loop() {
  String time;
  timestamp(time);
  // put your main code here, to run repeatedly:
//opening file
  myFile = SD.open("test.txt", FILE_WRITE);

  // if the file opened okay, write to it:
  if (myFile) {
    Serial.print("Writing to test.txt...");
    myFile.println(timestamp(time));
    // close the file:
    myFile.close();
    Serial.println("done.");
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }
 
  delay(5000);

}

I know that my timestamp() function send output only on Serial monitor.
How can I write a valid function for a timestamp Srting result?

I think a String is needed for myFile.println() function.

Many thanks!

If you can print data to serial or display, you can print it to file

Serial.println(data);
lcd.print(data);
myFile.println(data);

Below are snippets to change filename at midnight

char filename[] = "00000000.CSV";
File myFile;
    GetClock();
    getFileName();


void loop() {

  GetClock();
  if (today != day)
  {
   today = day;
   getFileName(); 
  dailyheader();
  }

void getFileName(){
sprintf(filename, "%02d%02d%02d.csv", year, month, day);
}

Thanks 4 support!

How can I change this function?

void timestamp(String) {
  int second = Clock.getSecond();
  int minute = Clock.getMinute();
  int hour = Clock.getHour(h12, PM);
  int date = Clock.getDate();
  int month = Clock.getMonth(Century);
  int year = Clock.getYear();

myTime = here I need to have this : "2017-10-28: 18:25"


  }

I tink I cant do "myFile.println(timestamp())" in this way.

go3mon:
Thanks 4 support!

How can I change this function?

void timestamp(String) {

...
...
myTime = here I need to have this : "2017-10-28: 18:25"

}





I tink I cant do "myFile.println(timestamp())" in this way.

No, you indeed can't because the function does not return anything.

What is the function of String as a parameter to the function.

You can use something like below

char *timeStamp()
{
  int year = 2017;
  int month = 10;
  int day = 28;
  int hour = 18;
  int minute = 40;
  int second = 10;

  sprintf(buffer, "%04d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, minute, second);
  return buffer;
}

This will store the timestamp in a char buffer that is declared as a global variable. It also shows how to return the (pointer to) the buffer.

Net you can (example for setup)

// text buffer to hold yyyy-MM-dd HH:mm:ss
char buffer[20];

void setup()
{
  Serial.begin(9600);

  timeStamp();


  Serial.println(buffer);

  or

  Serial.println(timeStamp());

}

The first print prints the content of buffer; the second one basically does the same but by calling timestamp and using the returned pointer to the text. Note that if you use the latter three times, you might get different times if the time comes from the RTC as the seconds might have moved.

You can use something like below

What is the point in having a function return a global variable?

In this case, so you can print directly. OP asked for that.

Thanks to all! Finally I can write timestamp and data on file.

I have just 1 question.

I attached too an OLED display because I want read in real time Humidity and Temperature but data need to be stored on file ONLY using a delay of 10minutes.

How can I separate real time monitor from storing data on file??

void loop() {

  //float h = dht.readHumidity(); // Leggo il valore di umidità
  //float t = dht.readTemperature(); // Leggo il valore di temperatura

  u8g.firstPage();
  do {
    draw();
  } while ( u8g.nextPage() );

  delay(600000);

    myFile = SD.open(filename, FILE_WRITE);

      myFile.print(timeStamp());
      myFile.print(" ");
      myFile.print(dht.readHumidity());
      myFile.print(" ");
      myFile.println(dht.readTemperature());
      // close the file:
      myFile.close();
      Serial.println(" done.");

    //delay(600000);  // wait 10minutes

}

This is the final code

#include "U8glib.h"
#include "DHT.h"
#include <Wire.h>
#include <SPI.h>

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE | U8G_I2C_OPT_DEV_0); // I2C / TWI
DHT dht(2,DHT22); //Definisco il pin al quale è collegato il sensore e il tipo

float h;
float t;

void draw(void) {
  //u8g.setFont(u8g_font_unifont);
  //u8g.setFont(u8g_font_freedoomr10r);
  //u8g.setFont(u8g_font_gdr12);
  u8g.setFont(u8g_font_fur14);
  u8g.setPrintPos(0, 15);
  u8g.print("H:");
 // u8g.setPrintPos(30, 10);
  u8g.print(" ");
  u8g.print(h);
  //u8g.setPrintPos(80, 10);
  u8g.print(" %");
  u8g.setPrintPos(0,50);
  u8g.print("T:");
  //u8g.setPrintPos(30, 40);
  u8g.print(" ");
  u8g.print(t);
  //u8g.setPrintPos(80, 40);
  u8g.print(" ");
  u8g.write(0xB0); //write degree characher
  u8g.print("C");
}

void setup(void) {

  // assign default color value
  if ( u8g.getMode() == U8G_MODE_R3G3B2 ) {
    u8g.setColorIndex(255); // white

  }
  else if ( u8g.getMode() == U8G_MODE_GRAY2BIT ) {
    u8g.setColorIndex(3); // max intensity

  }
  else if ( u8g.getMode() == U8G_MODE_BW ) {
    u8g.setColorIndex(1); // pixel on

  }
  else if ( u8g.getMode() == U8G_MODE_HICOLOR ) {
    u8g.setHiColorByRGB(255, 255, 255);

  }
}

void loop(void) {
  h = dht.readHumidity();
  t = dht.readTemperature(); 
  // picture loop
  u8g.firstPage();
  do {
    draw();
  } while ( u8g.nextPage() );

  // rebuild the picture after some delay
  delay(2000);
}

How can I separate real time monitor from storing data on file??

You need to explain what this means. Do you want to average temperature data and humidity for 10 minutes and then write? Or, do you just want to write the current data once every 10 minutes?

  delay(600000);

So much for real-time monitoring. The blink without delay example shows how not to bury your head in the sand for any length of time.

Hi Paul,

I need to write data on sd card EVERY 10minutes and read info on display in real time (delay 2000).

go3mon:
I attached too an OLED display because I want read in real time Humidity and Temperature but data need to be stored on file ONLY using a delay of 10minutes.

What you are saying is not clear but by realtime, I assume you mean more frequently, say in a one second loop. You just need to enter a count condition in your loop whereby after 600 you send data to SD and reset the counter to zero. This will mean just that current data is recorded. If you want all the data sent to SD, I guess you store it in an array and then dump it after ten minutes.

and read info on display in real time (delay 2000).

Wrong. Real-time means NO delay.

I read that is needed a delay of 2 seconds for updating data from DHT sensor...

OK I try to be more clear.

I want read DHT data on display in real time or with a small delay (just time to refresh data from DHT), and I need to store data on SD every 10minutes because I need to make a statistic during 24h.

How is possible to do that inside the loop() function?

I want read DHT data on display in real timeas often as possible

There, I fixed that for you.

Now that we are no longer stuck on real-time, we can make progress.

How is possible to do that inside the loop() function?

Did I mention the blink without delay example? I do believe I did.

void loop() {
int  count = 0;

  u8g.firstPage();
  do {
    draw();
  } while ( u8g.nextPage() );

  delay(2000);

  if (count < 5){

      count++;
  }
  else if (count = 5){
        myFile = SD.open(filename, FILE_WRITE);

      myFile.print(timeStamp());
      myFile.print(" ");
      myFile.print(dht.readHumidity());
      myFile.print(" ");
      myFile.println(dht.readTemperature());
      // close the file:
      myFile.close();
      Serial.println(" done.");
  }

}
  else if (count = 5){

Assigning the value 5 to count in an if statement is rarely the right thing to do.

Showing the temperature every 2 seconds, and logging it every 10 minutes, requires a count of more than 5.

Sorry for my english and sorry I'm a newbie in programming C.

I solved.

int count = 0;

void loop() {

  u8g.firstPage();
  do {
    draw();
  } while ( u8g.nextPage() );
  delay(2000);
  count++;
  
  if (count == 300) {
    myFile = SD.open(filename, FILE_WRITE);

    myFile.print(timeStamp());
    myFile.print(" ");
    myFile.print(dht.readHumidity());
    myFile.print(" ");
    myFile.println(dht.readTemperature());
    // close the file:
    myFile.close();
    Serial.println(" done.");
    count = 0;
  }

go3mon:
I read that is needed a delay of 2 seconds for updating data from DHT sensor...

You never need to use delay but it is quite legitimate to do so. There are other more sophisticated methods

go3mon:
I want read DHT data on display in real time or with a small delay (just time to refresh data from DHT), and I need to store data on SD every 10minutes because I need to make a statistic during 24h.

How is possible to do that inside the loop() function?

Read reply#9 again. You can have a delay of two seconds in the loop thereby determining the loop time and a count therein so that you only record to SD once every 300 loops.

For all that, you might consider whether or why you really need to do this. IF are recording for only 24 hours, AND as I understand you are only using one temp/hum sensor, I bet you don't.