I need the time for a solar tracking application. The choices are to use a GPS, or to use a RTC, or to use onboard timers with a correction. The correction is with a light sensor detecting sunrise and sunset. The mean time value will be applied to the clock at noon or midnight. The GPS approach is $$. The RTC clock drifts over time. So I am going to try light sensors. I can tolerate a daily error in terms of knowing where the sun is located. I have tried the following: Timer1 is used to increment the clock. Timer1 register is 16 bytes long = 65536 (2 to 16 power = 65536) The Mega clock goes at 16 mega Hz. The pre-scalar is 8. An additional loop scales the speed by 30. So 16,000,000/8/30 = 66666 Hz. The time for the 16 bit register to fill is 1.0172 seconds. (66666/65536 = 1.0172). The error is about 1 minute per hour. 1/ (1.0172-1) = 57.96 I am seeing the the accumulated error is more than 1 minute per hour, and am wondering why. Is it that the system clock has a tolerance (+/- ) ? Does anyone have a suggestion how the program could be modified so the scale factor (30) could be more precise? I can tweek the result by adding 1 minute per hour.
The uploaded program is a modified version that was obtained thru the forum's.
Making a 24 hour clock
Moderator: Benj
-
brandonb
- Posts: 438
- Joined: Mon Aug 29, 2011 12:26 am
- Location: arizona
- Has thanked: 175 times
- Been thanked: 173 times
Re: Making a 24 hour clock
here's a avr 328 arduino clock project i coded for a friend, can set the time hours,min,days, and displays in am pm format, it has tmr1 running at one hz, if can follow code sorry its in c, as it the closest thing i have to avr
Code: Select all
/* DAY ZERO IS MONDAY (0-6)
HOUR ZERO IS 12AM (0-23)*/
#include <LiquidCrystal.h>
LiquidCrystal lcd(7,8,9,10,11,12);
char* string_day_array [7]={"MON","TUE","WED","THU","FRI","SAT","SUN"};
const byte d2=2;
const byte d3=3;
const byte d4=4;
const byte d5=5;
const byte d6=6;
const byte d13=13;
boolean switch1;
boolean switch2;
boolean switch3;
boolean switch4;
boolean switch5;
byte tick=0;
byte second=0;
byte minute=0;
byte hour=0;
byte day=0;
byte old_minute=minute;
byte old_hour=hour;
byte old_day=day;
byte temp_hour;
boolean update_display=1;
boolean first=1;
unsigned int delay_value;
void setup()
{
noInterrupts();
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 15625; // 1HZ
TCCR1B = 5; // 1024:1 PRESCALER
TCCR1B |= (1 << 3);
TIMSK1 &= ~(1 << 1);
interrupts();
pinMode(d2,INPUT);
pinMode(d3,INPUT);
pinMode(d4,INPUT);
pinMode(d5,INPUT);
pinMode(d6,INPUT);
pinMode(d13,OUTPUT);
digitalWrite(d13,LOW);
lcd.begin(16,2);
lcd.clear();
set_day();
set_hour();
set_minute();
display_time();
}
void loop()
{
if(update_display==1)
{
update_display=0;
display_time();
}
/* THE CODE BELOW IS SET WHERE IT WILL TURN ON
THE D13 LED FRIDAY 11:20PM-11:22PM */
if((day==4)&&(hour==23))
{
if((minute>=20)&&(minute<22))
{
digitalWrite(d13,HIGH);
}
else
{
digitalWrite(d13,LOW);
}
}
}
//...........................................................................
ISR(TIMER1_COMPA_vect)
{
update_display=1;
second=second+1;
if(second==60)
{
second=0;
minute=minute+1;
if(minute==60)
{
minute=0;
hour=hour+1;
if(hour==24)
{
hour=0;
day=day+1;
if(day==7)
{
day=0;
}
}
}
}
}
//..........................................................................
void display_time()
{
if(first==1)
{
second=0;
TIMSK1 |= (1 << 1);
update_display=0;
lcd.clear();
lcd.setCursor(7,0);
lcd.print(":");
lcd.setCursor(10,0);
lcd.print(":");
}
if((old_day>day)|(old_day<day)|(first==1))
{
if(day<10)
{
lcd.setCursor(1,0);
lcd.print(string_day_array[day]);
}
}
if((old_hour>hour)|(old_hour<hour)|(first==1))
{
temp_hour=hour;
if(temp_hour>12){temp_hour=temp_hour-12;}
if(temp_hour==0){temp_hour=12;}
if(temp_hour<10)
{
lcd.setCursor(5,0);
lcd.print(" ");
lcd.setCursor(6,0);
lcd.print(temp_hour);
}
else
{
lcd.setCursor(5,0);
lcd.print(temp_hour);
}
}
if((old_minute>minute)|(old_minute<minute)|(first==1))
{
if(minute<10)
{
lcd.setCursor(8,0);
lcd.print("0");
lcd.setCursor(9,0);
lcd.print(minute);
}
else
{
lcd.setCursor(8,0);
lcd.print(minute);
}
}
if(second<10)
{
lcd.setCursor(11,0);
lcd.print("0");
lcd.setCursor(12,0);
lcd.print(second);
}
else
{
lcd.setCursor(11,0);
lcd.print(second);
}
lcd.setCursor(13,0);
if(hour<12)
{
lcd.print("AM");
}
else
{
lcd.print("PM");
}
old_minute=minute;
old_hour=hour;
old_day=day;
first=0;
}
//..........................................................................
void set_day()
{
update_display=1;
lcd.clear();
do
{
lcd.setCursor(3,0);
lcd.print("<SET DAY>");
lcd.setCursor(5,1);
switch1=digitalRead(d4);
switch2=digitalRead(d5);
switch5=digitalRead(d3);
if(switch1==1)
{
day=day+1;
delay_value=450;
if(day>6){day=0;}
update_display=1;
}
else if(switch2==1)
{
day=day-1;
delay_value=450;
if(day>6){day=6;}
update_display=1;
}
if(update_display==1)
{
update_display=0;
lcd.setCursor(6,1);
lcd.print(string_day_array[day]);
delay(delay_value);
}
}while(switch5!=1);
delay(500);
}
//.................................................................
void set_hour()
{
update_display=1;
lcd.clear();
do
{
lcd.setCursor(3,0);
lcd.print("<SET HOUR>");
lcd.setCursor(5,1);
switch1=digitalRead(d4);
switch2=digitalRead(d5);
switch3=digitalRead(d6);
switch5=digitalRead(d3);
if(switch1==1)
{
hour=hour+1;
if(switch3==1){delay_value=250;}
else
{
delay_value=450;
}
if(hour==24){hour=0;}
update_display=1;
}
else if(switch2==1)
{
hour=hour-1;
if(switch3==1){delay_value=250;}
else
{
delay_value=450;
}
if(hour>24){hour=23;}
update_display=1;
}
if(update_display==1)
{
update_display=0;
temp_hour=hour;
if(temp_hour>12){temp_hour=temp_hour-12;}
if(temp_hour==0)
{
temp_hour=12;
}
if(temp_hour<10)
{
lcd.setCursor(5,1);
lcd.print(" ");
lcd.setCursor(6,1);
lcd.print(temp_hour);
}
else
{
lcd.setCursor(5,1);
lcd.print(temp_hour);
}
lcd.setCursor(8,1);
if(hour<12)
{
lcd.print("AM");
}
else
{
lcd.print("PM");
}
delay(delay_value);
}
}while(switch5!=1);
delay(500);
}
//..................................................................
void set_minute()
{
update_display=1;
lcd.clear();
do
{
lcd.setCursor(2,0);
lcd.print("<SET MINUTE>");
lcd.setCursor(5,1);
switch1=digitalRead(d4);
switch2=digitalRead(d5);
switch3=digitalRead(d6);
switch5=digitalRead(d3);
if(switch1==1)
{
minute=minute+1;
if(switch3==1){delay_value=120;}
else
{
delay_value=250;
}
if(minute==60){minute=0;}
update_display=1;
}
else if(switch2==1)
{
minute=minute-1;
if(switch3==1){delay_value=120;}
else
{
delay_value=250;
}
if(minute>60){minute=59;}
update_display=1;
}
if(update_display==1)
{
update_display=0;
if(minute<10)
{
lcd.setCursor(7,1);
lcd.print(" ");
lcd.setCursor(8,1);
lcd.print(minute);
}
else
{
lcd.setCursor(7,1);
lcd.print(minute);
}
delay(delay_value);
}
}while(switch5!=1);
}
Last edited by brandonb on Tue Jun 04, 2013 3:07 am, edited 1 time in total.
-
billduck
- Posts: 162
- Joined: Thu Jul 01, 2010 1:57 am
- Has thanked: 23 times
- Been thanked: 16 times
- Contact:
Re: Making a 24 hour clock
Thanks. In void setup (), I am seeing
noInterrupts();
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 15625; // 1HZ
......
Flowcode does not have the ability to count to a preset value yet - "15625", so I am doing a timer1 overflow. I wonder if I could add "OCR1A = 15625; // 1HZ" in c code.
noInterrupts();
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 15625; // 1HZ
......
Flowcode does not have the ability to count to a preset value yet - "15625", so I am doing a timer1 overflow. I wonder if I could add "OCR1A = 15625; // 1HZ" in c code.
-
brandonb
- Posts: 438
- Joined: Mon Aug 29, 2011 12:26 am
- Location: arizona
- Has thanked: 175 times
- Been thanked: 173 times
Re: Making a 24 hour clock
yes, thats why i posted it, that works great for a 328p, not sure about the one you are using... im using tmr1, also look at the tmr vector code, i can show you how it works when i get off work in 6 hours with a video
{edit} oops i guess i did use timer1, but i used compair instead of overflow as its more accurate and can calculate accurate values, here is the website that i learned about the avr interrupts http://letsmakerobots.com/node/28278
{edit} oops i guess i did use timer1, but i used compair instead of overflow as its more accurate and can calculate accurate values, here is the website that i learned about the avr interrupts http://letsmakerobots.com/node/28278
Last edited by brandonb on Tue Jun 04, 2013 3:11 am, edited 1 time in total.
- JohnCrow
- Valued Contributor

- Posts: 1367
- Joined: Wed Sep 19, 2007 1:21 pm
- Location: Lincolnshire
- Has thanked: 364 times
- Been thanked: 716 times
Re: Making a 24 hour clock
Nice program.
Just had a quick look at it on my Arduino board. Seems to work fine, though not got time to have a close look at the code tonight.
Thanks.
Just had a quick look at it on my Arduino board. Seems to work fine, though not got time to have a close look at the code tonight.
Thanks.
1 in 10 people understand binary, the other one doesn't !