Notifications
Clear all

RTC Project and Datalogging to an SD

27 Posts
5 Users
0 Likes
6,789 Views
Berner
(@berner)
Member
Joined: 5 years ago
Posts: 31
Topic starter  

I am hoping I can get some guidance on how to modify this DBWS sketch so it also logs the time, temp and humidity to a SD card. The project is referenced towards the end of this YT vid:

And the sketch is as follows:

/*
  Time, Temperature and Humidity
  time_temp_humid.ino
  Displays results on Serial Monitor
  Uses AM2320 I2C Temperature and Humidity sensor
  Uses DS1307 Real Time Clock
  Uses TimeLib Library
  Uses DS1307RTC Library
  Uses Adafruit AM2320 Library
 
  DroneBot Workshop 2019
  https://dronebotworkshop.com
*/
// Include required libraries
#include <Wire.h>
#include <TimeLib.h>
#include <DS1307RTC.h>
#include <Adafruit_AM2320.h>
// Define constant for RTC I2C Address
#define DS1307_CTRL_ID 0x68
// Define object am2320
Adafruit_AM2320 am2320 = Adafruit_AM2320();
// Variables to count square wave pulses
int ticks = 0;
int old_tick_value = 0;
// Variables for Humidity and Temperature
float h;
float t;
void setup() {
  Serial.begin(9600);
 
  // Attach Interrupt to pin D2
  attachInterrupt(0,handleInt,FALLING);
  // Set Square Wave at 1Hz
  setSQW(0x10);
 
  // Initialize Temp & Humid Sensor
  am2320.begin();
  delay(2000);
  // Read Humidity
  h = am2320.readHumidity();
  // Read temperature as Celsius
  t = am2320.readTemperature();
}
void loop() {
// Read Temp Humid sensor every 10 seconds   
if (ticks ==10){
   // Read Humidity
    h = am2320.readHumidity();
    // Read temperature as Celsius
    t = am2320.readTemperature();
    ticks = 0;
  }
// Update serial monitor display if a second has elapsed 
if (ticks != old_tick_value) {
        old_tick_value = ticks;
        printCurrentTime(h,t);
    }
}
// Interrupt Handler
void handleInt() {
  ticks++;
 
}
// Setup RTC Module for 1 Hz square wave
void setSQW(uint8_t value) {
  Wire.beginTransmission(DS1307_CTRL_ID);
  Wire.write(7);
  Wire.write(value);
  Wire.endTransmission();
}
// Format numbers as 2-digit numbers
void print2digits(int number) {
  if (number >= 0 && number < 10) {
    Serial.print('0');
  }
  Serial.print(number);
}
// Print to the serial monitor
void printCurrentTime(float hum, float tem){
tmElements_t tm;
  if (RTC.read(tm)) {
    print2digits(tm.Hour);
    Serial.print(':');
    print2digits(tm.Minute);
    Serial.print(':');
    print2digits(tm.Second);
    Serial.print(" - ");
    Serial.print(tmYearToCalendar(tm.Year));
    Serial.print('-');
    print2digits(tm.Month);
    Serial.print('-');
    print2digits(tm.Day);
    Serial.print(" Hum: ");
    Serial.print(hum);
    Serial.print("% - Temp: ");
    Serial.print(tem);
    Serial.print(" C");
   
    Serial.println();
  }
}

   
Quote
Robo Pi
(@robo-pi)
Robotics Engineer
Joined: 5 years ago
Posts: 1669
 
Posted by: @berner

I am hoping I can get some guidance on how to modify this DBWS sketch so it also logs the time, temp and humidity to a SD card. The project is referenced towards the end of this YT vid:

Bill has a video on how to use the SD card module here:

SD Card Experiments with Arduino

Once you have the SD card sketch up and running just add that capability to your time, temp and humidity sketch and save the info to the SD card instead of printing it to the serial monitor.

DroneBot Workshop Robotics Engineer
James


   
ReplyQuote
Berner
(@berner)
Member
Joined: 5 years ago
Posts: 31
Topic starter  

@robo-pi

Yes, I am familiar with this DWBS project, and am trying to use that code to combine with the other code (coding concepts trip me up, which is strange because I am an IT pro! yes, strange I know.....). Once I add the include statements for the SD libraries, define my write file and so on, I get confused on the mechanics of actually getting the data onto the SD. In the RTC/AM2320 sketch, there is a section for printing to the serial monitor. Is it as simple as adding a datafile.println(thingtobeprinted) to the "// Print to the serial monitor" section?


   
ReplyQuote
Robo Pi
(@robo-pi)
Robotics Engineer
Joined: 5 years ago
Posts: 1669
 
Posted by: @berner

Is it as simple as adding a datafile.println(thingtobeprinted) to the "// Print to the serial monitor" section?

Yes, it should be that simple.

Of course, you may potentially need to add additional code if you want to save the data in some special format, like say CSV.   In that case you'd need to include the commas at the proper places.

But other than this it should be as straight forward as just converting the Serial.print statements over to datafile.print statements once you have the SD card set up.  

P.S. Don't forget open SD card file for writing just before the datafile.print statements, and close it afterward.  I'm sure you knew that but thought I'd mention it anyway.

DroneBot Workshop Robotics Engineer
James


   
ReplyQuote
Berner
(@berner)
Member
Joined: 5 years ago
Posts: 31
Topic starter  

@robo-pi

Got it! I will work on this tonight when I get home. I do have another quick question.... On sketches that write to the serial monitor, is it an issue to leave that in the code if your intention is to have your gadget run without being connected to a computer?


   
ReplyQuote
Robo Pi
(@robo-pi)
Robotics Engineer
Joined: 5 years ago
Posts: 1669
 
Posted by: @berner

@robo-pi

Got it! I will work on this tonight when I get home. I do have another quick question.... On sketches that write to the serial monitor, is it an issue to leave that in the code if your intention is to have your gadget run without being connected to a computer?

No, it's no an issue.  You can leave the Serial.print statements in the code.   As long as you don't have any code that is waiting for the serial port to acknowledge a connection or is waiting for input you should be fine.

DroneBot Workshop Robotics Engineer
James


   
ReplyQuote
Berner
(@berner)
Member
Joined: 5 years ago
Posts: 31
Topic starter  

@robo-pi

I am working through this and making progress, but hitting a few snags that I need an assist with. At the bottom of the sketch, the  code deals with formatting single digit numbers as two digit numbers, then runs an "if" statement to output the data to the serial monitor. The code I am using from the SD card project also uses an "if" statement to verify the datalog file exists on the SD card prior to writing to it. I am not sure how to combine the two code parts so I can have the "print two digits" part work on my data written to the SD card. Here is the code from DBWS sketch and my attempt to add the data to an SD card.... thoughts?

 

// Format numbers as 2-digit numbers
void print2digits(int number) {
  if (number >= 0 && number < 10) {
    Serial.print('0');
  }
  Serial.print(number);
}


// Print to the serial monitor
void printCurrentTime(float hum, float tem){
tmElements_t tm;


  if (RTC.read(tm)) {
    print2digits(tm.Hour);
    Serial.print(':');
    print2digits(tm.Minute);
    Serial.print(':');
    print2digits(tm.Second);
    Serial.print(" - ");
    Serial.print(tmYearToCalendar(tm.Year));
    Serial.print('-');
    print2digits(tm.Month);
    Serial.print('-');
    print2digits(tm.Day);
    Serial.print(" Hum: ");
    Serial.print(hum);
    Serial.print("% - Temp: ");
    Serial.print(tem);
    Serial.print(" C");
   
    Serial.println();
  }


  // 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("datalog1.txt", FILE_WRITE);


  // if the file is available, write to it:
  if (dataFile) {
    dataFile.print(tm.Hour);
    dataFile.print(':');
    dataFile.print(tm.Minute);
    dataFile.print(':');
    dataFile.print(tm.Second);
    dataFile.print(" - ");
    dataFile.print(tmYearToCalendar(tm.Year));
    dataFile.print('-');
    dataFile.print(tm.Month);
    dataFile.print('-');
    dataFile.print(tm.Day);
    dataFile.print(" Hum: ");
    dataFile.print(hum);
    dataFile.print("% - Temp: ");
    dataFile.print(tem);
    dataFile.print(" C");
   
    dataFile.println();
    dataFile.close();
    // print to the serial port too:
    Serial.print(tem);
  }
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening datalog.txt");
  }

 


   
ReplyQuote
Robo Pi
(@robo-pi)
Robotics Engineer
Joined: 5 years ago
Posts: 1669
 
Posted by: @berner

Here is the code from DBWS sketch and my attempt to add the data to an SD card.... thoughts?

Ok, I have bloodshot eyes and I'm really tired, so beware of my current suggestions. ? 

Just off the top of my head it looks to me like all you need to do is create a new method for the SD card almost identical to the print2digits() method for the Serial.print section.

// Format numbers as 2-digit numbers
void print2digits(int number) {
  if (number >= 0 && number < 10) {
    Serial.print('0');
    
  }
  Serial.print(number);
}

Change the name of the NEW method to print2digits_SD and change the Serial.print statement to datafile.print statements like so:

// Format numbers as 2-digit numbers for SD Card
void print2digits_SD(int number) {
  if (number >= 0 && number < 10) {
    datafile.print('0');
  }
  datafile.print(number);
}

Then in your if(datafile) method change every other line to call the print2digits_SD() method just like was done in the Serial.print section above it.

Hopefully that will work.  If not, don't look at me, I'm pooped! ? 

DroneBot Workshop Robotics Engineer
James


   
ReplyQuote
(@pugwash)
Sorcerers' Apprentice
Joined: 5 years ago
Posts: 923
 

@berner @robo-pi

Sorry guys, but you have created an illusion which is unusable.

You are only outputting to the serial monitor a string("0") followed by a single integer, which is of no further use. To write anything to an SD card you have to stringify everything.

The following code will return a usable string, either two digits or zero followed by one digit, depending on what value is passed to the print2digits() function.

void setup() {
Serial.begin(9600);
Serial.println(print2digits_SD(8)); // choose one or two digit integer
}

void loop() {
// put your main code here, to run repeatedly:
}

String print2digits_SD(int number){
String tString = String(number);
if (tString.length() < 2){
tString = "0" + tString;
}
return tString;
}

Have fun!!


   
ReplyQuote
(@pugwash)
Sorcerers' Apprentice
Joined: 5 years ago
Posts: 923
 

@berner

Here is an example of something usable.

//this demo shows how to make up a time string separated
//by hyphens suitable to write to an SD card


void setup() {
Serial.begin(9600);
int hrs = 2;
int mins = 8;
int secs = 40;
String mString = print2digits_SD(hrs) + "-" + print2digits_SD(mins) + "-" + print2digits_SD(secs);
Serial.println(mString);
}

void loop() {
// put your main code here, to run repeatedly:

}

String print2digits_SD(int number){
String tString = String(number);
if (tString.length() < 2){
tString = "0" + tString;
}
return tString;
}

 


   
ReplyQuote
(@pugwash)
Sorcerers' Apprentice
Joined: 5 years ago
Posts: 923
 

@berner

If you want too, you can replace the latter part of your code with the following, it should produce the same results.


String print2digits(int number){
String tString = String(number);
if (tString.length() < 2){
tString = "0" + tString;
}
return tString;
}

// Print to the serial monitor
void printCurrentTime(float hum, float tem){
tmElements_t tm;
String dataString;
if (RTC.read(tm)) {
dataString = print2digits(tm.Hour) + ":" +
print2digits(tm.Minute) + ":" +
print2digits(tm.Second) + "-" +
tmYearToCalendar(tm.Year) + "-" +
print2digits(tm.Month) + "-" +
print2digits(tm.Day) +
" Hum: " + hum + "% - Temp: " + tem + " C" + "\n";

Serial.println(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("datalog1.txt", FILE_WRITE);

// if the file is available, write to it:
if (dataFile) {
dataFile.print(dataString);
dataFile.close();
}else {
Serial.println("error opening datalog.txt");
}
}

The dataString may need a bit of tweaking, but this code more compact and efficient.


   
ReplyQuote
Berner
(@berner)
Member
Joined: 5 years ago
Posts: 31
Topic starter  

@robo-pi

Thanks for this Robo….. I used your guidance to start noodling around and actually was writing something to a file on an SD card. The couldn't get everything just right, but that's how you learn stuff. I do have a silly question, when including code examples in the forum posts, how do you do it? I cannot find the right buttons to make it look as you do.


   
ReplyQuote
Berner
(@berner)
Member
Joined: 5 years ago
Posts: 31
Topic starter  
Posted by: @pugwash

@berner

If you want too, you can replace the latter part of your code with the following, it should produce the same results.


String print2digits(int number){
String tString = String(number);
if (tString.length() < 2){
tString = "0" + tString;
}
return tString;
}

// Print to the serial monitor
void printCurrentTime(float hum, float tem){
tmElements_t tm;
String dataString;
if (RTC.read(tm)) {
dataString = print2digits(tm.Hour) + ":" +
print2digits(tm.Minute) + ":" +
print2digits(tm.Second) + "-" +
tmYearToCalendar(tm.Year) + "-" +
print2digits(tm.Month) + "-" +
print2digits(tm.Day) +
" Hum: " + hum + "% - Temp: " + tem + " C" + "\n";

Serial.println(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("datalog1.txt", FILE_WRITE);

// if the file is available, write to it:
if (dataFile) {
dataFile.print(dataString);
dataFile.close();
}else {
Serial.println("error opening datalog.txt");
}
}

The dataString may need a bit of tweaking, but this code more compact and efficient.

Hey Pugwash,

This is exactly what I was attempting to accomplish! Once you clarified that data to a SD likes strings, this cleared things up a tad. Thanks for this, much appreciated. Now that I have a working sketch, my next goal is to tinker around with adding other sensors. I have a VEML6075 UV sensor, and a MCP9808 temp sensor that supposedly has better accuracy. I also have a few 16x2 LCD to play with.... all I2C with unique addresses. I have them all working independently, so now I will bring them into this sketch and find a way to data log them. 

Not sure if this is the place to ask this one, but does anyone know if the AM2320 is capable of outputting the temp in F? In my other test sketches I figured how to do it with a formula in the code, but just thought I would ask. Again..... thanks.


   
ReplyQuote
Robo Pi
(@robo-pi)
Robotics Engineer
Joined: 5 years ago
Posts: 1669
 
Posted by: @berner

I do have a silly question, when including code examples in the forum posts, how do you do it? I cannot find the right buttons to make it look as you do.

Here's how I do it.

  1. Select the code in the Arduino IDE that you want to post.
  2. Right-click and select "Copy to HTML" from the pop-up window in the Arduino IDE
  3. Then in the post editor here on the forums select the "source code" icon at the top of the screen {:}
  4. Paste the HTML formatted Arduino code into the dialog box
  5. Then click "OK'.
  6. It won't look correct in the post editor just yet, but,...
  7. If  you click on the "Preview" link at the bottom of the post editor it will show correctly in the preview.
  8. And of course, it should also then show correctly when you make the post.

This method will preserve both the code formatting and the color scheme.

DroneBot Workshop Robotics Engineer
James


   
ReplyQuote
(@pugwash)
Sorcerers' Apprentice
Joined: 5 years ago
Posts: 923
 

@berner

Not sure if this is the place to ask this one, but does anyone know if the AM2320 is capable of outputting the temp in F? In my other test sketches I figured how to do it with a formula in the code, but just thought I would ask. Again..... thanks.

I find it hard to believe you asked this question. ICs that output Fahrenheit are about as rare as "rocking horse manure". Fahrenheit is only kept to humor {American spelling) Americans! Other than that it is of no use at all and has to be calculated.

One day, we might even get them to stop measuring wavelength in feet and inches! ? ? ? ? ? 

Edit: I am not entirely correct, Fahrenheit can be used for calculating BTUs, but I prefer joules!


   
ReplyQuote
Page 1 / 2