Arduino Binary Clock
I've finally made it, the binary clock the people around me heard me talked about for so long. I was trying to make this during the last christmas break, but time was lacking, I changed jobs 2 times in the last 6 months... so things were a bit hectic, but now everything is fine and I did it :)
I don't want to pretend like it's my idea. I took the design from this great instructables : My Arduino Binary Clock by Cello62 and I gave it my touch.
I used a real time clock to keep exact time, I used just the Atmega328 instead of a full Arduino and made some small changes here and there, but the clock's design is all Cello62's.
The Arduino Prototype
First I made the prototype with the Arduino, then I prototyped the circuit I would have in the final product, using the Atmega328 chip instead of the full Arduino to be sure that everything was working correctly.
The Schematics
Here you can see how the push buttons, the leds and the real time clock are connected with the Arduino.
N.B. the resistance values are not correct.
The Code
First let's setup the beginning to communicate with the real time clock and keep the time
#include <Wire.h>
//DS3232 I2C Address #define RTC_ADDRESS 0x68
//DS3232 Register Addresses #define RTC_SECONDS 0x00 #define RTC_MINUTES 0x01 #define RTC_HOURS 0x02
//Times keeping variables
byte seconds; //00-59 byte minutes; //00-59 byte hours; //00-23
Then we set constants to define the pins of the Arduino for the leds and push buttons
//Buttons pins
const int minutesButton = 14; const int hoursButton = 15;//LED pins const int hoursPin10 = 0; const int hoursPin20 = 1;
const int hoursPin1 = 2; const int hoursPin2 = 3; const int hoursPin4 = 4; const int hoursPin8 = 5;
const int minutesPin10 = 6; const int minutesPin20 = 7; const int minutesPin40 = 8;
const int minutesPin1 = 9; const int minutesPin2 = 10; const int minutesPin4 = 11; const int minutesPin8 = 12;
Then we need to initialize everything in the setup function
void setup() {
//Set Button pins mode pinMode(minutesButton, INPUT); pinMode(hoursButton, INPUT); //Set LED pins mode pinMode(hoursPin10, OUTPUT); pinMode(hoursPin20, OUTPUT); pinMode(hoursPin1, OUTPUT); pinMode(hoursPin2, OUTPUT); pinMode(hoursPin4, OUTPUT); pinMode(hoursPin8, OUTPUT); pinMode(minutesPin10, OUTPUT); pinMode(minutesPin20, OUTPUT); pinMode(minutesPin40, OUTPUT); pinMode(minutesPin1, OUTPUT); pinMode(minutesPin2, OUTPUT); pinMode(minutesPin4, OUTPUT); pinMode(minutesPin8, OUTPUT); //Start the RTC communication Wire.begin(); //Initialize and set time seconds = 00; minutes = 00; hours = 00; }
And we will have a simple loop function calling different functions to do the work it needs to do. We will sleep for 500 ms because we don't need to loop as fast as we can, this also helps with setting the time when we press the push buttons so it doesn't change too fast.
void loop() {
checkInputs(); getTime(); displayLights(); delay(500); }
Here's how we check for push buttons inputs and react to them
//----- Input Function -----
void checkInputs() { if (digitalRead(minutesButton) == HIGH) { minutes++; seconds = 00; if (minutes == 60) { minutes = 00; } setTime(); } if (digitalRead(hoursButton) == HIGH) { hours++; seconds = 00; if (hours == 24) { hours = 00; } setTime(); } }
To access the real time clock, let's create a setTime and getTime function
//----- RTC Functions -----
void setTime() { Wire.beginTransmission(RTC_ADDRESS); Wire.write(0); Wire.write(decToBcd(seconds)); Wire.write(decToBcd(minutes)); Wire.write(decToBcd(hours)); Wire.endTransmission(); }
void getTime() { Wire.beginTransmission(RTC_ADDRESS); Wire.write(0x00); Wire.endTransmission(); Wire.requestFrom(RTC_ADDRESS, 3); seconds = bcdToDec(Wire.read()); minutes = bcdToDec(Wire.read()); hours = bcdToDec(Wire.read() & 0b00111111); }
You probably noticed some strange function calls in the code above... let's create those utility functions. They are useful to convert decimal numbers to a byte readable by the real time clock protocol and vice versa
//----- Utility functions ----
byte decToBcd(byte val) { return ( (val/10*16) + (val%10) ); }
byte bcdToDec(byte val) { return ( (val/16*10) + (val%16) ); }
Now let's turn on and turn off the appropriate leds depending on what time it is
//----- Display Function -----
void displayLights() { if (hours >= 20) { digitalWrite(hoursPin20, HIGH); digitalWrite(hoursPin10, LOW); } else if (hours >= 10) { digitalWrite(hoursPin20, LOW); digitalWrite(hoursPin10, HIGH); } else { digitalWrite(hoursPin20, LOW); digitalWrite(hoursPin10, LOW); } int hoursUnit = hours % 10; if (hoursUnit >= 8) { digitalWrite(hoursPin8, HIGH); digitalWrite(hoursPin4, LOW); digitalWrite(hoursPin2, LOW); } else if (hoursUnit >= 6) { digitalWrite(hoursPin8, LOW); digitalWrite(hoursPin4, HIGH); digitalWrite(hoursPin2, HIGH); } else if (hoursUnit >= 4) { digitalWrite(hoursPin8, LOW); digitalWrite(hoursPin4, HIGH); digitalWrite(hoursPin2, LOW); } else if (hoursUnit >= 2) { digitalWrite(hoursPin8, LOW); digitalWrite(hoursPin4, LOW); digitalWrite(hoursPin2, HIGH); } else { digitalWrite(hoursPin8, LOW); digitalWrite(hoursPin4, LOW); digitalWrite(hoursPin2, LOW); } if (hoursUnit % 2 == 1) { digitalWrite(hoursPin1, HIGH); } else { digitalWrite(hoursPin1, LOW); } if (minutes >= 40) { digitalWrite(minutesPin40, HIGH); digitalWrite(minutesPin20, LOW); if (minutes >= 50) { digitalWrite(minutesPin10, HIGH); } else { digitalWrite(minutesPin10, LOW); } }else if (minutes >= 20) { digitalWrite(minutesPin40, LOW); digitalWrite(minutesPin20, HIGH); if (minutes >= 30) { digitalWrite(minutesPin10, HIGH); } else { digitalWrite(minutesPin10, LOW); } } else if (minutes >= 10) { digitalWrite(minutesPin40, LOW); digitalWrite(minutesPin20, LOW); digitalWrite(minutesPin10, HIGH); } else { digitalWrite(minutesPin40, LOW); digitalWrite(minutesPin20, LOW); digitalWrite(minutesPin10, LOW); } int minutesUnit = minutes % 10; if (minutesUnit >= 8) { digitalWrite(minutesPin8, HIGH); digitalWrite(minutesPin4, LOW); digitalWrite(minutesPin2, LOW); } else if (minutesUnit >= 6) { digitalWrite(minutesPin8, LOW); digitalWrite(minutesPin4, HIGH); digitalWrite(minutesPin2, HIGH); } else if (minutesUnit >= 4) { digitalWrite(minutesPin8, LOW); digitalWrite(minutesPin4, HIGH); digitalWrite(minutesPin2, LOW); } else if (minutesUnit >= 2) { digitalWrite(minutesPin8, LOW); digitalWrite(minutesPin4, LOW); digitalWrite(minutesPin2, HIGH); } else { digitalWrite(minutesPin8, LOW); digitalWrite(minutesPin4, LOW); digitalWrite(minutesPin2, LOW); } if (minutesUnit % 2 == 1) { digitalWrite(minutesPin1, HIGH); } else { digitalWrite(minutesPin1, LOW); } }
And the clock can work :)
Making the LED Board
Getting the tools ready.
Then you should print the file attached here to get a template of where to drill holes.
I used only 5mm LEDs.
I then got the glue gun out to make little "boxes" so the light from each LED doesn't travel to another hole.
Downloads
Installing the LEDs
I then installed the LEDs and put a resistor to every anode (-) pins.
And I connected them all together and to one of the wire of a flat ribbon wire.
Then I connected all the cathodes(+) to a wire part of a flat ribbon wire.
Making the Box
I then took a box big enough to house the circuit board, the buttons and the 5V D/C input.
I drilled holes for the buttons and got the size right after with a file.
I installed the buttons and fixed them with hot glue and identified the buttons to set the time. The red one is just to cut the flow of the ground for all the LEDs to turn off the lights without stopping the clock.
Making the Board
I then cut a board to the right size to install the circuit with the Atmega328 and all the wiring.
Putting It Together - Part Un
Let's hook up everything together in the box and test it.
Putting It Together - Part Deux
Then it's time to put everything in the frame, I reused a RIBBA frame that I had lying around (13cm x 18cm) (6" x 8") from IKEA... http://www.ikea.com/ca/en/catalog/products/00132524/
I decided to fix the boards with screws in the frame and to hold the box to the back of the frame with hot glue.
The Finished Product
Now it's time to see the final product, it's a nice piece of decoration.
To read the time you just need to add the values of each lights... for the tens and units of hours and the tens and units of minutes.
The first image would read (1, 2+4, 2, 1+2+4)... so 16h27
The last image would read (1, 1+2+4, 1+2, 1+2) so 17h33
The only thing I regret is not having more lights behind the Hours and Minutes at the top, because it doesn't light up properly... maybe one day I'll open it and make the modification.
Let me know what you think :)