Introduction: HackerBoxes 0008: Clockwork

Picture of HackerBoxes 0008: Clockwork

[cue theme music]

Clockwork: This month, HackerBox Hackers are exploring time, clocks, and timekeeping. There is no time like the present. This Instructable contains information for working with HackerBoxes #0008.

HackerBoxes is the monthly subscription box service for electronics hobbyists, makers, and hackers. Even if you are not a HackerBoxes subscriber, you can always join in the fun using your own materials and equipment. Of course, if you would like to receive a box like this right to your mailbox each month, please SUBSCRIBE HERE and join the HackerBoxes movement. Hack the Planet!

Step 1: HackerBoxes #0008: Box Contents

Picture of HackerBoxes #0008: Box Contents
  • HackerBox #0008 Collectible Reference Card
  • Digital Clock Kit with Acrylic Case
  • Ublox GY-NEO6MV2 GPS Module
  • Ceramic GPS Antenna 25mm x 25mm
  • Arduino Pro Mini 328P - 5V/16MHz
  • PL2303 USB to Serial Module
  • DS1302 Real-Time Clock Module
  • ESP8266 ESP-01 Serial Wi-Fi Module
  • TM1637 LED Clock Display Module
  • MAX7219 LED 8x8 Matrix Module
  • 40 DuPont Jumper Wires (F/F 10cm)
  • Overclock Computer Decal

Step 2: What Is Time?

Picture of What Is Time?

This is a simple question with no simple answer. Wikipedia offers, "Time is the indefinite continued progression of existence and events that occur in apparently irreversible succession from the past through the present to the future. Time is a component quantity of various measurements used to sequence events, to compare the duration of events or the intervals between them, and to quantify rates of change of quantities in material reality or in the conscious experience. Time is often referred to as the fourth dimension, along with the three spatial dimensions."

Like we said... no simple answer. Fortunately, we all sort of agree that we know what it is when we see it. We can generally employ phrases like, "I'll be there in an hour," without suffering any sort of philosophical crisis. That said, if you have the curiosity to invest in the scientific and philosophical aspects of our question, consider the magnificent video entitled The Illusion of Time from NOVA.

In the simplest, practical terms, time may be understood by simply showing how we measure it. For example, watching the movement of the hands on a clock gives a feeling for what a second is, or a minute, or an hour. Watching the sun, moon, and seasons gives us a feeling for longer units of time.

Step 3: How Is Time Measured?

Picture of How Is Time Measured?

In this brief interview, the well known physicist, Neil deGrasse Tyson, is asked what is time? He explains that, without really needing to know what it is, we can keep track of time. He suggests, "If you have something that repeats predictably, then you have created a timekeeping mechanism."

In nature, systems that repeat predictably are oscillators and timekeeping mechanisms are clocks based on those oscillators. Our earliest "clocks" were astronomical observations using orbits as their predictable oscillators. Later time keeping technologies used pendulums and springs as their predictable oscillators. Modern clocks generally use oscillation within a crystal lattice (e.g. a quartz wristwatch) or electrons hopping between orbits around an atomic nucleus (e.g. an atomic clock).

The official international standard for the length of one second is 9,192,631,770 cycles of the radiation needed for a cesium atom to vibrate between two energy states. For more information, have a look at the NIST Timekeeping FAQ.

Step 4: Electronic Oscilators

Picture of Electronic Oscilators

Planetary orbits, pendulums, springs, and atomic clocks can serve as a basis for time keeping because they have known repeating frequencies of oscillation. The frequency at which a system naturally oscillates as the system's resonant frequency. This concept is useful when considering a tuning fork or a guitar string as additional examples of mechanical oscillators.

A circuit combining a capacitor and an inductor (an LC Circuit) also has a resonant frequency given by the values of the capacitor (C) and of the inductor (L). This circuit (often referred to as a "tank circuit") is the basis of many electronic oscillators along with various astable multivibrators, other relaxation oscillators, and crystal oscillators.

Here are a couple of nice videos that survey basic electronic oscillators:

What is an Oscillator? and
Electronic Basics: Oscillators.

Looking back on previous HackerBoxes, Box #0004 (Step 4) explored the astable mode of the 555 timer chip functioning as an oscillator. Box #0001 leveraged a ring oscillator to create a seemingly non-synchronized flashing LED effect. And of course, experiments for every HackerBox have relied upon crystal oscillators to clock microcontrollers and other digital circuitry.

Step 5: Crystal Oscillators

Picture of Crystal Oscillators

Pretty much all digital circuits use crystal clock oscillators. This video from EngineeringGuy illustrates just how amazing these components are. Would you believe that there are actually SEVEN crystal oscillators in this HackerBox? No lie! Can you identify them all?

Step 6: Set Up the Arduino Pro Mini

Picture of Set Up the Arduino Pro Mini

The Arduino Pro Mini is a microcontroller board based on the ATmega328. It was originally designed by SparkFun Electronics. While less than one square inch in area, the Pro Mini features 14 digital input/output pins, six analog inputs, a crystal oscillator, a voltage regulator, and a reset button.

Because the Arduino Pro Mini was intended for integration into other systems, it arrives without pre-mounted headers, allowing the use of various types of connectors or direct soldering of wires. For our purposes here, we will be interfacing the Pro Mini using female DuPont jumper wires, so you should start by carefully soldering in the provided header pins.

WARNING: If you are new to soldering, really take your time with this. Go very, very slowly and take great care. There are a lot of great guides and videos online about soldering. Here is one example. You might want to find an old junk PCB for some practice (un)soldering. If you feel that you need additional assistance, consider joining a local makers group or hacker space in your area. Also, amateur radio clubs are always excellent sources of electronics experience.

TIP: You might want to start by only soldering the six pin header on the short edge of the Pro Mini board. These pins will be enough to let you power up the board and perform the verification process below and in the next step where we observe operation of, and then modify, the "blink" sketch. Once that basic level of operation is confirmed, you can go back and very carefully install the two longer headers.

Note that the Pro Mini does not have an on-board USB port. Instead, the six pin header (on the short side) provide a serial interface and power inputs that can be connected to a USB module. The USB module then provides power and communication to the board form a USB port on a PC. We'll be using a USB to Serial module based on the PL2303 chip (datasheet).

Wiring the Pro Mini to the PL2303 is fairly simple using four female-to-female DuPont jumpers. There are two power pins (3.3V and 5V) on the PL2303. We will only be using the 5V pin, since we are working with a 5V Pro Mini. Also note that the TX on one board goes to the RX to the other and vice versa. Take a moment to consider why.

  • PL2303 <----> PRO MINI
  • 5V <----> VCC
  • GND <----> GND
  • TX <----> RX
  • RX <----> TX

Unless your PC has been used with a PL2303 USB/Serial chip before, you will most likely need to install a device driver. The best source is straight from Prolific (manufacturer of the PL2303 chip itself). Their site provides Linux, OSX, and Windows drivers.

Once you have the two boards wired together and the driver installed, plug the PL2303 module into a USB connector on your PC. The power LED on the PL2303 should light up. Then, some pre-loaded code on the Pro Mini will start running. That code blinks an LED on the Pro Mini.

Step 7: Loading Code Onto the Arduino Pro Mini

Picture of Loading Code Onto the Arduino Pro Mini

If you haven't used an Arduino with your PC before, you will need to install the Arduino Software onto your computer. This software is often referred to as the Arduino IDE (short for integrated development environment).

Once the IDE is installed, make sure the PL2303 (wired to the Pro Mini) is plugged into your PC and launch the IDE.

Next, tell the IDE which board we are using:
tools->board: “Arduino Pro or Pro Mini”

And also which port:
tools->port: “usbserial” (or something indicating the PL2303 "port")

Finally, let's open some source code:


This is actually the code that was preloaded onto the Pro Mini and should be running right now to blink the LED. Accordingly, if we load this code as it stands nothing will happen. Instead, let's modify the code a little bit. Looking closely, you can see that the program turns the LED on, waits 1000 milliseconds (one second), turns the LED off, waits another second, and then does it all again - forever.

Modify the code: change both "delay(1000)" statements to "delay(100)"

This mod will cause the LED to blink ten times faster, right?

Let's load it to board and check.

  1. Press and Hold the reset button on the Pro Mini
  2. Click the UPLOAD button (the arrow icon) just above your modified code
  3. Watch below the code for the status info: "compiling" and then "uploading"
  4. As soon as it switches to "uploading" release the reset button on the Pro Mini
  5. The IDE should now say "Uploading Complete" and your LED should be blinking faster

If so, congratulations! You have just hacked your first code. If not, try again, sometimes the timing of the reset release is a little off. The blue transmit LED on the PL2303 module should light up steady for a second or two while the upload occurs. When you don't see this (followed by an error on the IDE), the reset release is generally to blame.

Can you change the code again to cause the LED to blink fast twice and then wait a couple of seconds before repeating? Give it a try! How about some other patterns?

As a bit of an aside, but in keeping with our time theme, here is an explanation of why you generally do not want to use the delay() function aside from really simple situations like what we've done here.

Step 8: Keeping Time With Software

Picture of Keeping Time With Software

So we've seen the delay() function, but how does the Pro Mini know what a millisecond is when we tell it to delay a given number of milliseconds. Well... It has a crystal oscillator of course. The tiny, surface-mount, 16MHz crystal oscillator is connected between the PB6/XTAL1 pin and the PB7/XTAL2 pin of the ATmega328 chip as highlighted here. Note that "xtal" is a common abbreviation for the word crystal.

The Arduino Time Library can use the internal clocking (from the crystal oscillator) to provide timekeeping functionality. The library allows a sketch to get the time and date as: second, minute, hour, day, month and year.

Start by downloading and installing the Time Library itself. Here is a well maintained version to grab from github. You might want to consult this guide to installing libraries.

The Time Library includes an example sketch called TimeSerial. Open this code up. Also, open the serial monitor and set its baud rate to 9600. Finally, program TimeSerial to the Pro Mini and let it rip. You can set the time in the serial monitor by typing the letter T followed by ten digits. These digits are the number of seconds since January 1, 1970. For example, you can set the time to noon on January 1, 2013 by entering "T1357041600"

The number of seconds since January 1, 1970 is known as Unix Time or Epoch Time. Here is a website for converting human readable date/time into epoch time. You can use this with the serial monitor "T" command to set the time to the actual time if you like.

This approach may seem to work great, but there is one big shortcoming to keeping time with software. The timekeeping stops when the software stops. For example, when we turn the power off. When we power back up, we will have to set the time again. In practice, this isn't very useful.

Step 9: Interfacing to Real-Time Clock (RTC) Hardware

Picture of Interfacing to Real-Time Clock (RTC) Hardware

A real-time clock (RTC) is a computer clock, generally in the form of an integrated circuit, operable to keep track of the current time. RTCs usually have an alternate source of power, so that they can continue to keep time while the primary source of power is off or unavailable. This alternate source of power may be a coin/button cell or a supercapacitor. The alternate power source can also supply power to battery backed RAM. In older personal computer systems, this battery backed RAM was often used to store BIOS configuration settings. When the battery failed, the user would generally have to boot the computer into the BIOS to reset the date/time and possibly settings such as the hard disk parameters or boot order.

A common example RTC integrated circuit is the DS1302 (datasheet). It's a trickle-charge timekeeping chip containing a real-time clock/calendar and 31 bytes of static RAM. It uses very little power and can be maintained by a small coin cell. The DS1302 can communicate with a microprocessor via a simple serial interface.

The DS1302 module has five pins. Power, Ground, Clock, Data, and Reset. The Reset pin is also sometimes referred to as CE (chip enable). As shown here, the five pins can just be wired straight through to pins 5-9 of the Pro Mini. Hold on? Why would we tie the VCC (power) and Ground pins onto I/O pins? Good catch. That is generally a bad idea since I/O pins cannot source/sink very much current. In this instance, we can allow it since the DS1302 uses very little power. We just have to be sure to configure those I/O pins as outputs and then drive the one associated with the RTC's VCC to high (5V) and the one assoicated with the RTC's GND to low (0V). There are proper VCC and GND pins available on the Pro Mini, but we're going to use them for something else in the next step.

Download and install the DS1302 Library.

The example code for this library also uses the streaming library, so install that as well.

Bring up the example called SetSerial that comes with the DS1302RTC library. Before compiling it, we need to set the five pin numbers in the code to what we have them wired up to. In our example, we have the I/Os wired to the RTC modules like so for pins 5-9:

// Set pins: CE, IO, CLK
DS1302RTC RTC(9, 8, 7);

// Optional connection for RTC module
#define DS1302_GND_PIN 6
#define DS1302_VCC_PIN 5

Those 5 pins numbers are the only things that need to be changed in the example code.

Before loading this code, open up the serial monitor and set the baud rate to 115,200.

Load the code (remember the reset button) and let the code run.

The RTC can be set from the serial monitor by entering the time in this format: year, month, day, hour, minute, second. For example:

"2016,6,15,8,30,0" for June 15, 2016 at 8:30.

You can use this interface to easily set the RTC time to your actual current time.

The example program will then also read the time from the RTC and show it on the serial monitor.

You can cut the power (unplug the USB port) and then notice that when you boot the Pro Mini back up (you may need to restart serial monitor) it is reading the correct time from the RTC. Success!

Step 10: Seven Segment LED Clock Display

Picture of Seven Segment LED Clock Display

A seven-segment display is an electronic display device for presenting decimal numerals. Seven-segment displays are widely used in digital clocks, electronic meters, basic calculators, and other electronic devices that display numerical information.

The TM1637 is a chip for driving seven-segment displays. There are several modules using this chip to form a four digit numerical display module.

We can install a TM1637 Library into the Arduino IDE.

Next, wire the four pins from the modules to the Pro Mini as shown in the photo:

  • TM1637 <----> Arduino Pro Mini
  • CLK <----> 3
  • DIO <----> 2
  • VCC <----> VCC
  • GND <----> GND

There is a cool example that comes with the TM1637 library called "Basic" it displays some messages and numbers onto the LED segments.

When you load up the "Basic" example, just change these two lines to match the correct pins:

const byte PIN_CLK = 3; // define CLK pin
const byte PIN_DIO = 2; // define DIO pin

Then upload and give it a go.

Once the TM1637 display is working, let's use it to display the time from the RTC. The program called RTCtoLCD shown here is a nice simple example. You've just made a basic digital clock!

Step 11: 8x8 LED Matrix for Binary Clock or Seconds Counter

Picture of 8x8 LED Matrix for Binary Clock or Seconds Counter

The 8x8 LED Matrix Module is a small PCB supporting an 8x8 LED matrix wired to a serial interface MAX7219 LED driver chip (datasheet). The module has pins on each side so that multiple modules can be easily wired in a chain. This might be useful for passing through the 5V and ground signals to another module given the limited number of power pins on Pro Mini.

The 8x8 LED Matrix Module can be used to display the time in binary instead of using the seven-segment display. Take a look at these examples for some inspiration:

Amazing Binary Clock in a LED Matrix

Arduino Binary clock using LED Matrix

Also, you could use the 8x8 LED Matrix Module along with the seven-segment display to display a seconds counter. Since there are 64 LEDs in the matrix, we can fill in one per second until the matrix is nearly full and then begin again for the next minute. Can you write code to make the matrix fill in interesting patterns? Random, Raindrops, Middle-Out, Sand in an Hourglass, Spiral, etc?

Step 12: SatNav - It’s About Time

Picture of SatNav - It’s About Time

Satellite navigation (SatNav) uses a system of satellites to determine positioning information. A SatNav system with global coverage is referred to as a global navigation satellite system (GNSS). The United States operates the NAVSTAR Global Positioning System (GPS) and Russia operates GLONASS. China is in the process of expanding its regional BeiDou Navigation Satellite System into the Compass GNSS. The European Union operates the Galileo GNSS scheduled to be fully operational by 2020.

SatNav systems allow small electronic receivers to determine their location (longitude, latitude, and altitude/elevation) to high precision (within a few meters) using time signals transmitted along a line of sight by radio from satellites. The signals also allow the electronic receiver to calculate the current local time to high precision.

GPS satellites continuously transmit their current time and position. A GPS receiver monitors multiple satellites and solves equations to determine the precise position of the receiver and its deviation from true time. At a minimum, four satellites must be in view of the receiver for it to compute four unknown quantities (three position coordinates and clock deviation from satellite time).

FYI, you can download a print resolution version of the GPS poster shown here or even request a printed copy for a classroom.

Step 13: Receiving GPS Time

Picture of Receiving GPS Time

The GY-NEO6MV2 GPS receiver has a ublox NEO-6M module on board.

We need to solder to the interface pads on the receiver. Use some header pins, or just solder stripped DuPont wires directly if you don't have any header pins. Now, wire the GPS receiver to the Arduino Pro Mini using three connections.

  • GPS Module <----> Arduino Pro Mini
  • TX <----> PIN 2
  • VCC <----> VCC
  • GND <----> GND
  • RX <----> DO NOT CONNECT

Download the TinyGPS Library for the Arduino IDE.

Load up the "TimeGPS" example from the Arduino Time Library.

Change the SoftwareSerial Pins to 2 and 3 like so:

SoftwareSerial SerialGPS = SoftwareSerial(2, 3); //RX on 2

Also, bump up the GPS serial rate from 4800 baud to 9600 like so:


Open the serial monitor. Set it to 9600 baud. Upload the code (remember the reset button).

The first time you operate the GPS receiver, it will take a few minutes to detect and synchronize with enough birds. Once it does, the green LED on the receiver will start blinking. After that, you will see GPS time stamps streaming in on the serial monitor.

Step 14: Operating Voltage and the Ublox NEO-6M

Picture of Operating Voltage and the Ublox NEO-6M

The ublox NEO-6M is a 3.3V device, but the Pro Mini is 5V.

As you can see from the GPS receiver schematic, there is an on-board 3.3V regulator, so VCC into the module can be either 3.3V or 5V and the regulator will fix it.

The TX signal from the GPS receiver is only 3.3V, but that is still enough to trigger an input on the Pro Mini.

However, the TX signal from the Pro Mini will be 5V and the RX pin into the GPS receiver expects to see a signal that is 3.3V max. That is why we did not connect that signal in the previous step. It also wasn't needed, so that was totally fine. However, if you do want to hook up the serial signal transmitting from the microcontroller and receiving into the GPS receiver, please take caution. In practice, leaving the signal at 5V seems to work just fine, and you would probably be safe just hooking the line up and not worrying about it. That said, best practices would dictate using a voltage divider as a level shifter on the TX line coming out of the Pro Mini before inputting into the RX line of the GPS receiver. The example voltage divider shows how it works.

The actual resistor values do not matter, only their relative values. The smaller (top) resistor should be 2K-20K with the larger (bottom) resistor being very close to twice that value.

Step 15: Receiving GPS Signals on a Computer

Picture of Receiving GPS Signals on a Computer

Wire the three GPS receiver pins (VCC, GND, TX) directly to the PL2303 pins (5V, GND, RX).

Plug the PL2303 into a PC and GPS data will come streaming in at 9600 baud in NMEA format as specified by the National Marine Electronics Association (NMEA).

If you are running Windows, you can download u-center, which is an GUI interface for ublox GPS modules. It can record, visualize, and analyze GPS data.

Step 16: Network Time Protocol and the ESP8266

Picture of Network Time Protocol and the ESP8266

Network Time Protocol (NTP) is a networking protocol for clock synchronization between computer systems over packet-switched, variable-latency data networks. In operation since before 1985, NTP is one of the oldest Internet protocols in current use.

Of course, to get the time using NTP, you need to be connected to a network. What follows is an advanced exercise leveraging the the ESP-01 module. The ESP-01 is based on the ESP8266 chip, which is a low-cost Wi-Fi chip with full TCP/IP stack and microcontroller core.

The ESP-01 is a 3.3V board and will not work at all with 5V. As such, so you have to take great care if you want to use it with with the 5V Pro Mini. For example, you can pull the 3.3V supply from the PL2303 and use a voltage divider to level shift the RX input into the ESP8266 from 5V to 3.3V.

Better yet, it turns out that the ESP8266 actually has a processor core right inside it that is possible to program directly from the Arduino IDE with a little hackory:

  • Interface from to the ESP8266 using the PL2303
  • Use the 3.3V supply and a voltage divider as shown in the schematic
  • Modify and configure the Arduino IDE according to this guide

The Example program "TimeNTP_ESP8266WiFi" from the Arduino Time Library shows an example of how to pull time via NTP over an ESP8266 Wi-Fi connection.

Step 17: Radio-Controlled Clocks

Picture of Radio-Controlled Clocks

A radio-controlled clock (RCC) is a clock that is automatically synchronized by a time code transmitted by a radio transmitter connected to a time standard such as an atomic clock. Such a clock may be synchronized to the time sent by a single transmitter, such as many national or regional time transmitters. This technology may be used to automatically set clocks or for any purpose where accurate time is needed.

WWVB is a time signal radio station near Fort Collins, Colorado and is operated by the National Institute of Standards and Technology (NIST). Most radio-controlled clocks in North America use WWVB's transmissions to set the correct time. The 70 kW ERP signal transmitted from WWVB is a continuous 60 kHz carrier wave, the frequency of which is derived from a set of atomic clocks located at the transmitter site, yielding a frequency uncertainty of less than 1 part in 1012. A one-bit-per-second time code, which is based on the IRIG "H" time code format and derived from the same set of atomic clocks, is then modulated onto the carrier wave using pulse width modulation and amplitude-shift keying. What is now WWVB began as radio station KK2XEI in July 1956.

Step 18: Assemble a Digital Clock With Acrylic Housing

Picture of Assemble a Digital Clock With Acrylic Housing

This video shows a slightly different PCB, but it is generally the same kit and can be followed more or less to assemble the kit. An little instruction sheet is included with the clock kit, but it is a somewhat difficult to understand. Hopefully this is a little clearer:

Soldering Instructions:
1. Components are soldered onto the back of the board (where the resistor, capacitor, and microcontroller silkscreens are printed). Start by soldering the lowest profile components such as the crystal, resistors, and capacitors first. Next, solder the battery holder.

2. Solder the socket for the MCU chip and the socket for the RTC chip. The semicircular pin-one-indicator on the PCB silkscreen needs to line up with the one on each if the sockets. Next, solder the switches, buzzer, and power socket.

3. Using diagonal cutters, cut-off the excess wire leads from the opposite side of the PCB. Make these as short as possible since the LED display will be seated on that side of the PCB and you want to avoid shoring any lines together.

4. Solder the LED display last. It is placed on the front of the PCB opposite form the other components.

5. Insert the two integrated circuit chips being careful to note the direction of each with respect the semicircular pin-one-indicator on the sockets.

To set the time and/or the alarm, there are two buttons: SET and ADJUST. Use the SET button to select which value is being adjusted and then the ADJUST button to change the value.

A 3V backup battery can be installed to prevent having to reset the time whenever the external power is removed. The battery holder should be able to grip a CR1220 3V lithium button cell.

Step 19: Anything Worth Doing...

Picture of Anything Worth Doing...

Anything worth doing is worth overdoing!

This impressive EEVblog details how to design a digital clock from 4000 series CMOS chips. Note that the time is based on the 50Hz AC oscillations of the power mains. Would this clock work in the United States?

This amazing piece of work is fabricated from 777 transistors, 1233 resistors, 136 LEDs, and half of a kilogram of solder.

In recent news, overclockers push Intel's crazy 10-core Broadwell-E chip to 5.7GHz. Liquid nitrogen is used to keep the chip cool while it runs at almost double standard speed.

Stop the Insanity!

Step 20: Hack the Planet

Picture of Hack the Planet

We hope you appreciate this little reminder to never take time for granted. If you enjoyed this Instrucable and would like to have a box like this delivered right to your mailbox each month, join us by SUBSCRIBING HERE.

Please share your success in the comments below and/or on the HackerBoxes Facebook page. Certainly let us know if you have any questions or need some help with anything. Thank you for being part of the HackerBoxes adventure. Please keep your suggestions and feedback coming. HackerBoxes are YOUR boxes. Let's make something great!


seaprimate (author)2017-08-02

My Windows 10 refuses to recognize the USB to TTL module you gave me. My device manager shows the error flag, and when I open it, it says:
"This device cannot start. (Code 10). A device which does not exist was specified."

So I went to the prolific website and downloaded the driver manually, still no improvement. The IDE never even recognizes the port, it stays grayed out. The reset button trick doesn't work if my IDE can't recognize the device to begin with...

The Prolific website warns against counterfeit PL2303 chips, and also states the PL2303HXA chips are no longer supported since windows 7. Is it possible I have a counterfeit or outdated chip on my usb-ttl board? And anyone else have the same problem that they've solved? Thanks!

BTW, built the alarm clock form the kit and it works great!

seaprimate (author)2017-07-27

I know the instructions say use a CR1220 for the battery backup on the
diy clock kit, but I couldn't find it locally at 3am. Instead I used a CR 1216 from walmart
that does just fine.

Fun fact I just learned: The batteries are named by their dimensions, so...

CR1216 = D 12mm x H 1.6mm
CR1220 = 12x2
CR1620 = 16x2
CR2025 = 20x2.5

So usually if the voltage matches, and the diameter matches, button cell holders sometimes will take a variety of heights.

CR1612 might sometimes fit similar to a CR1616 or CR1620 as long as the spring reaches and provides enough tension

willyeverlearn (author)2017-04-21

Hello, I will start by saying this is fun.

I am stuck on step 9

Everything is physically set up as directed.

Serial port it up and scrolling by with the default date. 1970

When I try to set the time/date with the command


The reply is....
RTC set failed

When the serial console is up and I re-upload the program I get....

The DS1302 is stopped. Please set timeto initialize the time and begin running.
The DS1302 is write protected. This normal.

I know I must be missing something silly.

josh45631 (author)2016-08-10

So I'm just starting out with this box, and I'm to the part where you upload the sketch for the Real Time Clock. I've changed the values for the pins, and when trying to upload the sketch, it fails to compile with error 'setSyncProvider' was not declared in this scope and the line setSyncProvider (RTC.get); is highlighted in red. I am a novice of the first order when It comes to this stuff, and I'm trying to learn, but I can't find any info on what to do. Can anyone help?

wkari (author)josh456312016-08-13

I'm having the same issue were u able to figure this out

josh45631 (author)wkari2016-08-20

Unfortunately no. I'm still stuck.

MichaelH539 (author)josh456312016-08-28

@josh45631... Usually when I run into an error like that, it is because I deleted a "{" or "}" somewhere or forgot the semi-colon. Also, make sure you have both the Streaming and Time libraries installed before you create the program. I have to close and re-open when a new library is installed for some reason. Here is what I had for the code, and it compiled without a problem. Double check the pin definitions though, I don't have it wired up anymore, and I might have entered them wrong. Here it is. Let me know how it goes... good luck!

<---Begin Code--->

#include <DS1302RTC.h>
#include <Streaming.h> //
#include <Time.h> //

// Set pins: CE, IO,CLK
DS1302RTC RTC(9, 8, 7);

// Optional connection for RTC module
#define DS1302_GND_PIN 6
#define DS1302_VCC_PIN 5

void setup(void)

// Activate RTC module
digitalWrite(DS1302_GND_PIN, LOW);
pinMode(DS1302_GND_PIN, OUTPUT);

digitalWrite(DS1302_VCC_PIN, HIGH);
pinMode(DS1302_VCC_PIN, OUTPUT);

Serial << F("RTC module activated");
Serial << endl;

if (RTC.haltRTC()) {
Serial << F("The DS1302 is stopped. Please set time");
Serial << F("to initialize the time and begin running.");
Serial << endl;
if (!RTC.writeEN()) {
Serial << F("The DS1302 is write protected. This normal.");
Serial << endl;


//setSyncProvider() causes the Time library to synchronize with the
//external RTC by calling RTC.get() every five minutes by default.

Serial << F("RTC Sync");
if (timeStatus() == timeSet)
Serial << F(" Ok!");
Serial << F(" FAIL!");
Serial << endl;

void loop(void)
static time_t tLast;
time_t t;
tmElements_t tm;

//check for input to set the RTC, minimum length is 12, i.e. yy,m,d,h,m,s
if (Serial.available() >= 12) {
//note that the tmElements_t Year member is an offset from 1970,
//but the RTC wants the last two digits of the calendar year.
//use the convenience macros from Time.h to do the conversions.
int y = Serial.parseInt();
if (y >= 100 && y < 1000)
Serial << F("Error: Year must be two digits or four digits!") << endl;
else {
if (y >= 1000)
tm.Year = CalendarYrToTm(y);
else //(y < 100)
tm.Year = y2kYearToTm(y);
tm.Month = Serial.parseInt();
tm.Day = Serial.parseInt();
tm.Hour = Serial.parseInt();
tm.Minute = Serial.parseInt();
tm.Second = Serial.parseInt();
t = makeTime(tm);
//use the time_t value to ensure correct weekday is set
if(RTC.set(t) == 0) { // Success
Serial << F("RTC set to: ");
Serial << endl;
Serial << F("RTC set failed!") << endl;
//dump any extraneous input
while (Serial.available() > 0);

t = now();
if (t != tLast) {
tLast = t;
Serial << endl;

//print date and time to Serial
void printDateTime(time_t t)
Serial << ' ';

//print time to Serial
void printTime(time_t t)
printI00(hour(t), ':');
printI00(minute(t), ':');
printI00(second(t), ' ');

//print date to Serial
void printDate(time_t t)
printI00(day(t), 0);
Serial << monthShortStr(month(t)) << _DEC(year(t));

//Print an integer in "00" format (with leading zero),
//followed by a delimiter character to Serial.
//Input value assumed to be between 0 and 99.
void printI00(int val, char delim)
if (val < 10) Serial << '0';
Serial << _DEC(val);
if (delim > 0) Serial << delim;

josh45631 (author)MichaelH5392016-08-28

I compared my sketch with yours, and it's identical. I even copy/pasted yours into a blank sketch and still got the same error when I tried to compile it. I'm going to uninstall the Arduino IDE and all the libraries, and just start from scratch. I really appreciate you taking the time to respond. I must have made some small mistake along the way somewhere! ARGH!! Deep breath....It's just part of the learning process..... It's just part of the learning process........ It's just part of the learning process............... and as I'm typing this I see someone else has a possible solution. Fingers crossed!!!! Thanks again!

rmartinezv (author)josh456312017-03-04

Did you find a solution for the

setSyncProvider' was not declared in this scope problem?


Jeremy67 (author)josh456312016-08-28

Download TimeAlarms.h and import it

I used this one:

rmartinezv (author)2017-03-04

I really like these boxes, the aren't cheap, but are really nice, but the thing with the PL-2303 that doesn't works with Windows 8/10 is dump.All the box projects are in pause because of this, so now I have to fin another usb to ttl adapter.

rmartinezv (author)rmartinezv2017-03-04

Ok, use this driver and make sure to press and hold the button until starts the uploading to the pro mini.

grtyvr (author)2016-09-27

Awesome collection of gear for hacking. Here is what I used the GPS in.

Gave you folks props in the video. Hope that is ok.

ForgottenMuppet made it! (author)2016-07-17

I made it but can't get the time to increment

Here's what I've deduced from lots and lots of button pressing with my clock after I got it all put together. These instructions assume you have just connected the clock to a power source. If you have a battery in yours, take it out and unplug it for a few minutes so it will reset.

Pressing the top button once puts the clock into Time Set Mode, starting with the hour.

With the hour digit(s) flashing, use the bottom button to advance the hour. When the correct hour is displayed, press the top button again to switch to set the minutes, which should now be flashing. Then use the bottom button to advance the minutes.

When you have the correct time set, another press of the top button switches to the alarm setting mode. Setting the alarm is identical to setting the time. When the desired alarm time is set, and the minutes are still flashing, one more press of the top button puts the clock into "Alarm On/Off Mode". None of the digits are flashing, and a press of the bottom button will turn on/off an LED in the bottom right corner of the clock. If the LED is on, the alarm is on. If the LED is off, the alarm is off.

One more press of the top button advances into some other mode that is identical to the alarm setting mode, with the exception of the minutes will only advance to 23. I'm not yet sure what this mode is. When you've advanced to where you can turn this mystery alarm on or off, press the top button one more time, and the current time should be displayed. The colon between the hour and minutes should be flashing, ticking off the seconds, and the temperature should display every 30 seconds(ish).

Your results may vary. I can only say for sure that this is how my clock works. Reading through the comments, it seems like these clocks are a bit wonky. For instance the dimming function doesn't work at all on mine, and the temperature is about 7 degrees low at all times.

These are kind of long, drawn out instructions, but I hope they help!

Thank you. I had figured most of that out as well. Mine just refuses to actually track time

Hypathie (author)ForgottenMuppet2016-08-15

I have the same problem...

Jeremy67 (author)2016-08-28

When I first ran the BASIC and RTCtoLCD programs, they functioned perfectly. However, the wires linking my 7-segment 4-digit display VCC to the Arduino Pro mini was kind of loose (the connector just doesn't seem to be snug). Nudging it would shut off the display. When I tried restarting it a few times, the display became more and more likely not to turn on at all.

Now I check my serial monitor and have added a print line to show that the program runs. The program runs fine and reports serial monitor when my VCC is not connected. The VCC pin on the Arduino Pro Mini has 5V over ground. But as soon as I connect VCC to pin, the serial output stops and a red indicator light on the Arduino blinks. The display no longer turns on at all.

Reverting to the BASIC example for the display also fails. I'm thinking the display somehow burnt out or draws too much current from the Arduino. Has anyone else had this problem?

Note, I only have the clock unit and display attached to the Arduino

Mudkillz (author)2016-07-30

When I attempt to load code to the board, it gives me the error message "avrdude: ser_open(): can't open device \\.\COM3: The system cannot find the file specified." When I click on the Tools tab, I'm not allowed to select a port. Does anybody know how to fix this?

Jeremy67 (author)Mudkillz2016-08-28

I get that problem on Windows7 and Windows10

You basically have to download an old version of the driver, then go into Device Manager and tell the Com port to use that driver, then it worked for me

peterlefferson (author)Mudkillz2016-08-06

I have spent hours trying to make the PL2303 driver work. Has anyone else have this problem and is there a solution?

PhilM28 (author)peterlefferson2016-08-09

I have a collection of EBay USB to Serial adapters to test on various platforms. Atypically, I do not have a Windows machine on which to try these. I have never gotten the PL2303 boards to work on Linux or OS X. My solution is to use a CH340-based six-pin USB to Serial adapter (which has a DTR pin). This allows the IDE to reset the board and avoid the "hold down the reset button" issue, as well. Here's an example of the board I use: but of course feel free to shop around (I'm not affiliated with any seller other than Adafruit, so I'm just trying to help out).

peterlefferson (author)PhilM282016-08-10

Thank you very much. Now I can get on with this box.

josh45631 (author)peterlefferson2016-08-07

Same problem here. After some research, the best answer I can come up with is that the PL2303 is a clone that will not work on Windows 8/10. I found a YouTube video where a fella was testing 3 different USB/serial chips, and he had the same problem with the PL2303 he was testing. He did get it to work on a Windows XP machine though. Unfortunately I haven't had a Windows XP machine in about 12 years. It seems like the solution is hit up some yard sales and try to find an old computer running XP, or buy a new USB/serial chip. Unless someone else can figure out how to get these PL2303's working on Windows 10.

Mudkillz (author)Mudkillz2016-07-30

I just looked up the serial-to usb driver, its the PL-2303HX chip. When downloaded the driver installer, it came with a program to check the chip. When I checked the version of said chip, it said it didn't exist! All my other COM ports had errors opening them, so it was the right port.

Hypathie (author)2016-08-15

My clock doesn't work. I set the time, but it doesn't change. Please help. Thank you in advance.

wkari (author)2016-08-15

can someone post there working code for setSerial please and thank you

MichaelH539 (author)2016-08-14

I was able to Frankenstein a GPS Clock display using the "Receiving GPS
Time" step and a portion of the "RTC to LCD" program with a few minor
tweaks. I wasn't, however, able to use the time offset in the TimeGPS
program to output the current local time to the LCD. I had to manually add the offset into the "display.printTime" line. Code has been pasted below. Is there any way to make this code less clunky, and use the offset time from the TimeGPS program? It seems like a lot of the code was already there to print to an LCD, but couldn't get it to work with the seven segment LCD display chip that came with the box.

// Begin TimeGPS_Display program code. Note CLK and DIO pins from TM1637 are connected to Arduino pins 4 and 3 respectively.

#include <TimeLib.h>
#include <TinyGPS.h> //
#include <SoftwareSerial.h>
#include <SevenSegmentTM1637.h>
#include <SevenSegmentExtended.h>

// TinyGPS and SoftwareSerial libraries are the work of Mikal Hart

SoftwareSerial SerialGPS = SoftwareSerial(2,3); // receive on pin 10
TinyGPS gps;

// Offset hours from gps time (UTC)
const int offset = 3; // Local Time

// LCD pins: (clock, data)
const byte PIN_CLK = 4;
const byte PIN_DIO = 3;
SevenSegmentExtended display(PIN_CLK, PIN_DIO);

time_t prevDisplay = 0; // when the digital clock was displayed

void setup()
while (!Serial) ; // Needed for Leonardo only
Serial.println("Waiting for GPS time ... ");

void loop()
while (SerialGPS.available()) {
if (gps.encode( { // process gps messages
// when TinyGPS reports new data...
unsigned long age;
int Year;
byte Month, Day, Hour, Minute, Second;
gps.crack_datetime(&Year, &Month, &Day, &Hour, &Minute, &Second, NULL, &age);
if (age < 500) {
// set the Time to the latest GPS reading
setTime(Hour, Minute, Second, Day, Month, Year);
adjustTime(offset * SECS_PER_HOUR);
// show the current UTC time on the display plus offset for local time
display.printTime(Hour +3, Minute, true);
if (timeStatus()!= timeNotSet) {
if (now() != prevDisplay) { //update the display only if the time has changed
prevDisplay = now();

void digitalClockDisplay(){
// digital clock display of the time
Serial.print(" ");
Serial.print(" ");
Serial.print(" ");

void printDigits(int digits) {
// utility function for digital clock display: prints preceding colon and leading 0
if(digits < 10)

// End TimeGPS_Display program code

peterlefferson (author)2016-08-11

Library programs with line numbers will not run until the line numbers are removed one by one. Is there an easy way around this? Thanks

Everett (author)2016-08-05

So, are the LDR (light sensor) and Temp sensor correctly designated?

ForgottenMuppet (author)2016-07-18

Can anyone think of why I get everything to work excetp the numbers actually incrementing?

ruthsarian (author)2016-07-06

About the 4-digit clock...

Has anyone tried programming the STC15F204EA that drives the digital clock? I took a stab at it using the USB-to-serial module we got in the box, the 4-pin header (above the switches) on the PCB and sctgal, but I couldn't get sctgal to dump information about the chip. It seems the TxD and RxD pins on the chip used for ISP are also used to drive the display; I wonder if that's creating a problem.

I found this project on GitHub
to update the firmware on a similar (but not the same) clock kit. The
MCU is the same, but the pins on that project are different from ours.
It seems like it might be a starting place to updating the firmware on
our clocks to use a 12 hour format, or Fahrenheit instead of Celsius.

Does anyone notice the display changing brightness based on the photoresistor? It doesn't seem to be doing anything for me. I checked the voltage across the photoresistor with a multimeter and the photoresistor itself is definitely working, which makes me think the firmware isn't even using it.

....I should have added that there is a delay in the dimming/brightness effect of about 1.5 seconds.

What positions do you have your thermistor and photoresistor attached to?

The instructions have the photoresistor in R5 for and the he thermistor in R4, but the schematic has it the other way around. I suspect my problem is I need to swap the two, but I'd like some confirmation before I start trying to desolder the display so I can get at the pads for R4 and R5.

eburman (author)ruthsarian2016-07-13

I just finished assembling the clock. Its very sweet, but I'm also suspicious of the placement of the LDR and thermistor. The LDR does nothing and the thermistor consistently reads 10 degrees higher then ambient room temperature. Makes me wonder.

My LDR is at R5, the thermistor is at R4.

I noticed that once I enclose the clock in the plastic housing, the dimming effect stops working. I have to completely cover the LDR to get it to work. I think the light from the display is too bright, so the dimmer never triggers.

On a related note, if you look at the documentation included with the kit (displayed above in HB instructions), am I crazy or do they have R5 labeled as the LDR ("light sensor") in the notes, and on the schematics R5 is shown as the thermistor ? (I skimmed your original post on my phone and didn't catch the fact you already noticed this - sorry'bout that ).

I ended up removing the 10K resistor at R2 and replaced it with a 2.2K resistor for better dimmer sensitivity.

You could go lower towards 1K for more sensitivity or higher towards 10K for less.

My desoldering skills are crap. I pulled the display and swapped the two and the temperature went from 28C to 50C, so the instructions, not the schematics, are definitely correct. I think changing the resistor to a lower value is a good idea. Unfortunately, my second desoldering of the display may have killed it. The MCU is good, but only a few segments are lighting up now. I think I lifted some pads and/or vias from the PCB. I'll grab another kit similar to this one off ebay so I can keep playing around. I might try running wires from the socket to the display pins later on if I feel up to it and see if I can salvage it at all. Just not up to it right now.

In the meantime, I put the MCU by itself on a breadboard and played around with reprogramming it. For one brief moment, the STC programming tool recognized the MCU and spit out some information about the chip, but I haven't been able to repeat that feat since. However it looks like pins 17 and 18 on the MCU have to be grounded to reprogram the chip; I don't think it can be done with just the 4-pin header on the PCB. And to trigger the MCU to check whether or not you're trying to program it requires a hard reset. That's about as far as I got tonight.

ruthsarian (author)ruthsarian2016-07-09

Fixed 4 lifted pads/vias with some jumper wire and got the clock working again.

Took another stab at hooking everything up this morning and I can get both the STC programmer and stcgal to reliably detect the MCU every time. You'll only need the 4-pin header that's on the board. P3.1 should go to the RxD pin on the USB to TTL module we got with the box. P3.0 should go to TxD. 5v and GND pins as well. To program it you need to start the program tool up and it will wait for a power cycle from the clock. A soft reset won't work, you need to remove power from the clock, then power it back up. Below is output from stcgal

C:\>stcgal -p COM6 -P stc15a
Waiting for MCU, please cycle power: done
Target model:
Name: STC15F204EA
Magic: F394
Code flash: 4.0 KB
EEPROM flash: 1.0 KB
Target frequency: 6.032 MHz
Target BSL version: 6.7R
Target options:

And this is the output from the STC programmer (stc-isp-15xx-v685O.exe)

Checking target MCU ...
MCU type: STC15F204EA
F/W version: 6.7R

Current H/W Option:
. Do not detect the level of P3.2 and P3.3 next download
. Power-on reset, use the general power-on delay
. RESET pin behaves as I/O pin
. Reset while detect a Low-Voltage
. Thresh voltage level of the built-in LVD : 3.82 V
. Inhibit EEPROM operation under Low-Voltage
. Hardware do not enable Watch-Dog-Timer
. Watch-Dog-Timer pre-scalar : 256
. Watch-Dog-Timer stop count in idle mode
. Program can modify the Watch-Dog-Timer scalar
. Do not erase user EEPROM area at next download

. MCU type: STC15F204EA
F/W version: 6.7R

Complete !(2016-07-09 12:09:16)

Going to see what I can do with zerog2k's stc_diyclock which is based on a similar kit, but uses a different pin configuration. I plan on using sdcc and stcgal to compile and upload the code to the MCU.

That's great - thanks for the update and the instructions! Looking forward to trying it out in the morning.

I've got the code running, but there are still some bugs that need I need to ironed out (mostly problems with button presses).

If you're playing around with the code as well, there are a couple things I wanted to quickly share that took me a while to figure out.

in ds1302.h the pins for the clock, DS_CE, DS_IO, DS_SCLK, need to be changed to P1_1, P1_2, P1_0. In ds1302.c the sendbyte() and readbyte() functions have these ports hard-coded in assembly and therefore also need to be updated. Replace _P1_2 with _P1_0 then replace _P1_1 with _P1_2.

In main.c, the port mode for the clock pins are being changed because their hardware included pull-up resistors on those pins. We don't have pull-up resistors on the pins, so we don't want to change the pin mode.

187. P1M1 |= (1<<6) | (1<<7);
188. P1M0 |= (1<<6) | (1<<7);

For a brighter display try adding

P3M0 = 0xFF;

below the above two lines.

Also in main.c, the timer0_isr() function controls updating the display. P3_0 through P3_7 pins are used for the segments, and P2_0 - P2_3 are used for the digits on our display. This function needs to be modified to reflect that.

114. P2 |= 0x0F;
119. P3 = dbuf[digit]
121. P2 &= ~(0x8 >> digit);

And be sure to change the switch pins in the code.

31. #define SW2 P2_7
33. #define SW1 P2_6

In led.h there are two arrays, ledtable[] and ledtable2[]. The second table is unique to the hardware for their project (their 3rd digit is inverted). We don't need it, so delete that table completely. Then modify updateTmpDisplay() and change the reference to ledtable2 in line 86 to just ledtable.

You may also need to invert the entries in ledtable[]; basically replace the value with the "was" value you see in the comment next to it.

I use sdcc and stcgal to compile and flash the code. I use the project's makefile to automate the process. I had to edit Makefile and change SDCC (remove the path, set it to sdcc), STCGALPORT (for me it's COM6, but set it to whatever COM port your USB to TTL dongle is on), and I had to change STCGAL to just "stcgal" without the path or .py. Then run make, and make flash. When you run make flash, stcgal will wait while you cycle the power on the clock, then it'll start flashing.

The dot for the third digit will blink with the colon. That's because this code uses their inverted third digit's dot to be the top of the colon, whereas we have the luxury of having a separate colon. I haven't fixed this yet, but fixing it should be a simple matter of looking for calls to dotdisplay() and filldisplay() where the first argument of either is a value of 2, the third argument should be changed to a 0.

The major problem I'm having is a single button press is registering multiple actions instead of 1 action per press. The colon also blinks fast for me. I think both problems are related to how the timing is handled. I could try increasing the values passed to _delay_ms() in the main loop, but I think I'm going to try to rework how button presses are handled and maybe stick the colon flash into the button press (debounce) timer.

Wow thanks ruthsarian! Your button issue does sound like a debounce problem. Might be able to address with a capacitor instead of the software?

I haven't been able to mess with it too much for the past couple days due to other more pressing and less fun issues (yardwork), but I hope to jump back on it mid-week. Thanks for the update - it's a huge help, and please keep the updates coming if it's not too much trouble. Nice work!

I've found that in the gettemp function in main.c, I need to cast the variable raw to float on the return otherwise odd things happen.

return 76 - (float)raw * 64 / 637;

I'd love to know where that formula for taking the ADC value of the thermistor came from. It's pretty effective and saves a lot of math overhead,

The button issue was my own doing. The code refers to a RELAY pin is an extra LED on their hardware that we don't have. I commented out the 3 lines of code that turn it on, wait, then turn it off. Turns out the wait part is important to the main loop's timing. Once I uncommented that line, it works much better.

In led.h, if you change all the values in ledtable[] back to what they were, you also need to modify the updateTmpDisplay() function and replace "tmp&=0x7F" with "tmp|=0x80" on all 4 lines, otherwise the colon/periods won't work.

ruthsarian -

My display definitely dims in darkness, gets brighter in light. It's a very noticeable change when it happens.

Hope you get it working. I'd be interested to hear if you make any progress on programming the controller.

Thanks for the confirmation. I must have something wired wrong or maybe a short somewhere. I'll poke around and see if I can find anything.

If I get anywhere with reprogramming it, I'll definitely share here.

ruthsarian (author)2016-07-11

I've created a fork of of Jens Jensen's stc_diyclock project on GitHub and modified the code to work with the digital clock kit that came with this HackerBox. You can grab the code from GitHub at It's a starting point for those who want to mod their clock.

GrantB29 made it! (author)2016-07-08

I hated the chenglish "manual install" but this little clock looks great on the desk next to my computer and even matches the blue power light on my PC case. The dimmer function, well, doesn't. I tried covering it completely and get get no results, and I screwed the pooch and soldered the thermistor too close to the board and cut the ends before I realized it needed to fit though the hole in the top of the case. Oh well, I'm an American, I don't understand that Celsius stuff anyway. I do like the 24hr clock, I'm retired Army and I like my clocks on 24hr time, it's easier for me.

Thank you to slackmasterstan for the user instructions written in understandable English, the hourly chime was driving my wife nuts, and I admit it was kind of weird.

jasper_fracture (author)GrantB292016-07-08

Grant -

I ended up removing the 10K resistor at R2 and replaced it with a 2.2K resistor for better dimmer sensitivity.

You could go lower towards 1K for more sensitivity or higher towards 10K for less.

It's always 5 PM somewhere....apparently at your house. :)

ruthsarian made it! (author)jasper_fracture2016-07-09

I soldered a 1k resistor in parallel with the 10k resistor on the light sensor (rather than having to desolder the display to get at the back of the board to desolder the 10k resistor) and that gave it the sensitivity I preferred. You could do the same with a 2.2k resistor for a little less sensitivity. I opted for the lower value because the display is especially bright so I wanted it on its dim setting even when it's somewhat light out.

GrantB29 (author)ruthsarian2016-07-09

I like that, I think that's what I'll do so I don't have to try to desolder anything that way

About This Instructable




More by HackerBoxes:HackerBox 0024: Vision QuestHackerBox 0023: Digital AirwavesHackerBox 0022: BBC Micro:Bit
Add instructable to: