The ability to understand and control LED matrices is an important skill for anyone who hopes to be well versed in electronics. The understanding of shift registers and row scanning techniques necessary for such feats will prove useful in countless other fields, and will allow you to do many other things past simple LED matrix manipulation. In need of such skills, I turned to internet searches to find a tutorial on how to do such things. While I found plenty of resources, I found that simply building a basic 8x8 led matrix and displaying some simple animations across it was somewhat useless; what would I ever use this for? I wanted to use my knowledge to build something useful, and so I immediately though of building a clock using an LED display and a real-time-clock (RTC). Then, wanting to distinguish my project from the thousands of other DIY clocks on the internet, I decided to add a sunrise alarm to it. For those of you who may be unaware, a sunrise alarm clock uses a light that gradually gets brighter to wake you up, emulating the sunrise in a way much more natural than a piercing alarm. At the time you set the alarm for, an LED array will gradually get brighter over the course of 15 minutes, and provided it is angled properly, you should be wide awake by the time it reaches its full brightness.
I find sunrise alarm clocks to be much more pleasant than traditional alarms, and hopefully this clock will make a fine addition to your bedside table decor while still teaching you a lot about LED matrices and shift registers.
Step 1: Theory
For a more in-depth explanation of how LED matrices work, visit this page. As you can see in the circuit diagram above, an LED matrix consists of a number of LEDs wired together in a grid-like fashion. Obviously, their final arrangement does not have to be in a grid shape, however their wiring does. Essentially all the LEDs in each row have their anodes connected to each other, and all the LEDs in each column has their cathodes wired together. In order to turn any one LED on, you must connect the its anode (via its common row connection) to V+ and connect its cathode (via its common column connection) to GND. In this way, each LED can be individually addressed. This causes a problem almost immediately, however. What if you wanted to turn two LEDs on at the same, one in the first column one down from the top and another one in the third column two down from the top? Well, you would connect the second and third rows to V+, and the first and third columns to GND. But now suddenly four LEDs are on, rather than the two you originally desired. To get around this problem, row or column scanning is used.
With row and column scanning, only one row orcolumn is ever connected to V+ or GND at a time (in row scanning, only one row is connected to V+, and in column scanning only one column is connected to GND). In this way, the only LEDs that will be lit are the ones in the row/column that is currently being connected to V+/GND. In order to make it look like more than one row/column is on at a time, the rows/columns are scanned; as soon as one row/column has been turned on and its corresponding LEDs have been turned on/off, it is turned off again and the same thing happens with the next row/column. This pulsing of the lights happen so fast that your eye cannot see anything turning off in what is known as persistence of vision (POV), and our brains process that multiple rows/columns are on at a time.
I decided to use row scanning for this project. I figured it would be easiest, as I am using a matrix consisting of five rows and 11 columns, and five rows are able to fit into the 8-output-maximum of the shift registers that will be used to control the matrix. The reason I am using shift is that a standard Arduino Uno does not have enough I/O for both the LED matrix and the push buttons used to control the clock. The shift registers use 6 Arduino pins rather than the 16 that would be required to directly drive each column and row. Three shift registers are used: one for the row scanning and another 2 for the column sinking. Because the row scanning is essentially running independently from everything else, it must be controlled separately from the column registers. The column registers can actually be daisy chained together using the serial output of one of the shift registers, which allows us to reduce the number of Arduino pins. This project uses the 74HC595 shift register.
For a guide on what shift registers are and how to use them with an Arduino, click here.
The sunrise alarm circuitry is fairly simple, and only consists of a basic RC circuit that gradually increases the current on the gate of an IRF510 MOSFET, which in turn allows more and more current to flow through an LED array, through its drain-source path, and into GND. The more current flowing through the array, the brighter its LEDs are, and the closer you get to waking up in the morning.
Step 2: Materials
- 1 x Arduino Uno or similar
- 1 x Ds1307 real time clock
- 1 x 2 amp capable 12 volt to 5 volt DC to DC regulator (such as this one)
- 3 x 74HC595 shift register
- 5 x power PNP transistor (link). They must be able to source at least 220 mA, which is more than a standard 2n3906 or equivalent can handle
- 12 x 2n3904 or equivalent NPN transistor
- 2 x green ultra bright LED (link)
- 44 x blue ultra bright LED (link)
- 72 x white ultra bright LED (link)
- 1 x 1000uf capacitor
- 1 x IRF510 MOSFET
- 1 x 180K resistor
- 4 x 10K resistor
- 17 x 1K resistor
- 11 x 56-68R resistor (68R is the "proper" value, however 56R is what I had on hand)
- 72 x 75-90R resistor (90R is the "proper" value, however 75R is what I had on hand)
- 1 x 100R potentiometer
- 1 x SPST switch
- 3 x SPST momentary button
- 3 x 16-pin I socket (optional, but highly recommend)
- Female and male headers(optional, however the modularity they provide makes assembly and debugging much easier)
- Assorted lengths and colors of wire
- Heat shrink tubing (electrical tape would also work, but heat shrink tubing makes everything look a lot neater)
- 2 x 1'x2'x1/8" plywood (this is the maximum size of the laser cutter I used and the CAD files are optimized for such, however you could of course use any sizes that fit your needs)
- 1/8" Plexiglas
2 x M3 screw with matching nut
Make sure to have a laser cutter and other assorted tools necessary for this build on hand (I will not go into specifics, as tool palettes vary widely and many of my techniques and tools can easily be substituted)
Step 3: Laser Cutting
Using the attached files, laser cut the parts out of 1/8" plywood. As mentioned earlier, the files included are optimized for two 1'x2' pieces of wood (you will see a 1'x2' outline in each file), however you can edit the designs to suit your needs. Make sure to cut out the Plexiglas, as well. This piece is used to diffuse the lights of the LEDs.
Although the attached Plexiglas file engraves the entire face of the Plexiglas, thus frosting it, if you do not appreciate the smells and fumes this creates you can always frost the Plexiglas by hand using sand paper. Make sure to check if it is opaque enough when you're done.
Step 4: Initial Assembly
Then assemble the front facade of the clock. Use the photos as a reference to super glue each layer together Iin the proper order, excluding the Plexiglas and front grid for now (these will be glued on later in the assembly process). Partially assembling some of the side pieces may help with alignment, as shown in the photos.
Step 5: Assemble the LED Matrix
Begin by placing the blue (or whatever color you like) LEDs into the face plate holes in such a way that you can easily solder the negative leads in each column and the positive leads in each row to each other. You'll notice that I decided to make the colon LEDs green; again, this color choice is entirely up to you. Before soldering, test each LED with a button cell battery, to make sure that you didn't receive any defective LEDs. Then bend and solder the positive leads of each LED, followed by the negative leads, making sure that there is a slight gap between the positive and leads of each LED to prevent shorting. Finally, test that everything has been wired properly using a power supply of your choice.
Step 6: LED Matrix Connection Wires
Once you have determined that the matrix is wired properly, you will need to interface it with the rest of your circuitry. This is done by connecting stranded wire to each column and row. I arbitrarily chose the lengths for my wires, only making sure that they were long enough for my testing purposes. I built this before fully knowing how it was going to work, and so did not know how long they had to be. I would recommend that you measure out each wire to fit the enclosure, as I did not do this and the lengths I chose ended up being quite a bit longer than what was really needed. I chose solder headers to each wire, a step that aided me in my testing and added some additional modularity, however you could easily solder these wires directly to the circuit board constructed later on.
Step 7: Assemble the Sunrise LED Array
As you saw in the schematic, each of the "alarm" LEDs simply has its anode connected to V+ and its cathode connected to the MOSFET with a 75R resistor. In order to wire up the LEDs in this way, begin by inserting the white (or whatever color you like) LEDs into the holes cut into the frame. Orient them so that the positive leads are facing outward and the negative leads are facing inward - this will make soldering a lot easier. Before soldering, make sure to again test each LED to guard against the use of any defective LEDs. Then, bend the positive leads of the LEDs in such a way that they can all be easily soldered together, as shown in the photos. Finally, solder all the positive leads together, creating a positive "rail," and test for proper connectivity.
Step 8: Add Resistors to the Sunrise LEDs
Begin by twisting a resistor around each negative lead. Do not to tighten it too much, so that you can still slide it down to the base of the lead and solder it. Once each LED has resistor soldered to it, connect the other end of all the resistors to each other, essentially creating a negative "rail" that will later be connected to the brightness control circuitry. After testing that everything has been connected properly, solder another set of wires with headers to the positive and negative rails.
Make sure to clip any excess leads between each step!
Step 9: Prepare the Voltage Regulator and RTC
Solder some headers to the Voltage Regulator and RTC (not pictured), as doing so will make soldering them to the final PCB much easier.
Step 10: Wire the Circuit
To view the schematic, either use the attached PDF file, the attached image, or click here.
Because going over how to build a circuit on a PCB could require an entire tutorial in and of itself, I will leave the exact details up to you. The basic theory of this process, however, is to use the schematic to lay out all of the components in a logical fashion on your PCB (in this case I had to use two due to space restraints) and then use old lead clippings and short lengths of wires to make all of the necessary connections. I recommend making all the component connections first, and then cutting lengths of wires to make any external connections (buttons, Arduino pins, etc.). Doing this may require some partial assembly of the frame, so that you can more accurately measure out the necessary lengths. I would also strongly advise you to avoid the fatal mistake I made, in which I used 14-pin sockets rather than 16-pin sockets, an error that greatly threw off my layout and required me to ghetto-mod the chips into the proper place.
**Breadboard the circuit first, to make sure that all your components work properly and to allow you to make any modifications in a non-permanent fashion!
Explanation of Circuit:
As you can see from the schematic, the circuit is fairly simple, and mainly consists of a simple module repeated many times. There is one transistor per row/column, with PNP transistors used to source the row LEDs to V+ and NPN transistors used to sink the column LEDs to GND. You'll notice a 1K resistor in between each transistor base and its corresponding shift register pin; this is simply to prevent over loading the base; omit them and you may fry your transistors! There is an additional set of 56R resistors between each column and its NPN transistor, these are current limiting resistors to prevent the LEDs from burning out. Moving on to the shift registers themselves, their connections are fairly straightforward, consisting of directly connecting the clock, latch, and data pins of two of them to the Arduino pins. The third one is daisy-chained to another one of the others. This was done to leave more Arduino pins open for the rest of the circuitry, and the two work in tandem to sink each LED column to ground. The remaining connections are for things such as the output enable and clear functions of each shift register, and these were just pulled high or low depending on how they affected the output pins of the shift registers (on or off).
The next part of the circuitry is the sunrise alarm part, and as explained earlier this is mainly a simple RC circuit that begins when the NPN transistor across both leads of the capacitor is turned off, allowing it to charge. Moving on from that you'll notice the voltage regulator that is simply taking power from the barrel jack of the Arduino (via the Vin pin) and stepping it down to a usable 5 volts. Normally I would have simply used the 5v pin, however I knew the LEDs would be drawing a lot of power and did not want to risk damaging the Arduino by drawing too much power from that unregulated source. Everything is powered from this regulator, and it provides a reliable ~2A output for the entirety of the circuitry.
The button/switch circuitry is quite simple, and is essentially a series of 10K pull down resistors attached to each input pin. Pushing each switch will cause the input pins to be connected to 5 volts, which the Arduino registers as a high input. The display-dimming circuitry is simply a 100R potentiometer connected between the emitters of all the column NPN transistors and ground. Varying the amount of resistance on this part will adjust the amount of current flowing through the display LED, making them brighter or dimmer. I understand that this is a very improper way of doing this, and that I should have used a PWM circuit along with a MOSFET, however time was running low and I did not want to fuss with such things.
Step 11: Upload and Test Code
This is a simple matter of downloading the attached library and then uploading the attached sketch the Arduino or equivalent micro-controller. Here you may wish to modify the code to your liking, adapting it to your specific interpretation of this project. I have commented the code fairly thoroughly, so you should be able to understand what is going on from that, however here is a basic overview of how to use the clock:
The actual time keeping part of the clock is done by the RTC, and so all you need to do is set the time once using the example sketch in the attached library. Once the time of the RTC has been set, all you need to do is upload my sketch and you should be good to go. The clock's default state should be displaying the time, with the display's brightness adjustable via the potentiometer (see previous step for additional explanation). Once the alarm set switch has been flipped, the alarm time will be displayed. Pushing the hour and minute buttons will increment the alarm hour and minute, and this time will automatically be saved to the Arduino's RAM. The PM LED should also come on when the time you are setting is at night. Once the desired alarm time has been set, simply flip the alarm set switch back and you will see the current time displayed once again. When the alarm time has been reached, the LEDs will begin to slowly turn on, until they reach their full brightness at the 15 minute mark. They will remain at full brightness until the "snooze" button has been hit, which turns of the alarm until the alarm time the next day (this is not really a snooze button, a major deficiency of this project - I would encourage you to add such a thing, as snooze buttons are an integral part of any alarm clock).
Another point of possible improvement is that the alarm time will be reset every time the Arduino loses power. If you were to use the EEPROM library, you could save the alarm time to the Arduino's non-volatile memory, and preserve its setting even after a power loss (the RTC is powered by a battery, so you do not have to worry about it losing its time). A final point of improvement would be to put the refresh() sequence (explained in the code) on an interrupt timer, so that the updating of the display is less affected by whatever is going on in the main loop of the code.
If any of the above does not work for you, go back through the schematic and all your connections to make sure everything was wired correctly. Again, I recommend breadboarding everything first, to make sure everything works for you and your components.
Step 12: Final Assembly
Once you are sure that everything is working, it is time to assemble the enclosure and secure the electronics inside. Using superglue or another comparable wood glue, assemble the frame, using the pictures as guidance, making sure that all the teeth interlock properly and that all the sides are square with each other. As shown in the pictures, you may need to temporarily tape the sides together to hold while the glue is drying. Then build the closing mechanism, gluing the two sets of small squares together, making sure that the bolt and nut holes line up. When inserting the hexagonal nuts into their holes, you may glue them down if you like, however I found that the holes were tight enough to simply friction-fit the nuts into place. After the locking pieces have been assembled glue them to the shorter sides of the frame, in the deeper groove provided for them. The hexagon-hole-sides should face towards the clock face. Again, use the pictures for assistance.
Now secure the circuit board(s) to the frame. I wanted to mount them more "professionally," using screws, however I found that hot glue was simply much easier to use. Then screw in all the switches and the potentiometer into their respective holes, and insert all the wires into the Arduino pins. At this point you should be finished, and all that is left to do is to test everything one more time and close up the box using the M3 screws.
I really enjoyed building this sunrise alarm clock and I learned a lot in the process; my hope is that the same is true for you - enjoy!