Arduino Binary Clock

by Clapoti in Circuits > Arduino

12106 Views, 74 Favorites, 0 Comments

Arduino Binary Clock

IMG_20150521_192533.jpg

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

IMG_20150419_142609.jpg
IMG_20150422_214901.jpg

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

prototype.jpg

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

IMG_20150419_150828.jpg
IMG_20150419_154626.jpg
IMG_20150419_160403.jpg
IMG_20150419_161346.jpg
IMG_20150419_164827.jpg
IMG_20150419_175359.jpg

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

IMG_20150425_173315.jpg
IMG_20150425_175138.jpg
IMG_20150425_175939.jpg
IMG_20150425_182116.jpg
IMG_20150426_083328.jpg
IMG_20150513_210150.jpg

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

IMG_20150512_201902.jpg
IMG_20150512_202430.jpg
IMG_20150513_210126.jpg

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

IMG_20150426_171352.jpg
IMG_20150512_201856.jpg
IMG_20150512_205223.jpg
IMG_20150512_210826.jpg
IMG_20150513_210138.jpg

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

IMG_20150513_210117.jpg
IMG_20150513_211611.jpg
IMG_20150513_220115.jpg

Let's hook up everything together in the box and test it.

Putting It Together - Part Deux

IMG_20150520_152501.jpg
IMG_20150520_154127.jpg
IMG_20150520_152535.jpg
IMG_20150520_154743.jpg
IMG_20150520_155909.jpg

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

IMG_20150520_160111.jpg
IMG_20150520_173209.jpg
IMG_20150520_173247.jpg
IMG_20150520_173302.jpg

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 :)