Arduino Clock: Setting Time

mem: Can you tell me with syntax how I can send two numbers (h and m) using headers over the serial port?
Also, where in the arduino code below is the time header retrieved from processing? I'm asking so i know how to modify the code. sorry i'm having you baby-sit me thru the process

//arduino code
#include <DateTime.h>
#include <DateTimeStrings.h>

#define TIME_MSG_LEN 11 // time sync to PC is HEADER and unix time_t as ten ascii digits
#define TIME_HEADER 255 // Header tag for serial time sync message

void setup(){
Serial.begin(19200);
}

void loop(){
getPCtime(); // try to get time sync from pc
if(DateTime.available()) { // update clocks if time has been synced
unsigned long prevtime = DateTime.now();
while( prevtime == DateTime.now() ) // wait for the second to rollover
;
DateTime.available(); //refresh the Date and time properties
digitalClockDisplay( ); // update digital clock

// send our time to an app listening on the serial port
Serial.print( TIME_HEADER,BYTE); // this is the header for the current time
Serial.println(DateTime.now());
}
}

void getPCtime() {
// if time available from serial port, sync the DateTime library
while(Serial.available() >= TIME_MSG_LEN ){ // time message
if( Serial.read() == TIME_HEADER ) {
time_t pctime = 0;
for(int i=0; i < TIME_MSG_LEN -1; i++){
char c= Serial.read();
if( c >= '0' && c <= '9')
pctime = (10 * pctime) + (c - '0') ; // convert digits to a number
}
DateTime.sync(pctime); // Sync DateTime clock to the time received on the serial port
}
}
}

void digitalClockDisplay(){
// digital clock display of current time
Serial.print(DateTime.Hour,DEC);
printDigits(DateTime.Minute);
printDigits(DateTime.Second);
Serial.print(" ");
Serial.print(DateTimeStrings.dayStr(DateTime.DayofWeek));
Serial.print(" ");
Serial.print(DateTimeStrings.monthStr(DateTime.Month));
Serial.print(" ");
Serial.println(DateTime.Day, DEC);
}

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

You can see how to send Data to Arduino by studying the Processing Serial examples. There is Arduino code at the end of the Processing example sketches. In Processing, select : Files/Examples/Libraries/Serial/

I have added some more comments to help clarify how the Arduino sketch gets the time.

void getPCtime() {
 // if time available from serial port, sync the DateTime library
 // a time message consists of a header followed by ten digits (TIME_MSG_LEN equals 11)
 while(Serial.available() >=  TIME_MSG_LEN ){  // time message
 // you make sure you have the start of the message by checking the header
   if( Serial.read() == TIME_HEADER ) {        
     // header was found so get the next ten digits and convert to a number
     time_t pctime = 0;
     for(int i=0; i < TIME_MSG_LEN -1; i++){   
       char c= Serial.read();          
       if( c >= '0' && c <= '9')   
         pctime = (10 * pctime) + (c - '0') ; // convert digits to a number    
// the ASCII character is converted to a digit by subtracting '0' which has an ASCII value 48.
// So, if ch equals '1', its ASCII value is 49. 49- '0' is the same as 49-48 and they both equal 1,
// which is the numeric value of the character '1'        
     }   
     // the next method sets the clock with the pc time received above
     DateTime.sync(pctime);   // Sync DateTime clock to the time received on the serial port
   }  
 }
}

I think my case is different. So, parsing the data the same way you do as the time clock shouldn't be the same way. I guess the question now is how do you parse the data since i'm sending two integers over the port. The processing code below is wat i'm using to send the data to the arduino, how would you parse it in arduino? Thanks!

//processing code
port.write(header2); //writes the header first
port.write(h);
port.write(m);

if the header, h, and m are all chars then you don't need to parse. read a byte in arduino and if its the header you can then read h and m directly.

Mem: Thanks a lot!!!

Quote:
time_t alarmOnTime = (8 * SECS_PER_HOUR) + (30 * SECS_PER_MIN);
time_t alarmOffTime = alarmOnTime + (60 * SECS_PER_MIN);
time_t nextAlarm;

nextAlarm = previousMidnight(DateTime.now())+ alarmOnTime;

if( DateTime.now() >= nextAlarm && DateTime.now() < nextAlarm + alarmOffTime )
digitalWrite(ledPin), HIGH);
else
digitalWrite(ledPin), LOW);

Mem: the LED turns on at the precise time (8:30) but does not turn off at all. Do you have any idea why it acts likes that?

I saw this too and changed the second test in the if statement to:

previousMidnight(DateTime.now())+ alarmOffTime;

and it worked for me.

hello...

I'm totally new to arduino and I have a project to hand next week

my goal to accoplishe is to use arduino as alarm clock that turn on light on specific time

I searched solutions online, most on this forum, but I can't connect it all

firs idea was that computer send real time to arduino that is displayed on lcd (it's working fine), but after failure I decided to use code from internet that allows to set up time and than counts

a problem is now to start led when desirable time is reached, by chance to slowly start up, opposite of dimming (example)

code I used so far:

#include <LiquidCrystal.h>
#include <DateTime.h>

// simple sketch to display a digital clock on an LCD
// see the LiquidCrystal documentation for more info on this

LiquidCrystal lcd(7,8,9,10,11,12);

int ledPin = 13; // LED connected to digital pin 13

void setup(){
//DateTime.sync(1230768000); // set jan 1 2009 as the default time
DateTime.sync(DateTime.makeTime(0, 40, 10, 29, 5, 2010));
}

void loop(){
if(DateTime.available()) {
unsigned long prevtime = DateTime.now();
while( prevtime == DateTime.now() ) // wait for the second to rollover
;
DateTime.available(); //refresh the Date and time properties
digitalClockDisplay( ); // update digital clock
}
}

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

void digitalClockDisplay(){
lcd.home();
// digital clock display of current time
lcd.print(DateTime.Hour,DEC);
printDigits(DateTime.Minute);
printDigits(DateTime.Second);
}

time_t alarmOnTime = (10 * SECS_PER_HOUR) + (45 * SECS_PER_MIN);
time_t alarmOffTime = alarmOnTime + (60 * SECS_PER_MIN);
time_t nextAlarm;

nextAlarm = previousMidnight(DateTime.now())+ alarmOffTime;

if ( DateTime.now() >= alarmOnTime && DateTime.now() < alarmOnTime + alarmOffTime ){
digitalWrite(ledPin), HIGH);
}
else{
digitalWrite(ledPin), LOW);
}

but error occur

any suggestion is appreciated

(my C programming is in basics =/)

None of this code is inside a function:

time_t  alarmOnTime =  (10 * SECS_PER_HOUR) + (45 * SECS_PER_MIN);
time_t  alarmOffTime =  alarmOnTime  + (60 * SECS_PER_MIN);
time_t nextAlarm;


nextAlarm =  previousMidnight(DateTime.now())+ alarmOffTime;


if ( DateTime.now() >= alarmOnTime  && DateTime.now()  < alarmOnTime + alarmOffTime ){
   digitalWrite(ledPin), HIGH);
}
else{
  digitalWrite(ledPin), LOW);
}

All executable code needs to be inside a function.

thnx a lot!!

always learning ;D

code now looks like:

#include <LiquidCrystal.h>
#include <DateTime.h>

// simple sketch to display a digital clock on an LCD
// see the LiquidCrystal documentation for more info on this

LiquidCrystal lcd(7,8,9,10,11,12);

int ledPin = 13; // LED connected to digital pin 13

void setup(){
//DateTime.sync(1230768000); // set jan 1 2009 as the default time
DateTime.sync(DateTime.makeTime(45, 40, 10, 29, 5, 2010));
lcd.begin(16, 2);
// initialize the digital pin as an output:
pinMode(ledPin, OUTPUT);
}

void loop(){
if(DateTime.available()) {
unsigned long prevtime = DateTime.now();
while( prevtime == DateTime.now() ) // wait for the second to rollover
;
DateTime.available(); //refresh the Date and time properties
digitalClockDisplay( ); // update digital clock

time_t alarmOnTime = (10 * SECS_PER_HOUR) + (41 * SECS_PER_MIN);
time_t alarmOffTime = alarmOnTime + (60 * SECS_PER_MIN);
time_t nextAlarm;

nextAlarm = previousMidnight(DateTime.now())+ alarmOffTime;

if ( DateTime.now() >= alarmOnTime && DateTime.now() < alarmOnTime + alarmOffTime ){
digitalWrite(ledPin, HIGH);
}
else{
digitalWrite(ledPin, LOW);
}
}
}

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

void digitalClockDisplay(){
lcd.home();
// digital clock display of current time
lcd.print(DateTime.Hour,DEC);
printDigits(DateTime.Minute);
printDigits(DateTime.Second);
}

but when it hits 10:41:00 nothing happened :-/

You might want to print out some values.

nextAlarm =  previousMidnight(DateTime.now())+ alarmOffTime;

The nextAlarm value looks to me like that's the next time to turn the alarm off. If that's the case, the name choice is poor.

The nextAlarm variable is going to hold a fairly large number, though, since it is the number of seconds from an event that happened years ago.

The variables alarmOnTime and alarmOffTime hold very small values, since they are to be used as relative values. alarmOffTime is relative to alarmOnTime. alarmOnTime is not relative to the same event that nextAlarm is, though. It isn't relative to anything, for that matter.

So, this code:

if ( DateTime.now() >= alarmOnTime  && DateTime.now()  < alarmOnTime + alarmOffTime )

will always be false.

DateTime.now() returns the number of seconds since that same event many years ago, so it is a large number. That number is always going to be greater than the value in alarmOnTime. It will NOT be less than alarmOnTime + alarmOffTime, unless alarmOffTime is very large (say about 40 years).

I see now...

I don't need next alarm

all I want is LED to activate when it hits 10:41:00 and be activated about a minute

how to do it, I don't know

from when DateTime.now() is start counting
my intention is ti put
DateTime.sync(DateTime.makeTime(45, 40, 10, 29, 5, 2010));
that time in DateTime.now() that will start count secont if that is posible and than if condition will work, I think so

would appreciate that if condition that works, VERY
or some exaples or advices to move on...

The nextAlarm variable is set to when the alarm should go off (10 hours and 42 minutes after midnight). Rename it to nextAlarmOff. Create another variable, nextAlarmOn that is set like nextAlarm, but to when to then the alarm on.

Then, in the if test, see if now is greater than nextAlarmOn and less than nextAlarmOff. If it is, light up the LED.

thnx a lot!!!

the code is now working!!

here it is:

time_t alarmOnTime = (10 * SECS_PER_HOUR) + (41 * SECS_PER_MIN);
time_t alarmOffTime = (10 * SECS_PER_HOUR) + (42 * SECS_PER_MIN);
//time_t alarmOffTime = alarmOnTime + (30 * SECS_PER_SEC);
time_t nextAlarmOff;
time_t nextAlarmOn;

nextAlarmOn = previousMidnight(DateTime.now())+ alarmOnTime;
nextAlarmOff = previousMidnight(DateTime.now())+ alarmOffTime;

if ( DateTime.now() >= nextAlarmOn && DateTime.now() < nextAlarmOff){
digitalWrite(ledPin, HIGH);
}
else
{
digitalWrite(ledPin, LOW);
}
}
}

now I'm curious to set exact seconds to turn of, not minutes, something like
time_t alarmOffTime = alarmOnTime + (30 * SECS_PER_SEC);
but SECS_PER_SEC don't exist

and also I'll need to slowly start led...

PaulS, you saved me :slight_smile:

That's because SECS_PER_SEC is 1.

ok, second to turn off led are solved

but there still a problem with turning on led, opposite of fading (can't remember word now)

I used code from fading, but problem is when for loop is active, clock stop counting...
any ideas how to accomplish it in another way?

if ( DateTime.now() >= nextAlarmOn && DateTime.now() < nextAlarmOff){
//digitalWrite(ledPin, HIGH);
for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=10) {
// sets the value (range from 0 to 255):
analogWrite(ledPin, fadeValue);

delay(500);
}
}
else
{
digitalWrite(ledPin, LOW);
}
}

Look at the BlinkWithoutDelay example.

On each pass through loop, see if it is time to have the LED on, as you are doing now. If it is, see if it is time to step up another level.

I mixed something up...

#include <LiquidCrystal.h>
#include <DateTime.h>

LiquidCrystal lcd(7,8,9,10,11,12);

int ledPin = 6; // LED connected to digital pin 6

void setup(){
DateTime.sync(DateTime.makeTime(55, 40, 10, 29, 5, 2010)); //set up time
lcd.begin(16, 2);
// initialize the digital pin as an output:
pinMode(ledPin, OUTPUT);
}

void loop(){
if(DateTime.available()) {
unsigned long prevtime = DateTime.now();
while( prevtime == DateTime.now() ) // wait for the second to rollover
;
DateTime.available(); //refresh the Date and time properties
digitalClockDisplay( ); // update digital clock

time_t alarmOnTime = (10 * SECS_PER_HOUR) + (41 * SECS_PER_MIN);
time_t alarmOffTime = alarmOnTime + (1 * SECS_PER_MIN)/4; //led turn on 15 seconds
time_t nextAlarmOff;
time_t nextAlarmOn;

nextAlarmOn = previousMidnight(DateTime.now())+ alarmOnTime;
nextAlarmOff = previousMidnight(DateTime.now())+ alarmOffTime;

if ( DateTime.now() >= nextAlarmOn && DateTime.now() < nextAlarmOff){
//digitalWrite(ledPin, HIGH);
for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=15) {
// sets the value (range from 0 to 255):
analogWrite(ledPin, fadeValue);
delay(800);
}
digitalWrite(ledPin, HIGH);
}
else
{
digitalWrite(ledPin, LOW);
}
}
}

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

void digitalClockDisplay(){
lcd.home();
// digital clock display of current time
lcd.print(DateTime.Hour,DEC);
printDigits(DateTime.Minute);
printDigits(DateTime.Second);
}

alarm activates at 10:41:00 and lasts for 15 seconds....

problem is to me now to left light turn on, while after execute the program it turns off

ideao was to put digitalWrite(ledPin, HIGH); after for loop but it doesn't work

why? :o

alarm activates at 10:41:00 and lasts for 15 seconds....

That's good.

problem is to me now to left light turn on, while after execute the program it turns off

I suspect that English is not your native language, but, this doesn't make sense. If the light stays on, then the alarm is not lasting just 15 seconds.

Can you try again to explain what the problem is?

DarkElf, you are in good hands with PaulS so I don't want to interrupt as it sounds like you are close to solving your problem.

However, I do wonder why you are using the older DateTime library as there is an updated version that is a little easer to use and has some enhancements and bug fixes, see: Arduino Playground - Time

That download includes a companion library called TimeAlarms that would make your task easier. Using this library you can create one alarm to turn on your led at 10:41 and another alarm that turns the led off at 10:42. There is an example sketch for the TimeAlarm library that you could use as a starting point.