Arduino project: Digital Clock

Arduino is the world’s favourite microcontroller board and despite its low 16MHz/8-bit computing power, it can drive robots, connect to Twitter and even power 3D printers and quadcopters. One of the many reasons for its success is the number of expansion boards or shields available.

We’ve already looked at a few including the W5100 Ethernet Shield, along with two motor drive shields — one for DC motors (used in our Rolly Robot project and free-roaming Attacknid hack) and one for servo motors (powering our Stompy walking robot project). But it’s the ability to make Arduino handle human interaction that makes it so versatile.

We’ve already looked at how you can connect your Arduino to your TV showing weather information and playing Space Invaders, but there is a low-cost shield that can display data in a far more compact way.

The 1602 LCD Shield

One of the most popular shields is the 1602 LCD Shield. You can find clones of these everywhere on eBay selling for as little as $6 and that includes shipping. The shield itself delivers a smaller daughterboard containing an alphanumeric LCD panel consisting of two lines with 16 characters per line, typically driven by the popular Hitachi HD44780 LCD controller. Throw in five user-programmable push-button switches plus on-board master reset button and you have the 1602 LCD Shield.


The shield’s rear has no components so it can’t short against the Arduino board.

These little 16×2 LCD panels have been around for over 20 years — I created a simple project in Silicon Chip magazine back in 1993 that connected one to a PC’s parallel printer port. But it’s only with the introduction of Arduino that they’ve become so ridiculously cheap. And by integrating the LCD panel into a shield, there’s no soldering involved — you just slot it into place using the Arduino’s Shield header pins.

The LCD panel is backlit, lighting as soon as power is applied, but it can be turned off by programming. While green-backlit panels are common, there’s a growing number of blue-backlit options as well. The six push-button switches are located on the bottom left side with four in a plus-pad arrangement, the outer switch on the left designated as Select and a master-reset button on the far right. Press the reset button and your sketch will restart. You can adjust the LCD contrast by the small potentiometer (or ‘pot’ for short) at the top-left. Adjust it so the blank pixels are just beginning to darken and back it off a little. There are many different brands of 1602 Shield on the market but they all conform to this basic layout.

So not only do you have a compact display device but you can also handle user feedback, which makes this shield an ideal project companion to any compatible Arduino microcontroller board.


Again, this is one of those shields whose applications are only limited by your imagination. Normally when demonstrating something for the first time, you do the equivalent of ‘Hello, world’ program or ‘sketch’, but to show you how the interaction works, we decided to go a bit further by creating our own simple digital clock. We’ve taken our clock the extra step by 3D printing a case designed for this particular shield, complete with push-button actuators.


The push-buttons allow for user feedback, but only use one analog input.

Programming the Shield

As usual, we’re making the sketch available on our web site for this project and you’ll find it over at Copy the contents of the /libraries folder to the /arduino -1.0.5/libraries folder, launch the Arduino IDE and load the sketch file.

There are a few things going on in this sketch but here’s the overview — basically we need to display initial information on the LCD panel, handle input via the shield buttons and accurately updating the time display once every second.


The tiny 10kohm potentiometer (pot) sets the LCD screen contrast.


The 1602 LCD Shield relies on two specific software libraries — LiquidCrystal and LCDKeypad. The very first thing you have to do is initial the LCD Shield so that the Arduino microcontroller knows what you’re playing with. And it’s here you may find initial problems. While there are many different 1602 Shield clones available, not all use the same pin configuration, so the LiquidCrystal library is designed to allow you to set it to your specific shield. You can read about it at Keeping it short, virtually all 16×2 LCD panels can run over a 4-bit data bus with two extra control pins — RS (register select) and EN (enable).

If you purchase the super-cheap $6 DFRobot shield (like we did), you’ll probably find that using pin D8 for RS and pin D9 for EN, along with D4-D7 for the four-bit data bus pins should work. This is outlined in the code line:

LiquidCrystal lcd(8,9,4,5,6,7);

Once that’s done, displaying text on the panel is as simple as setting to cursor position using the setCursor command and printing your text through the print command like this:


lcd.print(“Darren’s little”);


lcd.print(“digital clock”);

The cursor position is set by (char, row) with each dimension starting with zero, meaning the top line is ‘row 0’ and the bottom line ‘row 1’. There are numerous other functions available as well.

Programming push-buttons

One of the more unusual aspects of this shield is how the buttons are electrically connected to the Arduino. Push-button switches are essentially digital in their actuation — they’re either on or off. However, with five input switches, you could potentially tie up five digital input/output (I/O) lines to handle them. But instead, the switches are all connected to just one of the analog inputs. When you push one of the buttons, it sets up a specific voltage on the analog input through a resistor network.

Using DFRobot’s LCDkeypad library, you can check for these inputs to know which button was pressed and perform an appropriate action. It’s a little awkward in how it works but using one input rather than five leaves you more I/O lines for your project. The five analog values are stored in a one-dimension array at the start of the sketch:

int adc_key_val[5] ={ 50, 200, 400, 600, 800 };

We incorporated a common routine used to check the input value to see which button was pressed.

How do you code a clock?

Your PC, notebook, tablet and smartphone all have clock apps built into their operating systems. In fact, clocks are such an important part of where computing meets the real world that special electronic modules called ‘real time clocks’ (RTCs) have been invented with the express job of simply keeping the time.

When you want a software program to create a change in some real-world hardware at a particular event, such as a push-button being pressed, you generate what’s called an interrupt. As its name suggests, its job is to interrupt the main flow of the software to launch a specific function. Depending on the microcontroller (or CPU), interrupts can be triggered by hardware (a specific input for example) or software.

Our clock keeps track of the year, month, day, date, hour, minutes and seconds. Since the second counter is the smallest unit we need to update, we’ll need to ensure it gets updated each second. We don’t have an RTC at our disposal so to create the interrupt, we use the TimedAction library like this:

TimedAction timer = TimedAction(1000,clockUpdate);

This library allows you to create a repeating interrupt trigger at a program-defined time interval that runs a procedure or function. We use this library to create a repeating interrupt once per second (1000 milliseconds). Each time it triggers, we run the clockUpdate code function that increments the seconds counter and takes care of the rollover for each new minute, hour, day, date, month and year.

Setting the time

In normal operation, a clock doesn’t have to interact with the outside world — except when you’re setting the time to begin with. In one way, we’ve taken a fairly basic approach to time setting — you do this as soon as you power up the Arduino clock through a series of questions you answer for each of the time intervals — year, month, day, date, hour, minute — using the Up, Down and Select buttons to set each option. Once you press the Select button, you move onto the next setting. After pressing it the final time, the clock sketch goes into the time function loop and updates every second.


Setting the time is as simple as using the Up, Down and Select buttons.

However, the backroom code automatically sets the correct options for each time interval — for example, you set the month by selecting from January, February and so on; days from Sunday, Monday etc. Once you set the month, you can choose the correct day, which means the code knows that January has 31 days; April has 30, and so on. You can’t select ‘April 31’ for example. It also knows the difference between AM and PM and that there can only be 60 minutes in an hour, 60 seconds in a minute. We do this using a series of two-dimensional character arrays like this:

char day[7][10] = { “Sunday “,”Monday “,”Tuesday “,”Wednesday”,”Thursday “,”Friday “,”Saturday “};

Here, we’re setting up the day options — the array has seven elements, each with 10 characters. Because of the way Arduino works, you must fill the array characters explicitly, which is the reason for the blank spaces in the smaller day names. If you don’t, your sketch won’t compile for you.

So overall, this is a more complex example of allowing a choice from a limited number of options and varying the options for subsequent input based on previous selections.

What our sketch doesn’t do is take into account leap years — we’ll leave that as an exercise for you to do. It also doesn’t allow for time modification after the initial setup. To do that, you have to hit the Reset button and start again.

Remember, the idea here is to show off the LCD Shield as well as show how to code for it into your apps. The rest is up to you.

3D printed case

To finish off our clock, we’ve had a look on and not surprisingly, there are dozens of brackets and cases designed for various members of the Arduino family. We were expecting to have to buy a small general-purpose ABS plastic Jiffy box from Jaycar Electronics to put our clock in, but someone has designed a case specifically to use this Arduino/Shield combo, so we printed it out on our Printrbot Jr 3D printer. You can check out the case at


You don’t need to screw the Arduino/Shield combo into place in the case — it will sit in position on its own once the two shell halves come together. The only thing you need to be careful of is the two retention clips. These can break so don’t press the clips — press on shell either side of the clips to compress it so the clips will lock into the base. Make sure the button actuators move cleanly inside their holes too, otherwise, they’ll jam up the switches. Use a small wood file to open the holes as necessary — just not too much or the actuators will fall out.


The shield slots into the Arduino Uno board, overhanging on one end only.


The clock consumes little power so you can either grab a simple 5VDC/200mA power brick with the right 2.1mm DC plug or you can get a cheap USB phone charger and power the clock through the USB port. Either way will work just fine.


The clock can be powered by USB cable or DC power adapter.

Modification ideas

The sketch code for this clock we threw together in a day is more a demonstration of how the 1602 Shield works. But if you want to modify it, go right ahead. Improvements we can think of straight away are:

  • a simpler time-adjustment system without resetting
  • battery backup
  • automatic backlight dimming
  • programmable alarm with snooze
  • FM radio

Sure, you can buy a clock radio that does all of this but where’s the fun in that? We don’t care what anyone says — the best way to learn is by doing and there’s plenty of scope for exploring ideas in this project. For example, you could use the Arduino to control another device via a user-settable alarm time — it could be your bed-side lamp or your coffee maker. That’s well beyond the entry-level hobbyist but it just takes a spark of imagination to come up with your own ideas.


Our digital clock inside a 3D printed case designed for this shield.

  • Using DFRobot’s LCDkeypad library, you can check for these inputs to know which button was pressed and perform an appropriate action. It’s a little awkward in how it works but using one input rather than five leaves you more I/O lines for your project. The five analog values are stored in a one-dimension array at the start of the sketch:

  • Terrence J MacCabe

    I just put this together using Freetronics Eleven R3 and Freetronics 16X2 LCD Shield V2.0 and it worked perfectly first time so for some home grown products you can’t go past Freetronics and APC Mag, thanks for the project Darren, Cheers.

  • Bryan Posso

    Having issues when uploading: “APC_clock_v2:46: error: ‘clockUpdate’ was not declared in this scope

    TimedAction timer = TimedAction(1000,clockUpdate);


    exit status 1

    ‘clockUpdate’ was not declared in this scope”

    Any suggestions?

    • Hi Bryan,
      Just check you haven’t made any inadvertent changes to the source code. Other readers have had success with it – try downloading it again and having another go. ‘clockUpdate’ is the subroutine or ‘method’ that makes the project work, so just make sure you can see a ‘void clockUpdate()’ method in the code.

      • Mark

        It doesn’t work in Arduino 1.6.5.

        • Taylor

          See my response above. 🙂

    • Taylor

      You need to move: TimedAction timer = TimedAction(1000,clockUpdate);
      To below the clockUpdate function.

      And move the clockUpdate Function above the void loop function.

  • Bill

    Hi Darren,
    Many Thanks for your wonderful & informative projects !!!
    I’ve built your Arduino Wi-Fi – Part 1 & 2 projects.
    There is one issue with the regulator device. It only outputs 2.9V to the WiFi module under load. So I got around that by using a digital power supply.
    In Part 1, all I see in the serial monitor is some random characters, then the WiFi identifying itself, followed by random characters again, but they stop.
    In Part 2, I consistently get 6 lines of random characters, followed by “—Sensor OK—Ready—& then Temperature & Humidity” values line after line, which is great !!!
    As far as the communication between the WiFi & the Arduino goes, there could be an issue.
    Unfortunately, my C++ coding leaves a lot to be desired, but at least I’m learning something in Python.
    Is it possible that the WiFi module is damaged ?
    Please help Darren !!!

    • Hi BIll,

      When you say you get ‘temperature & humidity values’, are they are actual values? If you’re getting random characters, 1) I think there are possibly Chinese characters in the firmware that are not being translated by the Serial Monitor, but 2) I’d just check that the baud rate is set right.

      The reason I say that is another reader has found (and I was remiss in mentioning this in the original story) that early ESP8266 modules had the baud rate set to 115200, whereas more recent versions had it set to 9600.

      You can set the baud rate yourself using the command:


      to read the baud rate, and:


      to set it to 9600bps.

      Also a bit surprised to hear the regulator module is only 2.9V under load. Are we talking about an AMS1117-3.3 regulator here? If so, just check that your wiring is right, just to be sure. I’m pretty certain the ESP8266 won’t survive 5VDC on its supply rail, so stick with it.
      Could the ESP8266 be damaged? All things are possible, but the only way to know for sure is to grab a second one and compare – as long as you’re happy that the code is working as it should.
      I would get to know the Hayes AT modem commands for the ESP8266 and just check that you get understandable responses from it before you decide its damaged.

      Anyway, hope that helps,

  • Bill

    Happy New Year Darren !!!
    I’ve tried a new WiFi module from Core Electronics. Now I get about 6 lines of nothing, before it goes into the DHT22 readings, which are correct.
    The regulator can only supply 2.7-2.9 volts with your original circuit.
    So I put 5.0V in from my lab supply, clamped @ a maximum of 300mA. Now the WiFi module is getting 3.32V.
    At this stage, it looks like a problem with the code.
    Also, when you first power everything up, there is a burst of activity on the blue WiFi LED, followed by two blinks on the red breadboard LED, which both stay off afterwards.
    Please help !!!
    Bill Sakell

  • saksham

    thank you

    • saksham

      but how can i add alarm to my clock