I've been designing a clock and I've decided that the only way it's going to work is with and Arduino.
I'm newbie to this, never really tried programming before and I've been looking over some simple commands.
Basically I was just wondering if what I proposing is do-able, or if their is a better way of doing it...
The clock consists of digits 1 to 12 being lit up (the hours), and 00 to 55 being lit up (the minutes), the board would be controlling 24 relays to turn on a much bigger power supply to control the lights. The relays are latching so I would have to pulse them rather than keep them on.
The code I was thinking of using was counting in milliseconds, when it reached 5 mins it would turn 00 off and turn 05 on and so on until it reached 55, after that it would go back to 00 and the hour light will change. Then once it reached the 13th hour it would go back to 1.
This is my first project using Arduino and code, so please be nice Looking forward to other projects I might try once I get the hang of it Also sorry if this question has been asked before...
Basically I was just wondering if what I proposing is do-able
Yes, it is.
Since you didn't ask any other questions, I guess that's all the answers you need. Good luck.
As a suggestion, though, the Arduino isn't all that accurate as a clock. Adding a RTC (real time clock) to a project involving 24 relays, 24 high power LEDS, a large power supply, and an Arduino is not going to add any significant cost to the project, and will make it much easier to develop the project.
The RTC library will, for instance, have a method to return the hour as a separate integer. That makes it enormously easier to determine which of 12 relays to bang on.
Similarly, it will have a method to get minutes.
Since you are into a fairly complex project, you might consider adding 60 small LEDs around the perimeter and lighting one per second. These don't need to be high power LEDs switched with relays. It's fun to watch the second indicator sweep around (and will give you much more immediate feedback that the code is working). Waiting 12 hours to see that all the relays latch in the correct order can try your patience.
The clock consists of digits 1 to 12 being lit up (the hours), and 00 to 55 being lit up (the minutes), the board would be controlling 24 relays to turn on a much bigger power supply to control the lights. The relays are latching so I would have to pulse them rather than keep them on.
Using an interrupt and you are done. I wrote the following piece for some other purpose but it can be easily repurposed here:
//unsigned long _timer1_period=0; //timer period, in seconds
unsigned long _timer1_counter=0; //timer1 counter
struct {
unsigned char hour;
unsigned char minute;
unsigned char second;
} mytime;
//timer1 isr
ISR(TIMER1_OVF_vect) {
_timer1_counter+=0x10000ul; //increment timer_counter
if (_timer1_counter >=F_CPU) {
_timer1_counter -= F_CPU; //reset timer_counter
mytime.second+=1; //increment the seconds
if (mytime.second >=60) {
mytime.second -= 60; //reset seconds
mytime.minute += 1; //increment the minute
if (mytime.minute>=60) {
mytime.minute -= 60; //reset minute
mytime.hour += 1;
}
}
}
}
//initialize the timer
//to expire in user-specified period of time
void tmr1_init(void) {
_timer1_counter = 0; //reset timer1 counter
mytime.hour = mytime.minute = mytime.second = 0;//reset mytime
TCCR1B = 0x00; //turn off the timer
TCCR1A = 0x00; //normal portion operation
TCNT1 = 0; //reset the timer
TIFR1 |= (1<<TOV1); //clear the timer flag
TCCR1B = 0x01; //turn on the timer, 1:1 prescaler
TIMSK1 |= (1<<TOIE1); //enable the timer interrupt
sei(); //enable global interrupt
}
In your code, you will just set it up and test it:
void setup(void) {
...
tmr1_init(); //reset the timer and get it started
}
void loop(void) {
if (mytime is mydesiredtime) {
//do something
}
}
The clock consists of digits 1 to 12 being lit up (the hours), and 00 to 55 being lit up (the minutes), the board would be controlling 24 relays to turn on a much bigger power supply to control the lights. The relays are latching so I would have to pulse them rather than keep them on.
So the Arduino would set the start time (by buttons) on the RTC, then the RTC would count the time for the Arduino, and then it sorts out what time to put on?
Thank you for the advice
dhenry - Thank you very much for that code, i'll have a proper read over it, trying to understand all the different parts
Riva - I was planning on using el wire rather than LEDs, I didn't think the board could supply that much power, or am I completely wrong? But yes it is sort of like a word clock.
So the Arduino would set the start time (by buttons) on the RTC, then the RTC would count the time for the Arduino, and then it sorts out what time to put on?
If that final it refers to the Arduino, rather than the RTC, then yes.
You might try this code. I have found my crystal equipped duemilanova tracks the time really well. http://www.time.gov/timezone.cgi?Eastern/d/-5/java
Download this, with the time set a minute or so ahead, then open the serial monitor when the time is about 2-3 seconds ahead of where you set it.
For example, I set mine for 9:26, uploaded to the board, and at 9:25:57 I opened the serial monitor, which reset the board with a time at 9:26.
When I have run this in the past I did not see it drifting at all.
// time display test
unsigned long currentmicros = 0;
unsigned long previousmicros = 0;
unsigned long interval = 10000;
byte tens_hours = 0; // enter the time here, add in reading some buttons to make it standalone/adjustable
byte ones_hours = 9;
byte tens_minutes = 2;
byte ones_minutes = 6;
byte tens_seconds = 0;
byte ones_seconds = 0;
byte tenths = 0;
byte hundredths= 0;
byte prior_seconds = 0;
void setup()
{
Serial.begin(57600);
}
void loop()
{
currentmicros = micros(); // read the time.
while (currentmicros - previousmicros >= interval) // 10 milliseconds have gone by
{
hundredths = hundredths +1;
if (hundredths == 10){
hundredths = 0;
tenths = tenths +1;
}
if (tenths == 10){
tenths = 0;
ones_seconds = ones_seconds +1;
}
if (ones_seconds == 10){
ones_seconds = 0;
tens_seconds = tens_seconds +1;
}
if (tens_seconds == 6){
tens_seconds = 0;
ones_minutes = ones_minutes +1;
}
if (ones_minutes == 10){
ones_minutes = 0;
tens_minutes = tens_minutes +1;
}
if (tens_minutes == 6){
tens_minutes = 0;
ones_hours = ones_hours +1;
}
if (ones_hours == 10){
ones_hours = 0;
tens_hours = tens_hours +1;
}
if (tens_hours == 3){
tens_hours = 0;
}
previousmicros = previousmicros + interval; // update for the next comparison
}
// counters are all updated now,
if (prior_seconds != ones_seconds){
Serial.print (tens_hours, DEC);
Serial.print (" ");
Serial.print (ones_hours, DEC);
Serial.print (" : ");
Serial.print (tens_minutes, DEC);
Serial.print (" ");
Serial.print (ones_minutes, DEC);
Serial.print (" : ");
Serial.print (tens_seconds, DEC);
Serial.print (" ");
Serial.println (ones_seconds, DEC);
prior_seconds = ones_seconds;
}
} // end void loop
No, the onboard clock source - an actual crystal vs a resonator. Vs an RTC, which is a seperate chip with its own crystal. DS1307 is one chip, I2C interface and uses 32.768KHz crystal. Ohers are DS3231 & DS3234, both are somewhat larger chips but have built-in crystal and supposedly more accurate.
This was just test code, so it only outputs to the serial monitor.
Would be straightforward to output to an LCD, replace the serial print calls with LCD calls.
You can use a rtc but it is really not need for your application: the main crystal does an excellent job keeping time, if you code it so.
On the other hand, if the clock/Arduino ever looses power, you get to reset the time again. An RTC has a battery backup, so it isn't necessary to reset it.
Relays will be noisy, quite expensive (given the number you require and the fact that they will all need drivers) and unreliable in the long term. Why not use opto triacs instead, like this board https://www.sparkfun.com/products/11323 does?
PaulS:
On the other hand, if the clock/Arduino ever looses power, you get to reset the time again. An RTC has a battery backup, so it isn't necessary to reset it.
Going on that I think it's the best choice.
dc42:
Relays will be noisy, quite expensive (given the number you require and the fact that they will all need drivers) and unreliable in the long term. Why not use opto triacs instead, like this board https://www.sparkfun.com/products/11323 does?
Unfortunately I live in the UK, I could only find them for US sale? Plus I already won 50 relays off ebay... so there isn't a problem on price, and they're latching so I don't need to have a current flowing through them, just need to pulse them, so I'm assuming there will be no noise... What do I need the drivers for? Thanks again everyone
How much voltage and current do your latching relays need? The Arduino has a current limit of 40mA per pin, plus a per-chip limit (e.g. 200mA total Vcc or ground current for the Uno).
Thank you very much for pointing me in the right direction, so I'd need 24 of them? And I only just got the relays, they were listed at 4.2V-6V, but didn't mention current and I haven't had a chance to test them... I found some on a website and they said they'd work with Arduino boards though
If you have a multimeter, measure the resistance of a relay coil, then you can work out the current @ 5V (Ohms's Law). If it's less than 40mA then you can drive it directly from an Arduino pin - although you must connect a diode in parallel with the coil to absorb the back emf when you turn it off.
I've got my clock code fixed. It actually tracks time correctly now - was 6 hours off this morning! Finally realized I reset the hours when time rolled over at 30:00 instead of 24:00 - oops!
Running again now, made it past midnight okay. Running in sync since I reset it around 7:00pm.
unsigned long currentmicros = 0;
unsigned long nextmicros = 0;
unsigned long interval = 10000;
byte tens_hours = 1;
byte ones_hours = 8;
byte tens_minutes = 5;
byte ones_minutes = 4;
byte tens_seconds = 3;
byte ones_seconds = 0;
byte tenths = 0;
byte hundredths= 0;
byte prior_seconds = 0;
void setup()
{
Serial.begin(57600);
nextmicros = micros();
}
void loop()
{
currentmicros = micros(); // read the time.
if ((currentmicros - nextmicros) >= interval) // 10 milliseconds have gone by
{
hundredths = hundredths +1;
if (hundredths == 10){
hundredths = 0;
tenths = tenths +1;
}
if (tenths == 10){
tenths = 0;
ones_seconds = ones_seconds +1;
}
if (ones_seconds == 10){
ones_seconds = 0;
tens_seconds = tens_seconds +1;
}
if (tens_seconds == 6){
tens_seconds = 0;
ones_minutes = ones_minutes +1;
}
if (ones_minutes == 10){
ones_minutes = 0;
tens_minutes = tens_minutes +1;
}
if (tens_minutes == 6){
tens_minutes = 0;
ones_hours = ones_hours +1;
}
if (ones_hours == 10){
ones_hours = 0;
tens_hours = tens_hours +1;
}
if ((tens_hours == 2) && (ones_hours == 4)){
ones_hours = 0;
tens_hours = 0;
}
nextmicros = nextmicros + interval; // update for the next comparison
} // end time interval check
// counters are all updated now, send to display
if (prior_seconds != ones_seconds){
Serial.print (tens_hours, DEC);
Serial.print (" ");
Serial.print (ones_hours, DEC);
Serial.print (" : ");
Serial.print (tens_minutes, DEC);
Serial.print (" ");
Serial.print (ones_minutes, DEC);
Serial.print (" : ");
Serial.print (tens_seconds, DEC);
Serial.print (" ");
Serial.println (ones_seconds, DEC);
prior_seconds = ones_seconds; // show time update once/second
} // end one second passing check
// do other stuff in the meantime ...
} // end void loop
Sorry for the slow reply, been away and didn't have an internet connection...
dc42:
If you have a multimeter, measure the resistance of a relay coil
Tried it and got a value of 1, which can't be right... So I'm not sure what to do about that. Should I be checking while it's switching? Or is just putting a multimeter across it okay? Sorry for my poor knowledge on this...
Thanks again CrossRoads, I am trying my hardest to understand what is going on, fear I may have jumped in at the deep end...
Tried it and got a value of 1, which can't be right... So I'm not sure what to do about that. Should I be checking while it's switching? Or is just putting a multimeter across it okay? Sorry for my poor knowledge on this...
You have to measure the relay coil resistance 'out of circuit', meaning no other wires (or diode) attached to the relay coil, just the multimeter leads across the relay coil terminals.