Arduino Binary Clock

This is a simple Arduino Binary Clock. It comes with a program that generates the script and uploads it to the arduino board. Part of the code isn’t mine only the part that allows you to get the time from the computer and configure the script to use it.

You can download the script maker program from here. You can get this same circuit diagram by opening the program with the /C parameter. There are a lot of command-line options to choose from to configure your Binary Clock. R1 through R13 must have a value that will limit the current enough that it will not break the Arduino or any of its pins. Its probably best to use a 1kilo ohm resistor.

program binclock_uno;

{$APPTYPE CONSOLE}
{$RESOURCE binclock_uno32.RES}
{This program will need binclock.ino added to the resource as ID 1 
and type "ARDUINO" You can use Resource Hacker to build binclock_uno32.RES file.
 The schematic is id 1 and type is "JPEG"}

uses
  SysUtils,
  graphics,
  jpeg,
  windows,shellapi,
  Classes;
const INSERT_POINT='//INSERT_POINT';
//To make the program use less memory and file size, we will use format type string constants
STRING_VAR='String %s = "%s";';
ARDUINO_PINVALUES:ARRAY[0..1]OF STRING=('LOW','HIGH');
DEFINE_INTEGER='#define %s %d';
DEFINE_STRING='#define %s %s';
BYTE_VAR='byte %s=%u;';
INO_PATH='%s\%s.ino';
var args,inofile:tstringlist;
res:tresourcestream;
i:integer;
st:systemtime;
exename:string;
herr:hinst;
rs1:longint;
arduino_exename,inocommand,inoname:array[0..max_path]of char;
tid:dword;
function GetConsoleWindow:hwnd;stdcall;external kernel32;
function ConsolePicture(id:integer):dword;stdcall;
//This thread draws the schematic onto the console window
var jpg:tjpegimage;
ConsoleCanvas:tcanvas;
res:tresourcestream;
r:Trect;
label loop;
begin
jpg:=tjpegimage.Create;
res:=tresourcestream.CreateFromID(hinstance,id,'JPEG');
jpg.LoadFromStream(res);res.Free;
consolecanvas:=TCanvas.Create;
consolecanvas.Handle:=getdc(getconsolewindow);
loop:
getclientrect(getconsolewindow,r);
r.Left:=0;r.Top:=0;
consolecanvas.StretchDraw(r,jpg);
sleep(5000);
goto loop;
end;

begin
args:=tstringlist.Create;
for i:=1 to paramcount do
args.Add(Paramstr(i));
exename:=extractfilename(paramstr(0));
if paramcount=0then begin
writeln('Usage:',exename,' /BIAS=OFFSET /MIDNIGHT /C /F=FILENAME /UP /UTC /24 /12 /LED=number /HBTN=ANALOG_PIN /MBTN=ANALOG_PIN /NBTN');
writeln('/UTC       Use UTC Time instead of localtime.');
writeln('/BIAS      Uses a custom timezone bias');
writeln('/12        Use 12-hour format');
writeln('/24        Use 24-hour format');
writeln('/LED       Sets the LED on position logic, 0 for cathode 1 for anode');
writeln('/MBTN      Analog pin for Minute button');
writeln('/HBTN      Analog pin for Hour button');
Writeln('/NBTN      Disable the use of buttons');
writeln('/UP        Automatically upload file to Arduino');
writeln('/F         The output script name(without .ino extension),if omitted it will be stored as binclock\binclock.ino');
writeln('/C         Brings up the circuit diagram for the clock');
writeln('/MIDNIGHT  Use midnight as the starting time instead of computer clock');
writeln;
writeln('Example: Use a LOW value on all digital LED pins and UTC Time and 24-hour format');
writeln(exename,' /UTC /24 /LED=0 /F=MyBinClock /UP');
write('Press enter to quit...');
readln;
args.Free;
exitprocess(0);
end;
if args.IndexOf('/C')>-1Then
begin
createthread(nil,0,@consolepicture,pointer(1),0,tid);
readln;
exitprocess(0);
end;
getsystemtime(st);
if args.IndexOfName('/BIAS')=-1then args.Values['/BIAS']:='00:00';
datetimetosystemtime(systemtimetodatetime(st)-strtotime(args.Values['/BIAS']),
st);
gettimezoneinformation(tz);
if args.indexofname('/F')=-1 then args.Values['/F']:='binclock';
createdirectory(strpcopy(inoname,args.values['/F']),nil);
res:=tresourcestream.CreateFromID(hinstance,1,'ARDUINO');
inofile:=tstringlist.Create;
inofile.LoadFromStream(res);
res.Free;
if(strtointdef(args.values['/LED'],1)<0)or(strtointdef(args.values['/LED'],1)>1)
then begin writeln('Invalid /LED value');args.free;inofile.free;
exitprocess(error_invalid_parameter);end;
inofile.Insert(inofile.indexof(insert_point),format(define_string,['LED_ON',
ARDUINO_PINVALUES[strtointdef(args.values['/LED'],1)]]));
inofile.Insert(inofile.indexof(insert_point),FORMAT(DEFINE_STRING,['LED_OFF',
ARDUINO_PINVALUES[Strtointdef(args.values['/LED'],1)xor 1]]));
if args.IndexOf('/UTC')=-1Then getlocaltime(st);
if(args.IndexOf('/12')>-1)and(args.IndexOf('/24')>-1)then begin
writeln('Cannot use both /24 and /12 parameters at the same time');
args.Free;inofile.Free;
exitprocess(error_invalid_parameter);
end;
if args.IndexOf('/MIDNIGHT')>-1then begin if args.IndexOf('/12')>-1then
st.wHour:=12 else st.wHour:=0;st.wMinute:=0;st.wSecond:=0;end;
if(args.indexof('/24')=-1)and(args.IndexOf('/12')=-1)then begin
writeln('Must have a hour format parameter');inofile.Free;args.Free;
exitprocess(error_invalid_parameter);
end;
if args.indexof('/12')>-1then begin
inofile.Insert(inofile.indexof(insert_point),FORMAT(DEFINE_INTEGER,['HOUR_FORMAT',
12]));
if st.wHour=0then st.wHour:=12;
if st.wHour>12then
 st.wHour:=st.wHour-12;
end else
inofile.Insert(inofile.indexof(insert_point),FORMAT(DEFINE_INTEGER,['HOUR_FORMAT',
24]));
inofile.Insert(inofile.indexof(insert_point),FORMAT(DEFINE_INTEGER,['ANALOG_HSET',
STRTOINTDEF(ARGS.VALUES['/HBTN'],5)]));
inofile.Insert(inofile.indexof(insert_point),FORMAT(DEFINE_INTEGER,['ANALOG_MSET',
STRTOINTDEF(ARGS.VALUES['/MBTN'],0)]));
if args.IndexOf('/NBTN')=-1then inofile.Insert(inofile.indexof(insert_point),
FORMAT(DEFINE_STRING,['BUTTONS_ENABLED','true']))else inofile.Insert(
inofile.indexof(insert_point),FORMAT(DEFINE_STRING,['BUTTONS_ENABLED','false']));
inofile.Insert(inofile.indexof(insert_point),FORMAT(BYTE_VAR,['hour',ST.WHOUR]));
inofile.Insert(inofile.indexof(insert_point),FORMAT(BYTE_VAR,['minute',st.wminute]));
inofile.Insert(inofile.indexof(insert_point),FORMAT(BYTE_VAR,['second',st.wSecond]));
inofile.SaveToFile(format(ino_path,[inoname,inoname]));
writeln('Script saved to ',format(ino_path,[inoname,inoname]));
if args.IndexOf('/UP')>-1then begin rs1:=sizeof(arduino_exename);regqueryvalue(
hkey_classes_root,'Arduino File\shell\open\command',arduino_exename,rs1);herr:=
shellexecute(0,nil,strpcopy(arduino_exename,stringreplace(arduino_exename,' "%1"',
'',[])),strfmt(inocommand,'--upload "%s\%s.ino"',[inoname,inoname]),nil,sw_showdefault);
if herr<33then begin
if herr=0then writeln('Out of resources')else writeln(syserrormessage(herr));
args.Free;inofile.Free;
exitprocess(herr);
end;end;
args.Free;
inofile.Free;
exitprocess(0);
end.
/* Filename binclock.ino
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

I modified the code a little bit so it can have
12-hour format and pin configuration.

By Justin Roeder

/* IMPORTANT NOTICE BEFORE ADDING THIS SCRIPT TO THE RESOURCE OF THE GENERATOR EXECUTABLE
YOU MUST REMOVE ALL OF THE LINES UNTIL YOU GET TO //INSERT_POINT
LEAVE //INSERT_POINT IN SCRIPT. THAT TELLS THE GENERATOR WHERE TO PUT THE VARIABLES.
IF YOU ARE JUST GOING TO UPLOAD THHIS SCRIPT TO THE BOARD, YOU CAN LEAVE THE CODE ALONE. 
*/
#define LED_ON HIGH //LED Bit on logic
#define LED_OFF LOW //LED Bit off logic
#define HOUR_FORMAT 24 //Change to 12 for 12 hour time
#define ANALOG_HSET 5 //defines hour set button pin
#define ANALOG_MSET 0 //defines minure set buttonpin
#define BUTTONS_ENABLED true //set to false to disable buttons
byte hour=0;
byte minute=0;
byte second=0;
//Start at midnight 00:00:00
//INSERT_POINT

int munit,hunit,valm=0,valh=0,ledstats,i;
void setup() {
//set outputs 
for(int k=1;k<=13;k++) {
  pinMode(k, OUTPUT);
}
//set inputs
pinMode(0, INPUT);
}
void loop() {

static unsigned long lastTick = 0; // set up a local variable to hold the last time we moved forward one second
// (static variables are initialized once and keep their values between function calls)
// move forward one second every 1000 milliseconds

if (millis() - lastTick >= 1000) {
  lastTick = millis();
  second++;
}
// move forward one minute every 60 seconds
  if (second >= 60) {
  minute++;
  second = 0; // reset seconds to zero
}
// move forward one hour every 60 minutes
if (minute >=60) {
  hour++;
  minute = 0; // reset minutes to zero
}

if (hour >=24) {
  hour  = 0;
  minute  = 0; // reset minutes to zero
}
if(HOUR_FORMAT==12){
  if(hour>12){hour=hour-12;}
  if(hour==0){hour=12;}
}
  munit = minute%10; //sets the variable munit and hunit for the unit digits
  hunit = hour%10;
  ledstats = digitalRead(0);  // read input value, for setting leds off, but keeping count
  if (ledstats == LOW) {
   for(i=1;i<=13;i++){
    
    digitalWrite(i, LED_OFF);}

  } else  {

  //minutes units
  if(munit == 1 || munit == 3 || munit == 5 || munit == 7 || munit == 9) {  digitalWrite(1, LED_ON);} else {  digitalWrite(1,LED_OFF);}
  if(munit == 2 || munit == 3 || munit == 6 || munit == 7) {digitalWrite(2, LED_ON);} else {digitalWrite(2,LED_OFF);}
  if(munit == 4 || munit == 5 || munit == 6 || munit == 7) {digitalWrite(3, LED_ON);} else {digitalWrite(3,LED_OFF);}
  if(munit == 8 || munit == 9) {digitalWrite(4, LED_ON);} else {digitalWrite(4,LED_OFF);}

  //minutes 
  if((minute >= 10 && minute < 20) || (minute >= 30 && minute < 40) || (minute >= 50 && minute < 60))  {digitalWrite(5, LED_ON);} else {digitalWrite(5,LED_OFF);}
  if(minute >= 20 && minute < 40)  {digitalWrite(6, LED_ON);} else {digitalWrite(6,LED_OFF);}
  if(minute >= 40 && minute < 60) {digitalWrite(7, LED_ON);} else {digitalWrite(7,LED_OFF);}

  //hour units
  if(hunit == 1 || hunit == 3 || hunit == 5 || hunit == 7 || hunit == 9) {digitalWrite(8, LED_ON);} else {digitalWrite(8,LED_OFF);}
  if(hunit == 2 || hunit == 3 || hunit == 6 || hunit == 7) {digitalWrite(9, LED_ON);} else {digitalWrite(9,LED_OFF);}
  if(hunit == 4 || hunit == 5 || hunit == 6 || hunit == 7) {digitalWrite(10, LED_ON);} else {digitalWrite(10,LED_OFF);}
  if(hunit == 8 || hunit == 9) {digitalWrite(11, LED_ON);} else {digitalWrite(11,LED_OFF);}

  //hour
  if(hour >= 10 && hour < 20)  {digitalWrite(12, LED_ON);} else {digitalWrite(12,LED_OFF);}
  if(hour >= 20 && hour < 24)  {digitalWrite(13, LED_ON);} else {digitalWrite(13,LED_OFF);}

}
if(BUTTONS_ENABLED){ 
 valm = analogRead(ANALOG_MSET);    // add one minute when pressed
   if(valm<800) {
   minute++;
   second = 0;
   delay(250);
  }
  valh = analogRead(ANALOG_HSET);    // add one hour when pressed
   if(valh<800) {
   hour++;
   second = 0;
   delay(250);
  }}
}

How to read the display?

Each column represents a digit. As seen in the circuit diagram. A led has a row number the top LED like D4 in x1Minute is 8 below it is 4, 2, and 1. To get the digit for the column just add the row numbers. Below this paragraph is my binary clock screensaver showing 05:56:10 is read on the screen.

Binary Clock 05:56:10

I’m in the process of building itm I’m waiting for the 13 LEDs, resistors and project box. I am going to leave the buttons out of the one I’m building. If you are doing this then use the /NBTN parameter. I will keep you updated

Published by Justin Roeder

I am an electronics engineer and computer programmer that has autism. I learned by myself

Leave a comment

Your email address will not be published. Required fields are marked *