Why do you need a mirrorball when you can build your own “mirrorcube”? This project will allow you to bring the disco home (at least the lightning, the music choice is yours). What’s more, you will be able to boast that you are the handy one among your mates.
The project is based on microcontroller PIC16F877A and consists of a 3x3x3 RGB LED cube. Each RGB LED counts in fact with 3 leds: Red (R), Green (G) and Blue (B).
The control used in this project is ON/OFF, so each RGB LED can be lit with 7 colours (see image below). The full chromatic spectrum could be achieved by controlling each led’s current.
The LEDs used are through-hole (obviously they can’t be SMD) and common anode, although we will tell you what differences there are if you use common cathode LEDs.
PCB Design and components
The PCB has been designed with DesignSpark PCB 8.0 and the schematic and PCB files are attached at the end of this article. It is a 2 Layer Board with copper pour areas on both sides (5 V on top side and Ground on bottom side). Its area is 128.1 x 105 mm. (Only the first level of LEDs is shown in the PCB image.)
The components used in this project are:
- 8.4 V Battery with connector
- Linear Regulator L78S05CV (5V, 2A)1
- Microcontroller PIC16F877A
- 4 MHz Oscillator (for the microcontroller)
- 27 Common Anode RGB LEDs2
- 3 PNP transistors (IC > 540 mA)1, 3
- 3 diodes
- Resistors with various values4
- Capacitors with various values and functions (bulk capacitors, decoupling capacitors)
- Several Pin Headers and cables
(*) Pay attention to the superindexes notes. Notes 2 and 3 are specifically intended for those who want to build the cube with common cathode RGB LEDs.
1 Only 1 level (9 RGB LEDs) is lit up at a time. Each individual led needs 20 mA, which mean a maximum of 540 mA per level (if all the leds are ON).
This condition explains the requirement for the transistors (each one controls the switching of a level). We have used BC327 (IC = 800 mA). For the regulator, only as a precautionary measure, we have chosen one whose output current enables to light up the 3 levels at the same time.
2 RGB LEDs have, in most cases, 4 terminals; one common terminal (anode or cathode) and 3 more terminals, one for each individual led (R, G, B).
The LEDs used in this project are common anode. However, it doesn’t mean you can’t do the same project with common cathode LEDs. Just replace “anode” with “cathode” or vice versa in the following explanation and take into account that in your case the common terminal refers to the cathode instead of the anode.
The package and the pin numbering are shown in the image on the right. Nevertheless, terminals can have a different order (position of the common terminal, RBG instead of RGB ...). Look this information up in your LEDs’ datasheet.
3 If you have common cathode LEDs, you must use NPN transistors (for instance BC337) instead of PNP. Therefore, the schematic and the logic operation change, as shown in the image below. Notice that the direction of the diode used in the transistors’ base changes too.
4 Leds’ series resistors must be selected considering VCC (5 V), their forward voltage and their forward current, that can be different for each led (R, G, B).
In this case (you have to look your values up in your LEDs’ datasheet), typical forward voltages are 1.95 V (R) and 3.3 V (G, B) and forward current is 20 mA in all 3 cases. Therefore, the chosen resistors’ values are 150 Ω (R) and 82 Ω (G, B).
On the other hand, the transistors’ base resistor must ensure it is working in the saturation region when the LED is ON. We have used a 1 kΩ resistor.
Source code and operation
The source code has been written in C using MPLAB® X IDE v3.61 and XC8 (v1.42) C Compiler although previous versions can also be used.
There are 3 scripts attached: the source code used in this project (complete version, with all the lightning effects), a script with the basics of this project (cube with common anode RGB LEDs) and another script with the basics adapted for a common cathode RGB LED cube (as the logic operation changes).
The current source code is only an example of operation. Your experience will be more enjoyable if you develop your own lightning effects once you have understood the basics. Then, there will be no limits except for your imagination.
- Switching frequency: we only light up 1 level at a time. In order to be under the impression that all the levels are lit up at the same time, each transistor’s ON-OFF signal must have a frequency between 40 and 200 Hz. With 3 levels, this means the selected level must change between every 2 and 8 ms.
In this case, we change the selected level every 5 ms, using a timer (TMR1) and generating an interruption.
- RGB LEDs’ colours: if we have a variable for each RGB LED (27), we waste the microcontroller’s memory. Instead, we only need 3 unsigned long (32 bits) variables (colours1, colours2 and colours3), that save the colours of the 9 RGB LEDs (27 individual leds) of their respective level.
The bits 26-18 of the variable are for the ‘R’ leds, the bits 17-9 for the ‘G’ leds and the bits 8-0 for the ‘B’ leds; although other order could have been chosen. Each level’s RGB LEDs are numbered from 1 to 9 (see the PCB design).
- How to change a RGB LED’s colour: in order to light up a LED with a certain colour, we use c(R, G, B, LED, colours), where ‘R’, ‘G’, ‘B’ specify the selected colour, ‘LED’ is the number of the LED (from 1 to 9) and ‘colours’ is the unsigned long linked to one of the 3 levels (colours1, colours2 or colours3).
- How to light up 1 level at a time: we make use of the function level(), that needs 2 input variables: unsigned long ‘coloursx’, and level number ‘x’ (where ‘x’ can be 1, 2 or 3 for both variables).
The function writes on each port the values to have the desired colours and switches on the transistor that corresponds to the selected level. Of course, if you change the pin associated with each led, you will have to modify this function.
- How to change several RGB LEDs’ colour at a time: we use the function figure(), that has as inputs the variables r, g, b (desired colour for the chosen LEDs) and the array f. The array must contain the numbers of the selected LEDs, that range from 1 to 27 (1st level: 1-9, 2nd level: 10-18, 3rd level: 19-27) and must finish with a ‘0’.
figure() automatically does the proper changes in colours1, colours2 and colours3. This function has been created to easily light up a group of LEDs (even if they are from different levels), with the same colour, creating figures.
The assembly has the following steps:
1. With 9 RGB LEDs facing down, you form a 3x3 square with the LEDs equidistant from one another and separated more or less the length of the common terminal’s lead. We suggest not aligning the leads with the sides of the square (see image) as the soldering becomes more difficult otherwise.
In order to avoid the LEDs falling down, you must use a surface with previously drilled holes where you can introduce the LEDs’ cases; or simply a flat surface and an adhesive.
2. We bend the common terminals’ leads until they are horizontal and we solder them. Each lead has to be soldered to the beginning of the adjacent LED’s common terminal’s lead.
After finishing the external square, we solder the central LED’s common terminal to any of the common terminals of the other LEDs. Finally, we check continuity and verify the joints are correct. Now, we have a 3x3 square of LEDs.
3. We repeat steps 1 and 2 for the other 2 levels of LEDs.
4. Now, we solder the corresponding cathodes of the 3 levels. Before starting, we should bend, with the help of a pair of pliers, the beginning and the end of the leads of the cathodes of 2 out of the 3 levels (see image on the right). This way, we make the soldering easier and we reduce the risk of accidentally soldering the cathodes of different leds (R, G, B) for being too close.
The level whose leads remain straight will be the lowest (level 1) and the last to be soldered to the whole assembly, as we start from the top (level 3).
5. We take one 3x3 LEDs square, facing down (you should use a support, like in step 1). This square will be the highest level (level 3) and on top on it, facing down too, we place another 3x3 LEDs square that will be level 2. If level 3’s leads hold level 2’s LEDs’ cases before even starting the soldering, the process will be much easier.
After having soldered all the leads, a simple way of checking we haven’t made any mistakes is shortcutting the anodes of the 2 levels with a copper wire and verifying with the multimeter the corresponding leds of the 2 levels light up when we touch the anode and the cathode.
6. Same step as 5, but soldering level 1 to the previous structure (levels 2+3). We also check the soldering as before, but now the leds of all 3 levels should light up.
7. We have to solder the 3x3x3 cube to the PCB. We advised against bending the lowest level’ leads because this way it’s easier to get them through the PCB holes.
Each LED’s 3 leads must go through their respective PCB holes and we bend only the end of the leads before continuing with the next LED (if we don’t bend the ends, when we try to introduce the next LED, the last one will come out).
After introducing all the LEDs in their respective positions, we solder them to the PCB. Now, it is suggested repeating the verification done in step 6, as several joints could have been broken.
8. Finally, we solder 3 wires to the pins connected to the transistors’ collectors at one end, and to the common terminal of the corresponding level at the other end.
For the third time, it is advisable to check possible mistakes as in steps 6 and 7. If we succeed (or after solving the problems), we can start programming the microcontroller and checking the cube’s operation.
(*) Attached files
- Source code (attachments 1-3): source code complete version (1), source code basics (2) and source code basics adapted for common cathode RGB LED cube. If you want to use one of them, it must be included as a Source File in a MPLAB® Project. PIC16F877A must be the selected device. In other case, configuration settings will have to be changed.
- PCB files (attachments 4-6): schematic (4), PCB design (5) and 3D package library (6). (4) and (5) should be included in a DesignSpark PCB Project. (6) should be enabled using the Library Manager to visualize the PCB’s 3D View as it was intended.