I bought an arduino a while back and I think it's really nice, but I haven't really done anything useful with it yet, so now I thought it was time to make a bigger project. I decided to do an alarm clock since my old one is broken.
Here's a video of it in action:
There seems to be some problems with the video embedding, If you can't see the video above, here's a link to it: binary alarm clock
Remove these ads by
Signing UpStep 1What should be done?
An alarm clock should be able to: What I used:
- keep time - code
- display time - LEDs 5 for hours, 6 for minutes
- keep an alarm time - code
- let the user set the time - buttons
- let the user set the alarm - buttons
- make noise when the alarm goes off. - speaker
- let the user snooze - touch sensor "button"
- let the user turn on and off the alarm. - touch sensor "button"
It would be nice if it also:
- looks reasonably good - a nice box as case
- is cool and geeky - true binary display
| « Previous Step | Download PDFView All Steps | Next Step » |











































From step 3:
"Here are the pins I used for the different parts:
- 2 and 4: Touchsensor (4 is the send pin, 2 is recieve)
- 6 Hour button
- 5 Minute button
- 7 Switch
- 14-18 Display hour pins
- 8-13 Display minute pins"
Thank!, and great instructable
I've always wanted to learn this kind of thing but don't know a single soul who knows much beyond not using the wrong adaptor for the printer (and some don't know that much!). The more instructables I read, though, the more convinced I am that I'll have to make one, some day. It's getting harder to resist. :)
I didn't know anyone that could help me much when I started learning about electronics etc. either, but the internet is full of information and you can ask at forums if you get stuck.
condition ? run if true : otherwise run this;
So you could do that first if() statement like this:
current_millis_value < previous_millis_value ? m += MAX_MILLIS_VALUE - previous_millis_value + current_millis_value : m += current_millis_value - previous_millis_value;
It's not as pretty, but as always, C ignores whitespace, so you can write it like this if you want to organize it a little:
current_millis_value < previous_millis_value ?
m += MAX_MILLIS_VALUE - previous_millis_value + current_millis_value :
m += current_millis_value - previous_millis_value;
It might run faster and eliminate some of the timing error.
Also, you might be able to spread out the time correction a little more evenly than 2 seconds every 5 hours. Since it's .4 seconds, that's 400 milliseconds every 60 minutes. That goes down to 20 milliseconds every 3 minutes. Since you're counting milliseconds directly, and the overall count of seconds is a multiple of 3, it might be overall a little more accurate to the user to do the correction more often.
Great tutorial though, I might have to try this!
About the time compensation, yes I have thought about that and maybe I will add it later. Since the clock only shows minutes I don't think it matter that much. The advantage with that method is that it's easier to compensate for cases when you have for example 0.43 instead.
Hmm, I somehow thought It would be more complicated to compensate the milliseconds, but now when I think about it, it should be as easy, one just have to make the millis variable signed, so the subtraction won't cause it to underflow.
Thanks for the suggestions, I'm glad you like the instructable!
Yeah, I'll have to see how ternary operators and if() statements compare when I finally get an Arduino (Christmas is coming, as my plan currently stands). For a lot of embedded environments, all those conditional structures get compiled down the same way anyway. I think I recall that the C18 compiler (for PIC microcontrollers, like the one in my VEX robot) compiles if() and switch() statements to the same thing. I wouldn't be surprised if it takes while() loops down to if()-goto structures. Or I guess I could just look at the avr-gcc manual, but that would be too easy :D
I think I might eventually try this project, I've wanted a binary clock for a while, and I love the AVR line. One thing that I found last night is that the Arduino bootloader still allows you to use the lower-level avr-gcc commands. It turns out that digitalWrite() takes about 10 times longer to run than accessing the PORT register directly, because with each call of digitalWrite(), it turns off all of the PWM timers (and in the comments in the code, the guy is asking why that couldn't be moved up to pinMode(), which is interesting). Basically, digitalWrite() is just some safety mechanisms and a parser for the PORT register. It sets the PORT of your choice (lets say pin 13, which is under PORT B, pin 5) to an entire byte all at once (you can toggle 8 pins just about simultaneously). This would work like this, IIRC:
PORT_B = 0b00010000;
Or, to only affect that pin, you can use the | operator:
PORT_B |= 0b00010000;
You don't have to make these modifications, I realize it would take a long time to recalibrate, just thought you might be interested. I still love the tutorial. I think it might also be interesting to make a multiplexed or charlieplexed version, just for funsies.
Wouldn't that just work if you want to correct at least 1 millisecond every second (60ms per minute) wich is more than I want to?
"[...]
It turns out that digitalWrite() takes about 10 times longer to run than accessing the PORT register directly, because with each call of digitalWrite(), it turns off all of the PWM timers (and in the comments in the code, the guy is asking why that couldn't be moved up to pinMode(), which is interesting).
PORT_B = 0b00010000;
[...]"
Actually there have been much discussion about how to make digitalWrite faster on the arduino developers mailinglist lately (link), maybe digitalWrite compiled to one instruction will come in the next version of the arduino ide.
I think I'll just wait for that since using digitalWrite makes the code cleaner and easier to understand*, and It works good as it is. I don't have much time now anyway to tinker with the clock, because I have calculus exam soon :S.
* = for me at least, I'm not used to the PORT stuff since I have mostly used the arduino. I would like to learn more how microcontrollers really work sometime though. The arduino hides all complexity, which is really nice, and makes it easy to make stuff with it, but it would be intresting to learn how it works low-level.
"You don't have to make these modifications, I realize it would take a long time to recalibrate"
I don't think I would have to recallibrate, the time error should come from the crystal oscillator frequency and not from how long it takes to execute the loop.
"I think it might also be interesting to make a multiplexed or charlieplexed version, just for funsies."
Yes, I would like to experiment with charlieplexing too sometime.
if(seconds==59 && m > (!minutes%3 ? 999+6 : 999+7)) { //If divisible by 3, add
seconds++; //18 ms, otherwise 19
m = 0;
}
else if(m>999) { //Normally, a second is just 1000ms
seconds++;
m = 0;
}
I think how you do it with the 2 seconds every 5 hours is fine by the way, this is more just a point of discussion.
-Simon