Newbie : Help required for DS1307 RTC time formatting

Hi All

Thanks all of you for an excellent resource..WOW

I have been dabbling with the Arduino UNO for a little while and finally decided to use it as the base of grow timer to activate led's.
After combing the extensive amount of examples to setup the DS1307 clock and set the time etc. I am at wits end and could really use a little help hence the reason I am posting this.

I am having a problem finding a nice simple working example for a few things that are required to make this little contraption work.

Problem 1.
Could someone please help me with a working example as a guide to convert a human time to a unix timestamp.

I am using the following code which allows me to match two times (now() and a time I set in the code) and trigger an event which is working so far but I realize it's probably easier to do comparisons with unix timestamps.

Please excuse any bad code and syntax and silly questions I may ask as I really am new at this and battling along in the dark.

The code I am using is as follows :

#include <Wire.h>
#include "RTClib.h"

RTC_DS1307 RTC;

int second = 0;       
int minute = 0;   
int hour = 0;      
int day = 0;    
int month = 0;   
int year = 0; 
int dayOfWeek = 0;

boolean aflag = false; // a flag to see if led should be on


void setup () {
  Wire.begin();
  RTC.begin(); 
  Serial.begin(9600);
  Serial.print("\nThe current date and time will be updated every one seconds - set delay in code to change:\n\n");
}

void loop() {

  DateTime now = RTC.now();


  Serial.print(now.dayOfWeek(), DEC);
  Serial.print(" day of week\n");    
  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.println(); 
  delay(1000);
  Serial.print(" since 1970 = ");
  Serial.print(now.unixtime());

  /* compare dayOfWeek, year, month, day, hour, minute, or second */
  if (now.year() == 2015 && now.month() == 4 && now.day() == 9 && now.hour()== 1 && now.minute()==55 && now.second()==0) {
    Serial.print("\n Let the sunshine in \n"); 
    boolean aflag=true;
    Serial.println(); 
    Serial.print(" the value of aflag is");
    Serial.print(aflag);
    Serial.println(); 
  }
  else {
    Serial.print("\n Nothing is happening it's dark now! \n");
  }  

}

I did find this this conversion method

#include <Wire.h>

#include <Time.h>


//struct tm t;
time_t tmConvert_t(int YYYY, byte MM, byte DD, byte hh, byte mm, byte ss)
{
  tmElements_t tmSet;
  tmSet.Year = YYYY - 1970;
  tmSet.Month = MM;
  tmSet.Day = DD;
  tmSet.Hour = hh;
  tmSet.Minute = mm;
  tmSet.Second = ss;
  return makeTime(tmSet); 
}

//and later on in main loop ...

time_t unix1 = tmConvert_t(2015,4,19,7,30,01);
  
  Serial.print("converted time is :");
  Serial.println(unix1);

which works fine if used with the Time.h library but does not work when I try to use it in the first bit of above code which uses the RTClib.h.

Where am I going wrong ? I would like to use RTClib.h

Problem 2

I would like to store each led number as well as two unix timestamps and the aflag value somewhere.
So for example I would like to store the following:
led_number, timestamp1, timestamp2, aflag_value

My first thought was an array but it's probably better to store the values in a struct which I believe from what I have read should be used when storing different data types (Correct me if I am wrong ?).

The reasons being :
A.
I don't know how many led's will be added on and would like to add them without having to change a max value of supported led's
Can this be done ? either in an array or struct ? can they be dynamically dimensioned ?

B.
The array will need to be parsed to check for a matching timestamp.
What method/action do I need to take to do this ?

C.
When a match is encountered I would like to match the timestamp with the led number for logging (for example : 'Led number 12 was switched on using timestamp X ')

I hope someone can shed some light here in time ( :wink: )

D

Could someone please help me with a working example as a guide to convert a human time to a unix timestamp.

  DateTime now = RTC.now();
  Serial.print(now.unixtime());

There are other ways to create a DateTime object. The class can then convert ANY date/time to unix time.

I would like to store each led number as well as two unix timestamps and the aflag value somewhere.

A shoebox in the closet, maybe? Why do you need to store these someplace else?

My first thought was an array but it's probably better to store the values in a struct which I believe from what I have read should be used when storing different data types (Correct me if I am wrong ?).

An array would be used if all the elements are the same type. If not, a struct is the only sensible alternative.

Can this be done ? either in an array or struct ? can they be dynamically dimensioned ?

Of course.

The array will need to be parsed to check for a matching timestamp.

Strings get parsed. Arrays or structs do not.

When a match is encountered I would like to match the timestamp with the led number for logging (for example : 'Led number 12 was switched on using timestamp X ')

OK. Permission is granted.

Hi

Still battling here
:frowning:

Paul thanks for answering some of the questions I had. I at least have a little clarity now.
Permission granted ?? Er.. Thanks ?
Liftoff begins in T minus ...minus minus minus minus
:slight_smile:

here are other ways to create a DateTime object. The class can then convert ANY date/time to unix time.

Where and how ? Please point me to to some examples or documents or tutorial for the Arduino ?

Here's where I am battling.

  DateTime now = RTC.now();
  Serial.print(now.unixtime());

How do I create a custom timestamp using that ?
(And I agree this is probably a great example..but this shows how to convert the CURRENT date and time.)

I need to convert a custom time into a unixtime.
(Like the struct example I posted earlier which isn't working for me with RTClib.h but does work with Time.h)

So for example if my first timestamp is called unix1

How can I take a custom time and date like 2015,4,11,7,30,01 into a unixtime timestamp (object?)
Which will then be stored in a variable/array/struct ?

D

Hi Delta G

Thanks for the reply but how does that allow me to create a custom unix timestamp ?
As per my previous post(s)

How do I create a custom timestamp using that ?
(And I agree this is probably a great example..but this shows how to convert the CURRENT date and time.)

I need to convert a custom time into a unixtime.
(Like the struct example I posted earlier which isn't working for me with RTClib.h but does work with Time.h)

So for example if my first timestamp is called unix1
Q.
How can I take a custom time and date like 2015,4,11,7,30,01 into a unixtime timestamp (object?)
Q.
Which will then be stored in a variable/array/struct ?

Thanks for replying Delta_G ..I really appreciate it !
You're right that's what to use to do it and it works for the Time.h library --check my first post.

It doesn't work for RTClib.h from what I can tell and that's where I'm having the problem.

I get that for maketime() the time elements must be gathered and run through a function and the result is a unixstamp but how do I orchestrate this ?

I also get that with breaktime the reverse is done.

Also the page you mentioned shows line of code, but there are no actual examples in the examples provided of how that is used along with a walk-through.
Something like :
Here's a step by step walk-through of how to use maketime() or breaktime()
OR
This is how you would use it in your code etc.
On top of it all there are so many time libraries and forks of them it's so difficult to figure out which one to use.

So as an example as a newbie how do you take this time_t makeTime(byte sec, byte min, byte hour, byte day, byte month, int year );

and turn it into a timestamp , like in my first two posts above my timestamps would be called unix1 and unix2 respectively.

and then how is this done if you are using the RTClib.h ?
with this example :

DateTime now = RTC.now();
  Serial.print(now.unixtime());

D

Delta_G

THANKS A MILLION BILLION TRILLION and more !!

YOU ROCK !

And then I guess I would just do something like :

/* compare dayOfWeek, year, month, day, hour, minute, or second */
      if unix1 = now.unixtime()
    Serial.print("\n hello, we have a match. \n"); 
    boolean aflag=true;
    Serial.println(); 
    Serial.print(" the value of aflag is");
    Serial.print(aflag);
    Serial.println(); 
    }
    else {
      Serial.print("\n Nothing is happening! \n");
    }

Am I on the right track now ?

D

It would probably be better to use >= just in case you miss the time of the exact match.

Delta_G....

Thanks again ..I really really appreciate your help.
I also just saw the syntax booboo ..will fix it.
Can't thank you enough.

Hi UKHeliBob

Thanks you for for the tip .. could you possibly elaborate on the

miss the exact match

please ?
How or why would it happen ?

D

How or why would it happen ?

Suppose your time that something should happen is today at 3:23:07 AM. Suppose that it is 3:23:06 AM. When loop() iterates, the time is not correct, so nothing happens.

Now, suppose that, due to some delay() call or other blocking code, that loop() doesn't iterate again until 3:23:08 AM. Since, on this and every future iteration of loop(), it will not be 3:23:07 AM, the action will never happen.

If, instead, you compare now (today at 3:23:08) to when the action should occur (today at 3:23:07), and perform the action if now is equal to OR GREATER than the action time, the action WILL occur.

Delta G

Thanks again for the explanation it definitely makes sense.
So the >= will catch it in both instances (exact second and missed second) ?

@ PaulS

That definitely clears it up too.
I honestly didn't think of the reasons it might be missed ! Thank you and UKHeliBob kindly.

@ PaulS

I did read and take note of your replies at the beginning of this post and you asked me why I want to store things elsewhere .. well I think there might have been little confusion there.
I would like to hold the timestamps for each LED number somewhere .. didn't know where exactly yet.
I realize they will be stored in memory and I guess i should think about storing them in somewhere like a file or eeprom later on but will first get on with the array/struct plan.

So it looks like I need to store a led number , unix timestamp1, unix timestamp2 and a flag (true or false) for on and off as a check flag.

On this topic as well you corrected me on what gets PARSED...THANK YOU!

Q.
So to get this all right is it correct that I need a struct to hold the data and that it needs to get parsed with each iteration of the main loop to check if there is a match for the time against either an ON or an OFF timestamp ?

Q.
And once there is a match how do I identify that the timestamp is matched to the matching LED ?

D

So to get this all right is it correct that I need a struct to hold the data

If all the data is not the same type, or can't be stored in the same type, yes. If you have three floats and an int, the int COULD be stored in a float array with the other three floats. But, if you have three ints and a string, then there is no type that can store an int or a char pointer. In the first case, you could use an array. In the second case, you would need a struct.

and that it needs to get parsed with each iteration of the main loop to check if there is a match for the time against either an ON or an OFF timestamp ?

That sounds like a requirement, not a question.

And once there is a match how do I identify that the timestamp is matched to the matching LED ?

If you are using a struct that contains on time, off time, and pin number, and an array of these structs, then when you find the array element where the struct's on time indicates that it is time to turn the pin on, then the pin number is in that struct instance.

Hi again

PaulS

Thank you again.

If all the data is not the same type, or can't be stored in the same type, yes. If you have three floats and an int, the int COULD be stored in a float array with the other three floats. But, if you have three ints and a string, then there is no type that can store an int or a char pointer. In the first case, you could use an array. In the second case, you would need a struct.

So first off I need to decide what data is to be stored then based on that decide whether or not a struct or array should be used ?

The parsinig is a requirement ...yes agreed !

If you are using a struct that contains on time, off time, and pin number, and an array of these structs, then when you find the array element where the struct's on time indicates that it is time to turn the pin on, then the pin number is in that struct instance.

All right then.

I will get to work on the struct or array or both.

Q.
Since I may like to add LED's as I go can the array/struct be set as N+1 or N -1 ?

Q.
Would you mind giving me some guidance once I have some code going here ?

Thanks again

D

**** And thank you to all who have replied so far !

So first off I need to decide what data is to be stored then based on that decide whether or not a struct or array should be used ?

Yes.

Since I may like to add LED's as I go can the array/struct be set as N+1 or N -1 ?

That would depend on what "as I go" means and what is to be set to N+1 or N-1 and on what N is.

Would you mind giving me some guidance once I have some code going here ?

Of course.

din4444:
...
So first off I need to decide what data is to be stored then based on that decide whether or not a struct or array should be used ?
...

Q.
Since I may like to add LED's as I go can the array/struct be set as N+1 or N -1 ?
Q.
Would you mind giving me some guidance once I have some code going here ?

You don't need a struct, just two arrays. One for the LEDs and one for the timestamps. You could have an array of structs, but make life easy on yourself at the start. Leave that for later. As Paul suggested, set it up so the Nth timestamp corresponds with the Nth LED. That connects them logically.

A. You can not increase the size of an array after the program is compiled. So you need to decide on the maximum that you would like to add, and allocate an array of that size. You then create a variable that keeps track of how many elements are actually used (i.e. how many LEDs there are).

A. I can't speak for Paul. But honestly, although this is a great place to get guidance, it's not supposed to replace the usual ways of learning. For example, the ">=" operator that you asked about is well documented both in the reference, and in a plethora of online C references and tutorials. It would behoove you to make use of them. The way that it is used in this particular case, only requires that you think about it a little. You need to exercise those parts of your brain, to become a successful programmer. If you do, when you post for help, it will be obvious that you have, and people like Paul and many others will jump out of the woodwork to assist.

Another thing, not to discourage you from your project. But you should start some easier projects to work on at the same time. It will strengthen you for the main task. Also look at the examples in the IDE.

You don't need a struct, just two arrays. One for the LEDs and one for the timestamps.

Unless you need an on time and an off time for each LED. Then, you need three arrays. Or a struct and an array of instances of the struct. Learning about structs is not a waste of time.

A. You can not increase the size of an array after the program is compiled.

That depends on how the array is created in the first place. A static array can not change size. A dynamic array (created with malloc()) can be realloc()ed.

You need to exercise those parts of your brain, to become a successful programmer.

Wait a minute. You said you couldn't speak for me, but here you go.

Tired eyes ..time for sleep :wink:

Perhaps a debug g:c800 first thing in the morning ?

@aarg

Points noted .. but different people learn differently .. One thing is for sure though and that is that adults learn by doing.
And admittedly I don't know what stuff like this means, perhaps it is indeed flawed :

while(*t++ = *s++);

Define successful programmer ?
Does that mean all languages ... ?
Global multi-lingual ?
On which level exactly and what stack ?
PUSH POP or MOV ?

How does and ABACUS relate to a ROSETTA STONE ?
How were hieroglyphics and cuneiform decoded ?
How did people find out about the ALPHA and OMEGA ?
And more specifically how does the code we use relate to binary and hex and more when we analyze the i-ching ?

is it chicken and egg or SATOR SQUARE ?

Perhaps understanding early code is of no relevance with Arduino C ?

- a 0100
????:0100 MOV AH, 09
????:0102 MOV DX, 0000
????:0105 INT 21
????:0107 RET
????:0108 DB "Hello World!$"
????:0115 (Press ENTER)

Arrays could be ad-infinitum in size, I guess it all depends on the language.
How large would an array be to hold the number of stars in the known universe ?

@PaulS
Valid chirp!
LOL is that a remote voice api control system with dynamic thermo throttle trans-axial inverse modulation circuitry and and eye-tracking tapped into OOGLE glass with lip sync too ?
Where can I buy that ?

10 goto 20 
20 abort,retry,fail ?
30 goto 10

EDLIN ..where are you hiding ?

@ Delta_G

So it seems...!

But alas I truly am a arduino c newbie and I really really have been battling !

I would just like to once again thank all who have replied ..THANK YOU.

And please don't stop doing what you do, you truly have a gift to spot and use code in the blink of an eye.

I am humbled by the fast and accurate response.

D

@ ALL

Good day :slight_smile: , I hope all is well with you.

@ the person(s) who created the time library ...thank you ..this must have taken a lot of effort.

@PaulS ,

C.C. UkHeliBob , Delta_G , aarg

Code is fairly functional so far I think ... (Need your code filtering debug,optimization and suggestion eyes please).

/*
 * TimeRTC.pde
 * example code illustrating Time library with Real Time Clock.
 * 
 */

#include <Time.h>  
#include <Wire.h>  
#include <DS1307RTC.h>  // a basic DS1307 library that returns time as a time_t


//boolean aflag;
unsigned long unix1;
unsigned long unix2;

//struct tm t;
time_t tmConvert_t(int YYYY, byte MM, byte DD, byte hh, byte mm, byte ss)
{
  tmElements_t tmSet;
  tmSet.Year = YYYY - 1970;
  tmSet.Month = MM;
  tmSet.Day = DD;
  tmSet.Hour = hh;
  tmSet.Minute = mm;
  tmSet.Second = ss;
  return makeTime(tmSet); 
}

struct led_info { //led_id,unix1,unix2,aflag
  int led_id;
  unsigned long unix1;
  unsigned long unix2;
  boolean aflag;
};
led_info led_values = { //preloaded for now to test struct
  1,2,3,4}; 

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

  while (!Serial) ; // wait until Arduino Serial Monitor opens
  setSyncProvider(RTC.get);   // the function to get the time from the RTC
  if(timeStatus()!= timeSet) 
    Serial.println("Unable to sync with the RTC");
  else
    Serial.println("RTC has set the system time");      
}

void loop()
{
  if (timeStatus() == timeSet) {
    digitalClockDisplay();
  } 
  else { //add or change later
    Serial.println("The time has not been set.  Please run the Time");
    Serial.println("TimeRTCSet example, or DS1307RTC SetTime example.");
    Serial.println();
    delay(4000);
  }
  delay(1000); //adjust or remove as required , only here for test
  Serial.println(led_values.led_id);
  Serial.println(led_values.unix1);
  Serial.println(led_values.unix2);
  Serial.println(led_values.aflag);

  //test field for setTime
  //Serial.println("Time is now set using setTime");
  //setTime(9,30,50,12,4,2015);

  Serial.println("Collecting time_t = now();");
  time_t t = now();
  //test field for RTC.set()
  //Serial.println("now setting time using RTC.set(t);");
  //RTC.set(t);

  // get the timestamps (pre-populated for now)
  time_t unix1 = tmConvert_t(2015,4,19,7,30,00);

  Serial.print("First unix timestamp is : ");
  Serial.println(unix1);

  time_t unix2 = tmConvert_t(2015,4,19,7,30,00);

  Serial.print("Second unix timestamp is : ");
  Serial.println(unix2); 



  if (unix1 >= unix2) {
    Serial.print("\n hello, we have a match. \n"); 
    boolean aflag=true;
    Serial.println(); 
    Serial.print(" the value of aflag is --> ");
    Serial.print(aflag);
    Serial.println(); 
    //change delay as per requirements
    //delay 1000;
  }
  else {
    Serial.print("\n Nothing is happening! \n");
  } 
  
}

void digitalClockDisplay(){
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.print(" ");
  Serial.print(day());
  Serial.print(" ");
  Serial.print(month());
  Serial.print(" ");
  Serial.print(year()); 
  Serial.println(); 
}

void printDigits(int digits){
  // utility function for digital clock display: prints preceding colon and leading 0
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

Code is fairly functional so far I think ...
I pre-loaded the values and also made sure the if statement always matches for testing.
Now I need the help of your code filtering debug,optimization and suggestion eyes please.

***(And btw aarg .. this is where you are correct with regard to knowing the fundamentals and lot's of practice but a lot of the basic examples don't show these tips and tricks..correct me if I'm wrong)

Here are my questions and gotchas :

Q.
When trying to put the converted unix timestamps directly into the struct fields I receive and error from the compiler stating that ...

So to clarify .. what I am trying to do is take my unix timestamp and directly update the corresponding value in the struct :

This one is the working element:

// get the timestamps (pre-populated for now)
  time_t unix1 = tmConvert_t(2015,4,19,7,30,00);

This generates the error
expected initializer before '.'token :

// try to load the timestamp into the corresponding struct field/value
  time_t led_values.unix1 = tmConvert_t(2015,4,19,7,30,00);

Where and why am I messing up here and how is it fixed ?

Q.

Since I now have a struct with the correct fields(variables) in place ,namely led_id, unix1, unix2 and aflag,
how to i go on to make the array of struct and further more index and parse them dynamically ?

I look forward to your suggestions help and comments.

PS. I hope I'm on track so far...
PPS. I assume this is where the fun starts ?

din4444:
This generates the error :

// try to load the timestamp into the corresponding struct field/value

time_t led_value.unix1 = tmConvert_t(2015,4,19,7,30,00);



Where and why am I messing up here and how is it fixed ?

That's a duplicate declaration. Try:

// try to load the timestamp into the corresponding struct field/value
led_value.unix1 = tmConvert_t(2015,4,19,7,30,00);

You only declare a variable once. Also do you not mean:

led_value[0].unix1 = tmConvert_t(2015,4,19,7,30,00);

?

AARG !! YOU ROCK ! :slight_smile:

That's a duplicate declaration. Try:

// try to load the timestamp into the corresponding struct field/value
led_values.unix1 = tmConvert_t(2015,4,19,7,30,00);

Spot on !! the field is now updating and I can eliminate some variables ! YAY

Now with regards to the next one:

led_value[0].unix1 = tmConvert_t(2015,4,19,7,30,00);

I receive an error when trying that ..
no match for operator [] in led_values[0]

I assume this is because the struct is created but not dimensioned as an array or structs yet ? (See posted code @ struct declaration section.)

What are your thoughts ?