Building a Binary Clock – In the HTML5 Canvas

I recently found my Arduino from my first year at University and really want to build something with it so I hopped on the net and surfed about and quickly rediscovered Binary/LED Clocks.

I don’t know about you but I find all these LED and Binary clocks really cool and nerdy! So I jotted down some ideas in my notebook and looked up how I might make it.

I am not very good with electronics as it turns out so I have decided to put the actual physical building on the back-burner until I have sussed exactly how I’d make such a thing. So I thought I’d instead make a software version first, and it’d be an excuse to practice with NetBeans, HTML5 and JavaScript.

Preparation

First I needed to understand how a binary clock works. It’s quite simple really, it takes the current time, in hours minutes and seconds, and displays them using an array of LEDs instead of a seven segment display like normal digital clocks. To the uneducated it can seem very difficult to read the time off of a these clocks but for someone familiar with binary it can be very easy in fact. Note the picture there is actually using BCD as opposed to pure binary which is still very easy to read! I’ve chosen to go with regular binary because I like the look of it better.

So for the time in the format Hours:Minutes:Seconds we’d take each section and convert it into binary and use that to discern what LEDs should be on or off for a corresponding section.

For example 10:35:06 would be:

Hours: 1010
Minutes: 100011
Seconds: 110

And out of curiosity the maximum values (23:59:59 assuming we are using a 24 hour clock) for each section would be:

Hours: 10111
Minutes: 111011
Seconds: 111011

Which means in reality we’d only need 17 LEDS if we were to build it from electronics.

But we aren’t building it out of electronics right now so onto NetBeans!

Note: You can do this all outside of an IDE, in a simple text editor if you like! I just used NetBeans because of it’s debugging tools.

Coding it

We will start by creating a new HTML5 application in NetBeans.

Next we will set up the canvas tags:

<canvas id="watchCanvas" width="500" height="500">You're browser does not support the HTML5 Canvas</canvas>

Now to draw on the canvas we need some JavaScript! Let’s add some basic test code to make sure it’s working.

	    var c = document.getElementById("watchCanvas");
	    var context = c.getContext("2d");
	    context.fillStyle="#FF0000";
	    context.fillRect(0,0,500,500);

That should give us a very ugly red square where our canvas is. For now let’s leave that as it is.

Next lets start thinking about how we will convert the time into binary and then into something that looks good using JavaScript.

The JavaScript

Luckily JavaScript has some very handy built in functions and objects that will fulfil our needs. Creating a Date object is our first action as it has some handy functions including getHours(), getMinutes() and getSeconds() that let us get all the parts of the time we need. Next we need to convert the results to binary. This is again incredibly simple, the number objects returned by each of these functions each have a method called toString() that will let us convert them into a string with a certain base if we choose. Below is some code illustrating all of these together:

	    var date = new Date();
	    console.log("Hours: " + date.getHours() + " = " + date.getHours().toString(2));
	    console.log("Minutes: " + date.getMinutes() + " = " + date.getMinutes().toString(2));
	    console.log("Seconds: " + date.getSeconds() + " = " + date.getSeconds().toString(2));

So how are we going to display these on the screen? We could just write out the text onto a pretend display but that would be pretty boring and not really a Binary Clock. Why not make some squares light up on an image for now? We can get really artistic later (well you can).

First let’s load an image for the clock face since I don’t really want to be doing lots of complicated drawing using all the shape commands:

	    var clockFace = new Image();
	    clockFace.onload = function() {
		context.drawImage(clockFace, 0, 0);
	    };
	    clockFace.src = 'binaryClock.png';

That code there just makes a new Image object and draws it at the correct position when it’s finished loading.

Now the code for drawing the binary string as some ‘LEDs’.

	    function drawTime() {
		var hours = date.getHours().toString(2);
		var mins = date.getMinutes().toString(2);
		var secs = date.getSeconds().toString(2);

		var boxHeight = 10;
		var boxWidth = 10;
		var hoursY = 20;

		function drawString(string, Y) {
		    context.strokeStyle = "black";
		    context.lineWidth = 1;
		    for(var n = 0;n < string.length; n ++) {
			if(string[n] === "1") {
			    context.fillStyle = "rgba(255, 0, 0, 1)";
			}
			else {
			    context.fillStyle = "rgba(255, 0, 0, 0.1)";
			}
			context.fillRect(n*boxWidth,Y,boxWidth,boxHeight);
			context.strokeRect(n*boxWidth,Y,boxWidth,boxHeight);
		    }
		}
		drawString(hours, hoursY);
		drawString(mins, hoursY+10);
		drawString(secs, hoursY+20);
	    }

Hopefully this is easy enough to follow, we loop through the string and draw a representation of each character at a certain position. I’ve enclosed it in function because it seemed appropriate, I’ve also embedded within it another function to reduce the amount of code I needed to write.

If you place drawTime(); just after context.drawImage(clockFace, 0, 0); you will see the result.

If you’ve paid attention to the output of toString(2) you may of noticed a small problem, it is only as long as it needs to be. This means that if the decimal number we turn into a binary number will affect the position of the on and off ‘LEDs’ on the screen so for instance if it was 1 we’d get just one ‘LED’. To fix this I’ve added another parameter to drawString() that defines how long the string should be and if it is shorter we prepend some 0′s onto it.

		function drawString(string, Y, len) {
		    if(string.length < len) {
			var needed = len - string.length;
			for(var n = 0;n < needed; n ++) {
			    string = "0" + string;
			}
		    }

Now I get a result something like this:

Still a bit bland. So let’s centre it or at least move it away from the edge a bit and space them out a little.

Looks a little nicer!

Making it Update

Currently we just have a static page that shows the time when it was loaded, that won’t do! We want this to automatically update each second.

This is actually really simple to do since we place our drawing code inside drawTime() all we need to is add setTimeout(‘drawTime()’,1000); to the end of it, move the drawing of the image within it and add a clear command:

	    var c = document.getElementById("watchCanvas");
	    var context = c.getContext("2d");

	    var clockFace = new Image();
	    clockFace.src = "binaryClock.png";
	    clockFace.onload = function() {
		drawTime();
	    };

	    function drawTime() {
		context.clearRect ( 0 , 0 , 200 , 200 );
		context.drawImage(clockFace, 0, 0);
		var date = new Date();
		var hours = date.getHours().toString(2);
		var mins = date.getMinutes().toString(2);
		var secs = date.getSeconds().toString(2);

		var boxHeight = 10;
		var boxWidth = 10;
		var ledAmount = 6;

		var xOffset = (144 / 6) - 10;
		var yGap = 10;

		function drawString(string, Y, len) {
		    if(string.length < len) {
			var needed = len - string.length;
			for(var n = 0;n < needed; n ++) {
			    string = "0" + string;
			}
		    }
		    context.strokeStyle = "black";
		    context.lineWidth = 1;
		    for(var n = 0;n < string.length; n ++) {
			if(string[n] === "1") {
			    context.fillStyle = "rgba(255, 0, 0, 1)";
			}
			else {
			    context.fillStyle = "rgba(255, 0, 0, 0.1)";
			}
			context.fillRect((n*boxWidth)+xOffset+(yGap*n), Y, boxWidth, boxHeight);
			context.strokeRect((n*boxWidth)+xOffset+(yGap*n), Y, boxWidth, boxHeight);
		    }
		}
		var hoursY = 20;
		var minsY = hoursY*2;
		var secsY = hoursY*3;
		drawString(hours, hoursY, ledAmount);
		drawString(mins, minsY, ledAmount);
		drawString(secs, secsY, ledAmount);
		setTimeout('drawTime()',1000);
	    }

 

And that’s everything! We’ve now built a Binary Clock using JavaScript and HTML5! You can view the finished product here.

3 Comments

  1. Tom Burman says:

    Really nice mate, I like reading your blogs! haha. My dissertation is based on html5 JS and php etc, so was good to see someone elses insight into the canvas element. Tom

  2. Alex Kloss says:

    If you want to be sub-second-precise, use

    setTimeout(drawTime, 1000-date%1000);

Leave a Reply