Making a clock with arduino
Arduino
For once I wanted to have a bit of fun building a bit of hardware. Some times ago I stepped across the Arduino boards. They got plenty of input output and are easy to work with as you can write your code in C/C++.
Getting the time
The first step was to find a way to have the time on the Arduino. The Arduino itself doesn't have an RTC built in, which means it will lose the time as soon as the power is cut, and even if you manage to never remove the power, the precision of the clock is not very good.
Radio clock
At first I wanted to use the DCF77 signal broadcast to get the time. I found some receiver on conrad which I tried to interface with the Arduino.
With stable power supply no interference source, I was able to get the signal. Once obtained, the signal is easy to decode. But as soon as I tried near my computer or with a non ideal powersource, the signal was barely there.
This led me to find another way.
Using NTP
At first I thought of using NTP, which would be easy, but my clock is to be on the wall, not connected with my network. Of course, I could use a Wifi adapter of some sort, but they are expensive, and this solution sounds overkill.
Radio sync
Finally, I had an idea. I found some cheap radio transmitter using the 433Mhz band. I ended using the VirtualWire library which works very well.
I have a first arduino connected to a linux box via serial. This box sends over the serial interface time packets which are forwarded by the virtual wire library over to my arduino controlling my clock.
Code
Transmitter code
1 #include <VirtualWire.h>
2
3 #define TIMELEN 7 // YYMDHMS
4
5 void setup()
6 {
7 Serial.begin(115200);
8
9 vw_set_tx_pin(8);
10 vw_setup(2000);
11 }
12
13 void loop()
14 {
15 if (Serial.available())
16 {
17 byte code = Serial.read();
18 switch (code)
19 {
20 case 'T':
21 char buf[TIMELEN + 1] = "T";
22 if (Serial.readBytes(buf+1, TIMELEN) != TIMELEN)
23 {
24 Serial.println("ERR");
25 break;
26 }
27 vw_send((uint8_t *)buf, TIMELEN + 1);
28 vw_wait_tx();
29 Serial.println("OK");
30 break;
31 }
32 }
33 }
Receiver code:
1 void setup()
2 {
3 vw_set_rx_pin(RX_PIN);
4 vw_setup(2000);
5 vw_rx_start();
6
7 }
8
9 static void display_value(byte hour, byte minute)
10 {
11 byte v[4];
12 v[0] = numbers[hour / 10];
13 v[1] = numbers[hour % 10] | numbers[10];
14 v[2] = numbers[minute / 10];
15 v[3] = numbers[minute % 10];
16 // do whatever you want with v
17 }
18
19 void loop()
20 {
21 uint8_t buf[VW_MAX_MESSAGE_LEN];
22 uint8_t buflen = VW_MAX_MESSAGE_LEN;
23
24 static unsigned long last_update;
25 static byte last_hour;
26 static byte last_minute;
27 static byte last_second;
28 if (vw_get_message(buf, &buflen))
29 {
30 switch (buf[0])
31 {
32 case 'T':
33 if (buflen - 1 != TIMELEN)
34 break;
35 last_hour = buf[5];
36 last_minute = buf[6];
37 last_second = buf[7];
38 last_update = millis();
39 display_value(last_hour, last_minute);
40 return;
41 }
42 }
43 if (!last_update)
44 return;
45 int hour;
46 int minute;
47 unsigned long elapsed = (millis() - last_update) / 1000 + last_second;
48 minute = last_minute + elapsed / 60;
49 hour = last_hour + minute / 60;
50 display_value(hour % 24, minute % 60);
51 }
Pictures
Some pictures of the working clock.
Components
- Arduino UNO (note that one transmitter can sync multiple receivers)
- TI TLC5916IN LED drivers | http://ch.farnell.com/jsp/search/productdetail.jsp?SKU=1647814
- Avago HDSP-C2G1 | http://ch.farnell.com/jsp/search/productdetail.jsp?SKU=1830051
- Visalux VISUALUX (green filter) | http://ch.farnell.com/jsp/search/productdetail.jsp?SKU=178185
- IDC connectors (much faster than crimping) | http://ch.farnell.com/jsp/search/productdetail.jsp?SKU=9731849
- 433Mhz transmitter QUASAR QAM-TX1 | http://ch.farnell.com/jsp/search/productdetail.jsp?SKU=1304024
- 433Mhz receiver QUASAR QAM-RX2 | http://ch.farnell.com/jsp/search/productdetail.jsp?SKU=1304026
Libraries
While tinkering, I wrote two libraries, one for the led drivers, and one for the DCF77 antenna.
The one for the led driver works fine. The one for the DCF77 receiver works, but the signal has to be good, and as I never really got a good signal, I didn't work much on it.
- LED Driver http://github.com/goyman/led_driver
- DCF77 library http://github.com/goyman/dcf



