Introduction: A 15-LED RGB Clock With Arduino Core

The RGB clock utilizes the RGB color composition model used in all color displays. This model uses three ‘basic’ colors, namely red, green and blue, to build any other ‘composite’ color of the spectrum. With RGB clock, however, only ‘pure’ basic colors are combined, thus limiting the resulting number of colors to 8: red, green, blue, yellow, cyan, magenta, white and ‘black’. This way it is always possible to see which of the basic colors are currently on – like red and green in yellow.

Each of three basic colors is used to display its own part. Red shows hours, green and blue show minutes. By ‘dissecting’ the color combination you see on the RGB clock into its three basic colors you can easily tell the exact time.

A small approximation is made: the ‘clock face’ of the RGB clock consists only of six hours, so 12:00 and 6:00 look the same. Similar approximation is made in a regular clock face, as there are 24 hours in the day , but only 12 are usually numbered. I did this approximation for a different project where it was strictly necessary and found that you can easily discern between, say, 2:30 and 8:30 unless, of course, you suddenly wake up from an alcohol-induced sleep not knowing whether it’s evening or morning.

The hours are displayed in three-pixel vertical red bars. If none is on it’s 6 or 12 o’clock, all five on means 5 or 11 o’clock. The minutes are displayed by pixel in three 5-pixel long lines. In the first quarter of an hour green lights turn on one by one, filling the clock face from left-upper corner to right-lower. In the second quarter blue pixels turn on the same way. In the third quarter green pixels are turned off, and in the last quarter of an hour blue pixels turn off one by one. The colors of hours and minutes combine, thus at 6:00 and 12:00 no LEDs are turned on, and at 5:30 (11:30) all the LEDs show white, which is red, green and blue all on.

This concludes the introduction; grab your soldering iron and go make it. No particular schematics or ready sketches will be present in next steps due to the fact that my clock was made of customized PCB using a not-exactly-everywhere available LED drivers. These next steps will deal with the hardware options you should consider for this project, namely, how to drive 15 RGB LEDs, as well as contain some practical advices that may be useful. The last step shows some totally different clocks you may program on this device.

You’ll need:

- 15 RGB thru-hole LEDs, preferably bigger ones (8mm in my case)

- Arduino Nano or Pro Mini

- LED drivers: either a) 3 TLC5940 (or similar) or b) 6 74HC595 shift registers with 45 220 Ohm resistors

- a clock module

- a 10x5 cm one-sided copper-clad board

- some plywood and a frame

- a bunch of wires, resistors and capacitors

I consider this project to be a fairly easy one, but some working knowledge of Arduino connecting and programming, as well as soldering skills are required.

Step 1: Hardware Considerations 1: Driving LEDs

The normal Arduino has only 6 PWM outputs, which means it can drive 2 RGB LEDs by itself. You’ll need some additional hardware to control 15 of them. In my project I use a custom board that is essentially an Arduino Mini variation with 3 LED drivers installed; you’ll have to come up with your own solution. In this section I’ll try to explain the available options.

There are four main ways to drive a bunch of LEDs off an Arduino: a dedicated LED driver; a shift register; a multiplexing/charlieplexing driver; or LEDs with a chip on board. I have little or none first-hand experience with the two latter options, so I’ll be short about them.

Multiplexing drivers, like the widely known in Arduino circles MAX7219, are intended for use in LED number displays and 8x8 LED matrixes. They can drive up to 64 individual LEDs, so they seem to be pretty good for this project, as it requires 45 connections. However, these drivers don’t have any PWM options, so you won’t be able to set individual brightness of each LED and will be stuck with 7 basic colors of RGB LEDs with no additional options like smooth animations, fade-outs and the like (to be precise, there is a project adding rudimentary 4-bit PWM capability to MAX7219, you can see its limitations on video there). It will also be rather hard to wire them, as they are intended for different use. Finally, LEDs will flicker due to multiplexing – most people don’t notice this, but I don’t like the idea. In all, this is not recommended.

LEDs with a controller chip are either WS2812B (marketed in US as NeoPixels) or APA102 (aka DotStar). The first is more or less widely known, being on the market for some time; I never even considered this thing due to its absolutely infernal control method with precise timing requirements. The APA102 emerged fairly recently while my project was underway, and this one seems a lot better than its predecessor, as it can be controlled with SPI or even bit-banging. In the States APA102 even has a very adequate price tag, selling at $4.5 for 10 LEDs. Sadly I’m not there, so for me this one is still not an option. Some notes are due though. First, APA102 is currently available only in SMD form (5050): no thru-hole LEDs for you. Second, even with WS2812B being on the market for some time, it failed to become an industry standard. I personally have serious doubts regarding these LEDs lifetime due to heating. Third, note that even in US you may encounter trouble when seeking a replacement for the burnt-out LED. That said, I still find APA102 LEDs to be an interesting development that is worth considering, even if for experimentation only.

And now for the serious, industry-approved options.

1. LED driver

These chips are pretty common, because they are used in huge advertising LED screens. As they are specifically designed to drive LEDs, they are the obvious best option. These drivers are meant to be daisy-chained, so you can connect them in chain to light up as many LEDs as you wish using the same number of Arduino outputs. They are current sink devices, which means only common anode RGB LEDs can be used; but it also means that you won’t need resistors for each LED leg, only one per chip (or none at all with some drivers).

The most known among Arduino enthusiasts LED driver is Texas Instruments’ TLC5940 16-channel 12-bit current sink driver. It became popular because it’s one of the very few breadboard-friendly LED drivers, being available in DIP package. There’s a very thorough and much-tested library available for this chip. TLC5940 needs only 5 data lines from the controller plus voltage and ground.

I use obscure LED drivers called DM633 and DM634 from some Taiwanese manufacturer. I stumbled upon them while waiting for the package of TLCs that never arrived and am pretty glad at my luck, as these guys are 3 times cheaper and actually better: they have their own free-running PWM, so need only three data lines from the controller. They also feature global brightness control (which, in fact, is an internal resistor – so it is possible to ditch the external one, although I wouldn’t recommend it) and 634 has 16-bit grayscale depth. However, they are available in SMD packages only, so you’ll have to solder them (even if to the SSOP-DIP connector to use on a breadboard). If you managed to obtain these chips and have problems making them work feel free to use my sketch with basic functionality here (note that this is work-in-progress and not a library yet, so just include the code in your sketch).

The best and fastest way to control LED drivers is by using SPI interface. However, these chips are not designed specifically for SPI, so they can be programmed using simple bit-banging technique if you need SPI outputs (pins 10-13 on Arduino) for something else. See the TLC5940 library for details.

As a bonus, LED drivers can be used also to drive servos and motors. They are, after all, just PWM output multipliers.

2: Shift registers

Shift registers are available in a variety of packages almost everywhere, they are exceptionally cheap and they can be easily used as LED drivers thanks to the excellent shiftPWM library. They can also be daisy-chained. Which makes them the second-best possible choice, especially for breadboard prototyping (provided you find a place to put 6 of them).

The most common and cheapest shift register is the good old 74HC595. You can use both common anode and common cathode RGB LEDs with it, but it has a significant drawback: you’ll need to put a resistor at each data leg of each LED, and it’s 45 resistors in all for this project (pretty doable, in fact).

The alternative is a current sink shift register, which is essentially a LED driver without any in-built PWM. Here you’ll need only one resistor per shift register, but will also be limited to using common anode only LEDs. These chips are also more expensive.

As shift registers don’t have any in-built PWM, all the modulation will be done by ShiftPWM library in the microcontroller, and these calculations eat resources. For this project this resource sink won’t even be noticeable unless you try to make some serious visualizations with antialiasing and such. There’s a resource calculator at ShiftPWM page that’ll give you an idea of how much time the controller will be busy PWMing. Again, it is recommended to use SPI to communicate with shift registers, as this is faster; bit-banging is also available.

To summarize:

- LED drivers are the best but not the cheapest option. If you are interested in making LED visualizations with Arduino, you should certainly go for it: eventually you will have to get acquainted with these chips, so why not start now? You’ll need three 16-channel LED drivers plus three resistors for this project.

- Shift registers, namely 74HC595, present the cheapest option, with a drawback of needing a lot of resistors. Still, as shift registers are present in any Arduino workshop, this option may be ideal for people who wander into the LED driving field only occasionally and don’t want to invest in dedicated hardware. This is also a good (but not the only) option if you intend to build everything on a breadboard. You’ll need six 8-channel shift registers plus 45 resistors for this project.

- LEDs with chip on board, namely APA102, are worth considering if you have access to them and are content with their SMD-only form. Note that these are new and unique, so you won’t be able to find replacement if they get discontinued for some reason. You’ll need just 15 such LEDs here.

- Multiplexing drivers like MAX7219 are to be considered only if you already have them and want to put them to some meaningful use, as they won’t provide the full PWM capability. Don’t buy them for this project – one genuine MAX7219 costs the same as three TLC5940s. One MAX7219 can drive 15 RGB LEDs.

Step 2: Hardware Considerations 2: the Clock

While Arduino can be used to calculate time, it is not a perfect solution for clock projects, as it won’t be able to keep track of time while being disconnected. Thankfully, there’s an alternative – a very cheap clock module with DS3231 real-time clock and a battery on board. It uses external power when the device is on and keeps clock ticking off the battery when there’s no other power source present. Thus you don’t have to set time each time your device is turned on.

There is one problem, however, that I must mention here to save you time. I use these modules left and right and this project was the first one where this problem popped up: the clock module doesn’t keep time when turned off. I’ve spent really, really frustrating hours trying to nail this down. I still don’t know what exactly caused this, but I suspect it was overcharging of the Li-Ion battery on the time module.

These modules always come with a charging circuit. It may look cool, but in fact it’s not because it’s useless. An ordinary 2032 battery will be able to keep the RTC chip powered for about 10 years – and that’s actually more than the guaranteed lifetime of a Li-Ion rechargeable battery.

In any case, here’s the solution: remove the charging circuit, THEN replace the Li-Ion battery with an ordinary one. Note that you must not plug in an ordinary alkaline battery without removing the charging circuit first!

The simplest way to get rid of the charging circuit is removing a single resistor on the board. That’s 201 resistor sitting next to 4-pin connector on the module (see picture above). Unsolder it or just break it with brute force, then put in an alkaline battery and bingo! No more hour resetting for you.

Step 3: Software Considerations

I won’t provide the full sketch in here because, firstly, it was developed for the particular custom hardware and so won’t work with your device, and secondly, because there’s no rocket science in there – the basic RGB clock is pretty simple to do (please feel free to ask any questions if you have problems, though). There are, however, some considerations worth mentioning.

1. Doing RGB right

The RGB clock shows time by just mixing basic colors – red, green and blue. Considering that each basic color is driven by its own data channel the way to program this seems pretty straightforward – just turn on reds for hours, then green and blue for corresponding minutes. Color mixing will be done by LEDs themselves. Simple, right?

Wrong!

While this solution looks excellent from programming standpoint it’s not that good if visual aesthetics and power consumption are considered. An RGB LED is essentially three LEDs in one package. This means that if it displays red, only one LED is working. If it switches to yellow, two LEDs are turned on, and with white all three are shining. Thus, yellow is two times brighter than any basic color and white is three times brighter. This really doesn’t look good (and that is one of the reasons HSV model should never be used with LEDs, but that’s another story for a future article) and it uses too much power – in fact, when all 15 LEDs are white (at 5:30) the device will consume 900mA and won’t even work off a USB port (500 mA).

The other reason you’ll have to ‘hand-pick’ the colors it the fact that LEDs are not color-calibrated and different bunches can vary widely in the way they output same colors. It is a good idea to do some color calibration by hand to get the exact color hues you want, even when you are dealing with seemingly simple 7 colors.

Anyway, it is better to turn on each LED individually with carefully prepared values. In my sketch I first calculate which colors must be on and write it into a small array of bytes (with three rightmost bits used), then send the prepared values to the LEDs accordingly. Here are code snippets:

Byte preparation:

for (k=0;
k<15; k++) disp15[k]=0; //clear all bytes
for (k=1; k<6; k++)
{
if ((hour%6)>(k-1)) {disp15[k-1]=B100;disp15[k+4]=B100;disp15[k+9]=B100;};
}
if (minute<16) for (k=0; k
else
if (minute<31)
{for (k=0; k<16; k++) disp15[k]|=B010;
for (k=0; k<(minute-15); k++) disp15[k]|=B001;}
else
if (minute<46)
{for (k=0; k<16; k++) disp15[k]|=B001;
for (k=(minute-30); k<15; k++) disp15[k]|=B010;}
else for (k=(minute-45); k<15; k++) disp15[k]|=B001;

LEDs turning on:

for ( k=0; k<15; k++)
{ switch (disp15[k]) { case B000: setRGBpoint(k, 0, 0, 0); break; case B100: setRGBpoint(k, 3600, 0, 0); break; case B010: setRGBpoint(k, 0, 3000, 0); break; case B001: setRGBpoint(k, 0, 0, 3600); break; case B110: setRGBpoint(k, 1800, 1200, 0); break; case B011: setRGBpoint(k, 0, 2000, 1500); break; case B101: setRGBpoint(k, 1900, 0, 1700); break; case B111: setRGBpoint(k, 1200, 1000, 1000); break; } }

2. The Clock

Don’t use the Time.h library. While it can get the time out of the external RTC chip, it is overstuffed with unneeded things: it is turning your Arduino into a clock too, eating resources and memory (around 5Kb of it in fact!). Just get the needed functions out of it and use wire.h library only.

These are the salvaged functions you’ll need:

byte bcdToDec(byte val)
{ return ( (val/16*10) + (val%16) ); }
byte decToBcd(byte val)
{
return ((val/10*16) + (val%10));
}
void getTime ()
{
Wire.beginTransmission(0x68);
Wire.write(byte(0));
Wire.endTransmission();
Wire.requestFrom(0x68, 3);
second = bcdToDec (Wire.read());
minute = bcdToDec (Wire.read());
hour = bcdToDec(Wire.read())%12; //12 hour time
}
void setTime()
{
Wire.beginTransmission(0x68);
Wire.write(byte(0));
Wire.write(decToBcd(second));
Wire.write(decToBcd(minute));
Wire.write(decToBcd(hour));
Wire.write(byte(0));
Wire.endTransmission();
}

Don’t forget to #include and Wire.begin(); in setup() and declare second, minute and hour variables.

3. A Button

It is recommended to add a button to the RGB clock: it can be useful for clock setup or visualization mode changes if you have more than one. In my project the button is used for modes change (short press), time setup (long press, 1 second) and brightness setup (even longer press, 2 seconds). There’s also an orientation setup (selecting which side of the clock is on the bottom) – it is turned on by two short presses followed by a long one. To make matters simpler you may consider using more than one button.

This leads to a question of combining time visualization with waiting for a button presses. Again, the correct programming answer (assigning an interrupt to the button) is not necessarily right in our case. What if you want to read some sensor – for example, a photoresistor – to change the device behavior? What if you want to control the device with an IR remote?

As this is not strictly related to the particular simple RGB clock project of this instructable I’ll be brief. The visualization routines in my projects are not looped in on themselves: they just set up a display and then return control to the main loop() cycle that does stuff like checking buttons or sensors or anything else, then loops and calls the visualization again. I use a global variable modeCounter to keep track of the current visualization position for animated modes (it basically is the same as for(,,,) but without the contained loop). The details are really the matter for another article, hope this little snippet will help (and again, feel free to ask questions).

Step 4: Assembly

The RGB Clock consists of 4 major parts:

- The controller (namely, Arduino)

- The LED-driving hardware (drivers of shift registers, unless you use APA102 or similar LEDs)

- The clock module

- The display board with 15 8mm RGB LEDs

These parts can be separate or combined on one or more boards in any way. In my project the controller is on one board with LED drivers, but this is not optimal solution. If you’re building this from scratch I’d advise putting LED-driving chips on the board with LEDs: there’s enough space for everything and there will be less wires sticking around. Sure, there will be trace crossings with wire (or R0 resistor) bypasses, but not a lot of them. If you’re using 74HC595 shift registers as LED drivers you’ll have 45 resistors to use as bypasses, by the way. Note that DIP chips (shift registers or LED drivers) will be mounted on the same side of a single-sided board as the LEDs (the one without copper), so avoid using holders to keep their height to minimum.

It may be tempting to use perforated prototyping boards for this project. For example, a small 3x7 cm board can host all six 74HC595 chips, as shown above. However, the wiring of such a board is a headache. I drew all the needed wires and solder connectors (yellow rectangles) on such a board – you may see the scale of disaster yourself.

The hardware setups of different LED-driving circuits are available at their respective libraries pages:

- shiftPWM for 74HC595 shift registers;

- tlc5940 for TLC5940 LED driver.

If you’re using DM63x chips you may wish to check the datasheets, but their setup is pretty straightforward: pin 1 = GND; pin 2 = DATA IN; pin 3 = SCK; pin 4 = LATCH; pins 5-20 are LED outputs; pin 21 is not used here and can be left alone or grounded; pin 22 = DATA OUT (goes to DATA IN on the next chained chip); pin 23 = REXT, it should be connected via 2k or 3k resistor to GND; pin 24 = Vin, just 5v input, a 100nF capacitor is recommended. If you’re using SPI, DATA IN is pin 11 on Arduino, SCK is pin 13 and LATCH is pin 10 by default, but can be changed to anything you wish (although pin 10 must stay in OUTPUT mode to make the SPI interface work correctly).

Don’t try to align LED driver or shift register pins in a ‘right’ way, namely so than output 1 goes to red on LED1, 2 to green, 3 to blue, 4 to red on LED2, etc. Just connect them in most convenient way: it doesn’t matter as you’ll always be able to make a substitution table in a program and address your LEDs via it. For example, here’s mine:

uint8_t led15table[45]=
{43,42,41, 25,48,47, 28,27,26, 38,39,40, 24,33,34, 44,45,46, 10, 9,32, 18,19,20, 37,36,35, 23,22,21, 29,30,31, 11,12,13, 17, 8, 7, 3, 2, 1, 6, 5, 4};

What IS important though is the way you place LEDs on the board – they must all be placed identically, never turned upside-down or to the side. Because the RGB LED consists of three different LEDs it will look different when viewed from different sides even if it displays the same color.

So, let’s assume you decide to make a board for LEDs and their drivers yourself, and then connect it to an Arduino Nano/Mini and a clock module – three boards in all. In that case you’ll need a one-side copper-coated board to draw all the traces on, 5x10 cm size is good for this project. As the board density is rather low, you may easily draw all the traces with a 0.8mm paint marker like the Edding 780.

If you are going to use SMD chips instead of DIP ones, especially in TSOP package, the paint marker won’t be able to provide thin enough lines for the solder pads. If you have a laser printer, you may go for the technique described in this instructable. If you don’t have the printer, you may still draw the solder pads using asphalt lacquer aka bitumen varnish (or a more expensive etching, or eau-forte ground available in artist’s shops) and a needle. Cover the places intended for solder pads with lacquer, let it dry, then draw the trace outlines with a needle – I use a broken dart.

Don’t forget about power supply. If you’re using an Arduino Nano you may use its USB connector, but with Pro Mini you’ll have to place a connector on the LED board.

The process of making a board and etching it with hydrogen peroxide & citric acid solution is described in step 5 here. It is a good idea to draw the board in some editor first – with a small one-sided one you can use any free or evaluation-version software. It is easy to make mistakes without this step – for example, I forgot one connection and had to solder a wire to LED anode.

Once the board is ready, cover all traces with tin to avoid oxidization and solder everything except LEDs on it. Before soldering LEDs prepare a ‘display field’ for your device, namely a plywood board that the LEDs will be sticking out of. My ‘display’ is 15x9 cm in size, but that’s a bit small – go for 15x10 cm at least to accommodate everything neatly. Cut the plywood then drill holes for LEDs in it. Some splintering is inevitable, but filler paste will deal with it. Be extra careful when drilling holes, take some time aligning your drill, as even unnoticeable micron-wide mistakes or wrong angles will be rather visible when the LEDs are on (this is a hard-learned advice as you can see from the photos of my clock). Insert LEDs in their holes, then solder them to the LED board: this way you’ll make sure they are placed where you want them.

Now you can remove the plywood board, paint and frame it. The frame is the most expensive part of my project: it cost half the overall budget. That’s why a 15x10cm (aka 4x6”) ‘display field’ is better, as this is a standard size for cheap photo frames (an excellent Ribba from IKEA is one example; such frames are also available from photo shops). The ideal frame however should be deep enough to house everything – it’s called ‘boxy profile’, these frames are used to display dead insects and such.

Step 5: Going Further

I made this thing as an RGB clock described in step one. However, the resulting device is essentially a 5x3 color display, and I can’t stop until all the program memory of an Arduino chip is filled up, so another 20+ modes were included.

Most notably, if you put the clock vertically, you can just show normal numbers on it. So, an ‘abridged’ version of the RGB clock was born that shows hours in red numbers and minutes in green and blue dots. And it’s a 12-hour clock; 10, 11 and 12 are shown in roman numerals. The Rainbow Clock shows hours, minutes and seconds in spectrum hues; it’s not that easy to discern particular minutes on it. Another interesting mode is the Puzzle Clock that shows normal numbers (hours in red, tens of minutes in green and single minutes in blue) on top of each other, producing a seemingly random pattern of colored dots. Some modes are understandable, others seem weird, but all of them show time. The video above shows some.

I’ll explain the way the time is shown on some of these in the next article dealing with one-pixel information displays, but for now will leave you to think up and program your own stuff on this device.

And, well, while I was finishing this instructable a bunch of boards arrived from the fab, so I made a couple of clocks with them, as seen in works-in-progress above. The boards contain everything on them and can house both SMD and thru-hole LEDs, which was pretty useful with a ‘stained-glass’ model (shown above).

As always, comments and questions are welcome!

Time Contest

Participated in the
Time Contest

Make It Glow! Contest

Participated in the
Make It Glow! Contest