Arduino Project #21 – Sports Timekeeper

About a month or so ago, we received a request from APC reader Don Fraser for a special-design count-down timer using an Arduino Uno and a Freetronics 32×16-LED dot-matrix display (DMD). After looking at the idea, I realised this could be made into a project to suit a wider audience and still meet Don’s requirements. It also turned out to be an ideal project for looking at how the design process works when you’re making your own gear.

Keeping time

The Sports Timekeeper counts down from anywhere between one and 99 minutes, selectable in one-minute increments and will sound a siren (or in our case, a piezo buzzer) as the time period ends. It shows minutes and seconds on the display and you can pause and restart the clock with the same button (such as for ‘time off’ in a footy match).

We’ve kept the design really simple but you could easily expand it if you have some basic knowledge of electronics. All you need for this simple build is:

  • Arduino Uno R2 or R3 microcontroller board
  • DIY prototyping shield
  • Freetronics 32×16-LED dot matrix display
  • Three momentary-on pushbuttons
  • 5VDC piezo buzzer
  • A dozen dupont wires

And lastly, our source code/sketch software available free from our Arduino webpage at


How it works

The key component is that 320x160mm-sized 32×16-LED Dot Matrix Display (DMD) from local Australian retailer Freetronics ( We introduced it into our masterclass series not long ago with the Audio Spectrum Analyser project, but it’s such a versatile display, you could use it for 1001 different ideas.

With 512 LEDs to control, you’d be forgiven for wondering how we drive it with an Arduino having just 21 I/O ports. The simple answer is we don’t have to worry about that – the DMD only requires six digital I/O pins from the Arduino and uses a technique called ‘multiplexing’ to control them. We’ll look more at the software driving it shortly.

Switched on

In the meantime, we need to figure out some way to set the initial time it’ll begin to count down from, as well as some way to start, stop or pause the timer. For this project, we thought rather than go the whole hog like we did with the Arduino Enigma Cipher Machine and build the finished product, we’d go for a basic working mock-up via a breadboard instead, just so you can see how the whole thing works. And for that, we’ve used the DIY prototyping shield with a tiny breadboard on top.

Thanks to the relative ease of programming microcontrollers like the Atmel ATMEGA328P we’re using here, there’s a tendency these days for designs to go overboard with features. In fact, the end result can be so overloaded with buttons and options that it takes a 50-page manual to work out how to drive the thing! That’s why it’s so important to work out what your project design is meant to do right at the start, long before you lift a screwdriver. Once you start building, stick to the design like glue and be aware of ‘feature creep’.

One thing that can help is remembering who your device is intended for – always err on the side of simplicity with controls and ask yourself do you really need that many buttons or controls.

That’s why our Sports Timekeeper has just three buttons – two black ones and a red one. The two black ones set up the initial time in minutes – the left increments the count by 10, the right by one. Once a digit reaches ‘9’, the next press loops it around to ‘0’ again.


A typical design for doing this would give each digit separate ‘up’ and ‘down’ buttons/switches, but our method saves those two extra switches. At 20cents each wholesale, a 40-cent saving is nothing, but if you’re planning to make 50,000 widgets, that saving alone puts $20,000 back in your pocket.

The red button is the start/pause button – press it to start the count down, press it again to pause it (‘time off’) and press it yet again to restart it. Once the timer is started, you can’t change the initial time settings, but just put it in pause mode and you can ‘change away’. The Sports Timekeeper will simply count down from whatever is displayed on the DMD once it’s restarted.

We’ve added a tiny 5VDC piezo buzzer so that when the timer hits zero, it will sound off continuously in addition to putting up the ‘FULL TIME’ sign, until the reset button on the DIY proto shield is pressed. Finally, the DMD connector slots into the Arduino via the pin header on the DIY proto shield itself.

Because the DMD uses high-brightness LEDs, you can get a decent brightness level with just the power connected to the Arduino. But for a seriously bright output, you can connect up a power supply direct to the DMD, but it needs to be capable of up to 30-amps(!)

fulltime countdown

How the code works

Because the hardware isn’t as complex this month, we’ve got the opportunity to spend more time on how the code works and there are some tricks here worth knowing.

The complex task of controlling the DMD is thankfully handled by the free DMD library, reducing it to little more than print commands to display text, but we still have to create the timing code and handle the input from the momentary switches.

Switch debouncing

First up, let’s tackle the common problem of what’s called switch ‘contact bouncing’. When you press a mechanical switch, you don’t just get a single instantaneous change from one voltage level to another. If you were to watch what the switch does via a cathode ray oscilloscope (CRO), you’d see dozens of ‘ups and downs’ or noise pulses for a few tenths of a second until the switch stops ‘bouncing’ and it settles into its new ‘pressed’ state. Now if we just set our code to react to any change in voltage level, the code would trigger on each one of those pulses and we’d end up counting dozens instead of just one.


‘Debouncing a switch’ just means providing electronic circuitry or code to recognise the first ‘leading edge’ change only and ignore the rest while it steadies up. There are lots of complicated ways you can do this in software, depending on how tight a time tolerance you need in your code. But we’ve used a very simple, very crude but very effective solution here – and that’s to simply set off a 200-millisecond delay once a level change is detected. That 200 milliseconds gives the switch sufficient time to stop bouncing without noticeably affecting other code. It also provides an added feature – hold the button down and that digit will increment at around five counts per second. (As an experiment, try changing the number in the delay(200) commands inside the loop() method of our sketch code and see what happens!)

How long is one second?

You set the time of our Sports Timekeeper in minutes, but it displays the count down in seconds – so here’s a question: just how long is one second? Unfortunately, an Arduino doesn’t come with an in-built clock we can watch Mickey’s second-hand tick around on. But what it does have, however, is a crystal-locked 16MHz clock signal driving the microcontroller, creating a new clock pulse every 62.5nanoseconds. It also has three timers on-board – not timers in the usual sense, but binary counters that can be clocked by at a fraction or ‘prescaler’ of that 16MHz clock signal. You might remember we used one of these timers in our Digital Audio Recorder project a few months ago. We can do something similar here – use a timer to launch a trigger or ‘interrupt’ at a precise time interval (let’s say 1000 milliseconds) to decrement our count and update the DMD.

And that’s exactly what we do here – except, we’re cheating and using the free TimedAction library to do the hard yakka for us, but this is essentially how the library works. In the end, the Arduino triggers an interrupt after each second, which is then directed to launch the clockUpdate method in our code that decrements the count and updates the display.

dmdrear-1 uno

Monitoring the switches

While the code is continually waiting for each second and the interrupt that triggers our decrementing code, we also need to keep an eye on the start/stop button, so we can pause or restart the count on the user’s command.

When writing Arduino code, there are only two methods you need to include – setup() and loop(). Setup() runs once at the start and loop() loops continually until the power is removed or the reset button is pressed. That loop() method provides us with the coding window we need to monitor the button switches.

Those switches are connected up to three of the Arduino’s analog ports, A3, A4 and A5, all configured as digital inputs and using the built-in pull-up resistors. The switches we’re using are basic momentary-on pushbutton switches – essentially, they act as though you’re just joining two wires together. The pull-up resistors are activated by the pinMode command:

pinMode(A5, INPUT_PULLUP);

and ensure that the corresponding Arduino input sees 5VDC (a digital ‘high’) when the button isn’t pressed (that is, it’s ‘open’), but is pulled to ground (digital ‘low’) when it is pressed (the switch is ‘closed’). Using the Arduino’s internal resistors also mean we don’t have to supply our own, saving more money in our design. Again, these are cost-savings you would need to consider when designing real products.

The loop() method contains two main code threads – one that monitors whether or not the clock timer is paused, in which case, it keeps an eye on inputs A3 and A4 (the initial time set buttons), and another thread that monitors input A5 (the start/stop button).

timeset timeoff time45

DMD code

The Freetronics’ 32×16-LED DMD comes with free Arduino code libraries that make it extremely easy to write text on the display. To start, you ‘initialise’ the library by creating a new DMD ‘object’ we’re calling ‘dmd’ (lowercase). After creating a second timer called ‘Timer1’ using the TimerOne library and attaching it to our dmd object, we then call the ‘dmd.clearScreen(true)’ command to blank the display and ‘dmd.selectFont’ to choose one of three display fonts included in the code library.

We write text to the DMD using the ‘dmd.drawString(x,y, string, string_length, display_code)’ command. The ‘x’ and ‘y’ refer to the pixel coordinates (x,y) of the DMD where the first letter will begin, with top-left being (0,0). The ‘string’ refers to the text you want displayed, while ‘string_length’ is an integer representing the number of characters in the string. The ‘display_code’ allows you to change how the display works, such as display rotation etc.

For example, our ‘FULL TIME’ sign requires two commands:



We start at the sixth pixel across on the first row (co-ordinates are zero-based), draw ‘FULL’, move to the same pixel across but down to the ninth row and draw ‘TIME’. To be honest, we’re not sure why the ‘string_length’ parameter exists in this command since it can be calculated from the string itself.

switch piezo

Extra code libraries

While our sketch/source code may not have many lines (117 lines isn’t long), it does take advantage of a number of extra libraries to work.

  • The SPI (Serial Peripheral Interface) library turns pins D9, D10, D11 into an SPI port to transfer data fast enough to the DMD so that we see a smooth, non-flickering display.
  • The DMD library converts the commands we issue into actual LEDs lighting up on the display.
  • We also need the TimerOne library to work with the DMD code to set the display rate timing (that’s the ‘multiplexing’ we talked about at the beginning).
  • And finally, there’s the TimedAction library to create our one-second interrupts.

Code libraries are brilliant inventions because they allow us to incorporate reusable code to save us reinventing the wheel each time. The Arduino website ( has lots of freely available code libraries, so before you try coding a function from scratch, see if a suitable code library exists you can leverage off.

Get designing!

Designing Arduino projects is a two-part step – you figure out the electronics you’re connecting to the microcontroller board and then write the code that makes the whole thing work. Start simple and get the very basic features working, slowly building up until you have your project. Just remember to beware of ‘feature creep’, otherwise, you may never get it finished!


  • Rizki Hermawan

    Can this code work properly with arduino nano?