The Plan: The plan was simple. I'd bought an arduino with the intention of learning how to use it and I had a clock bought from Maplin which was horrendously inaccurate. I'd wanted a binary clock for ages so that seemed an ideal candidate, I wanted to build it around the arduino so I could easily upgrade it and potentially sync time over serial if necessary etc. This is my first microprocessor based project so it seemed like the easiest way, next time I'll do it properly ;-) I wanted something that would be accurate and easy to read at night but not so bright that it lights the whole room. I bought 15 degree narrow beam LEDs as I quite liked the effect of having them shining through something which also limited the amount of light coming out, ideal. I believe the correct value of resistor for these LEDs would be 220 ohm but I bought a selection and after some experimentation went with the highest value I'd got, 2.2k ohm, so the LEDs are nothing like as bright as they could be but they're plenty bright enough. Mk1 Build: I found a great design for a binary clock here so I used it pretty much without modification to create the Mk1: The stripboard layout was pretty simple, the LEDs have 5 strips between them so I used them to take each LED down to the bottom to connect to the arduino, connected the grounds together and added the circuitry for the switches to the top. All the wires go to the arduino, +5v, Gnd, digital 1-13 for LED outputs, digital 0 to turn lights off and a couple of analog inputs for the switches to change the time. I bought some translucent red boxes to build into but as it happened they were a bit small, I ended up having to put the arduino under the LED board which wasn't ideal. I managed to fit the board with some plastic blocks, spacing it nicely from the front. The projection idea of the LEDs works well but means they have to be soldered very carefully to keep them in line! The accuracy of this clock wasn't too bad using the arduino's internal crystal but ultimately it would drift and I didn't want to have to set the time at all if possible. I gave the Mk1 to a friend and started work on the Mk2, around the same time as Hack-a-Day reviewed the Macetech Chronodot so I took advantage of the deal and ordered a few Chronodohs. It's a high precision RTC module which should be as accurate as I need and it's battery backed up so I should very rarely need to set the time. The arduino uses I2C to talk to the RTC so that was something else I had to learn, getting the time from it was easy enough but setting the time took a bit of searching. In the end I found this page which contains all the relevant information. Thankfully the I2C bus uses analog pins 4 and 5 which were about the only ones I had free! I used the original code for the buttons to adjust the time of the RTC if necessary, it's not terribly reliable but I don't need it very much! You can see it at the bottom of the code block below. Mk2 Build: Without much foresight I made the LED board for the Mk2 with almost no excess round the edges which made mounting it tricky but as it happened, it was almost perfect. I had found a couple of old BT multimeters on Freecycle a few months back but never found a use for them, I took a look at one to find that the battery compartment opening was exactly the same size as the LED board, it looks cool as anything and has plenty of space and mounting points. I had planned to use the yellow box to house it but as it happens it sits quite nicely without but it's a handy carry case! It also has an analog gauge which I found I could control using PWM so I figured it would make a great second hand for the clock. This was dead easy to implement, I worked out how much resistance I needed so that a PWM value of 255 would make the gauge go all the way to the top then I just took the seconds value from the RTC, multiplied it by 4.2 (4.2*60=252, close enough to 255..) and had it update in the main loop. I had to use digital output 3 for PWM so the switch to turn the lights off had to go, no matter since I can just turn the whole thing off and have it keep time, so for Mk2 the LEDs are connected to digital outputs 0-2 and 4-13. The movement of the gauge isn't totally smooth but it's good enough and the alignment is spot on. Check out the terminally boring video below! Sadly the glass was cracked on both the gauges before I got them. Once it was all working together I fitted it into the multimeter, bolted the arduino in, connected the LED board with some ribbon cable in a bit of spiral wrap, terminated in some pin connectors which push fit into the arduino. I made a small board with pullup resistors for the I2C bus and the buttons which is not attached to anything but the wires are pretty stiff, it's not going anywhere. I had to use 5 22k ohm resistors for the gauge (didn't have anything bigger!) so they're on a little board of their own. As it happened, the LED board fitted perfectly into the original battery holder, secured with some cable ties. this also allowed me to adjust the gap between the LEDs and the front of the case. I attached some threaded rod to the battery holder which fitted nicely into the original clips, also allowing me to bolt something to diffuse the light on the front. I started with some of the mica from the multimeter, it's somewhat translucent and gave a nice effect but combined with a sheet of stripboard it's perfect, easily readable in any light but doesn't cast much light into the room. The final code is hacked together from what I've found, I think its all from the 2 sources credited at the top but if I've missed anything, let me know. I can't vouch for the quality of the code (or anything on this page!) but it's working great for me. The circuit diagram is available in pieces elsewhere but I've included it here for completeness. ![]() Parts List: I bought DFRduino Duemilanoves for £17.20 each on eBay UK, the Chronodohs worked out at £6/each. The rest of the parts were bought from Rapid Online (list below) making the total cost around £35 per clock. Comparable in price to a commercial product but so much cooler! 78-1522 BLACK BUTTON PUSH TO MAKE (RC) EACH 0.32 2 0.64 78-0237 LATCHING PUSH SW DOME BUTTON RED RC EACH 0.47 1 0.47 22-0795 36 WAY R/A SINGLE ROW PLUG (RC) EACH 0.33 1 0.33 62-0378 PACK 100 2K2 0.25W CF RESISTOR (RC) PACK 0.50 1 0.50 55-2476 LED 5MM HB RED 20000MCD (RC) EACH 0.20 13 2.60 34-0505 64 X 95MM STRIPBOARD (RC) EACH 0.62 1 0.62 30-3866 POLYCARBONATE BOX 150 X 80 X 50 RED (RC) EACH 4.35 1 4.35 34-0600 STRIPBOARD CUTTER (RE) EACH 2.49 1 2.49 Source Code: /*An open-source binary clock for Arduino. Based on the code from by Rob Faludi (http://www.faludi.com) Code under (cc) by Daniel Spillere Andrade, www.danielandrade.net http://creativecommons.org/license/cc-gpl Digital pins 0-2,4-13 LED outputs Digital pin 3 PWM output to gauge Analog pins 0,1 time adjustment buttons Analog pins 4,5 to Chronodoti2c code from http://www.glacialwanderer.com/hobbyrobotics/?p=12 */#include <Wire.h>int munit,hunit,valm=0,valh=0,i,gaugetemp;void setup() { //set outputs pinMode(0, OUTPUT); pinMode(1, OUTPUT); pinMode(2, OUTPUT); pinMode(4, OUTPUT); pinMode(5, OUTPUT); pinMode(6, OUTPUT); pinMode(7, OUTPUT); pinMode(8, OUTPUT); pinMode(9, OUTPUT); pinMode(10, OUTPUT); pinMode(11, OUTPUT); pinMode(12, OUTPUT); pinMode(13, OUTPUT); Wire.begin();}// Convert normal decimal numbers to binary coded decimalbyte decToBcd(byte val){ return ( (val/10*16) + (val%10) );}// Convert binary coded decimal to normal decimal numbersbyte bcdToDec(byte val){ return ( (val/16*10) + (val%16) );}void loop(){ // send request to receive data starting at register 0 Wire.beginTransmission(104); // 104 is DS3231 device address Wire.send(0); // start at register 0 Wire.endTransmission(); Wire.requestFrom(104, 3); // request three bytes (seconds, minutes, hours) while(Wire.available()) { int second = Wire.receive(); // get seconds int minute = Wire.receive(); // get minutes int hour = Wire.receive(); // get hours second = (((second & 0b11110000)>>4)*10 + (second & 0b00001111)); // convert BCD to decimal minute = (((minute & 0b11110000)>>4)*10 + (minute & 0b00001111)); // convert BCD to decimal hour = (((hour & 0b00110000)>>4)*10 + (hour & 0b00001111)); // convert BCD to decimal (assume 24 hour mode) munit = minute%10; //sets the variable munit and hunit for the unit digits hunit = hour%10; //Light LEDs to show the time //minutes units if(munit == 1 || munit == 3 || munit == 5 || munit == 7 || munit == 9) { digitalWrite(0, HIGH); } else { digitalWrite(0, LOW); } if(munit == 2 || munit == 3 || munit == 6 || munit == 7) { digitalWrite(1, HIGH); } else { digitalWrite(1,LOW); } if(munit == 4 || munit == 5 || munit == 6 || munit == 7) { digitalWrite(2, HIGH); } else { digitalWrite(2,LOW); } if(munit == 8 || munit == 9) { digitalWrite(4, HIGH); } else { digitalWrite(4,LOW); } //minutes if((minute >= 10 && minute < 20) || (minute >= 30 && minute < 40) || (minute >= 50 && minute < 60)) { digitalWrite(5, HIGH); } else { digitalWrite(5,LOW); } if(minute >= 20 && minute < 40) { digitalWrite(6, HIGH); } else { digitalWrite(6,LOW); } if(minute >= 40 && minute < 60) { digitalWrite(7, HIGH); } else { digitalWrite(7,LOW); } //hour units if(hunit == 1 || hunit == 3 || hunit == 5 || hunit == 7 || hunit == 9) { digitalWrite(8, HIGH); } else { digitalWrite(8,LOW); } if(hunit == 2 || hunit == 3 || hunit == 6 || hunit == 7) { digitalWrite(9, HIGH); } else { digitalWrite(9,LOW); } if(hunit == 4 || hunit == 5 || hunit == 6 || hunit == 7) { digitalWrite(10, HIGH); } else { digitalWrite(10,LOW); } if(hunit == 8 || hunit == 9) { digitalWrite(11, HIGH); } else { digitalWrite(11,LOW); } //hour if(hour >= 10 && hour < 20) { digitalWrite(12, HIGH); } else { digitalWrite(12,LOW); } if(hour >= 20 && hour < 24) { digitalWrite(13, HIGH); } else { digitalWrite(13,LOW); } int gaugetemp=second*4.2; //Turn seconds into PWM value analogWrite(3, gaugetemp); //Write PWM value to gauge delay(500); //Only run every half second, plenty often enough valm = analogRead(0); // add one minute when pressed if(valm<800) { minute++; //Take the minute value, add one, write to RTC Wire.beginTransmission(104); // Open I2C line in write mode Wire.send(0x00); // Set the register pointer to (0x00) Wire.send(decToBcd(00)); // Write three bytes Wire.send(decToBcd(minute)); Wire.send(decToBcd(hour)); Wire.endTransmission(); // End write mode delay(250); } valh = analogRead(1); // add one hour when pressed if(valh<800) { hour++; //Take the hour value, add one, write to RTC Wire.beginTransmission(104); // Open I2C line in write mode Wire.send(0x00); // Set the register pointer to (0x00) Wire.send(decToBcd(00)); // Write three bytes Wire.send(decToBcd(minute)); Wire.send(decToBcd(hour)); Wire.endTransmission(); // End write mode delay(250); } }} |

