Universal Led Strip Controller

Rob Bell and Mike Hansell

Issue 10, April 2018

This article includes additional downloadable resources.
Please log in to access.

Log in

This tiny project creates dazzling displays with an addressable LED strip.

This controller started life as the brains behind our Acrylic Lamp in Issue 8. However we quickly realised there was more potential in the fundamental idea than just for a lamp. The result is our universal LED strip controller. This is our first project to integrate the ATtiny85, which we’ve been excited about for a while now. It truly shows the versatility of the chip to provide microcontroller flexibility.


There are plenty of projects out there that use a full-size Arduino UNO or other similar microcontroller to control addressable LEDs. Indeed, our lamp project we just mentioned, used an UNO. However after it’s programmed, the size of the board simply becomes cumbersome, and it can be difficult to justify the cost of the UNO, in addition to the other hardware. This is the PERFECT scenario for an ATtiny85 to take over, once our prototyping is complete.

Our original PCB design for this project was good for an amp or two, which was fine for the original purpose of driving a dozen or so LEDs. But we quickly realised there is SO much more potential for this to be a universal controller. So here it is! And it’s good for 10A - that’s a lot of LEDs!


If you would like some background on this project, it may be worthwhile reviewing the code from our originally published UNO-compatible acrylic lamp project from Issue #008, however there is one major difference. Interrupts.

While our original code was lean enough to compile to an ATtiny85 in theory, there was a challenge between us and our downscaled intentions. The ATtiny85 doesn’t handle interrupts the same way as an ATmega-based chip like the Arduino UNO or Mega will. This required something of a rethink to make our code compatible for the ATtiny85.

There are eight pre-programmed modes. However you could expand this yourself, later if you wish.

The PCB itself provides ICSP headers to allow programming while the ATtiny85 is in place. If you use an IC socket (probably not a bad idea, even for experienced constructors), then you can simply remove it and install into a programmer of your choice if you prefer.

circuit diagram


Parts Required: Jaycar Altronics
1 X ATtiny85 ZZ8721 Z5105
2 x 100nF Ceramic Capacitors RC5360 R2865
1 x 10uF Electrolytic Capacitor RE6066 R5065
2 x 1000uF Electrolytic Capacitors RE6220 R5182
1 x 10Ω Resistor RR0524 R7510
3 x 300Ω Resistors RR0560 R7546
2 x 10kΩ Resistors RR0596 R7582
1 x 100kΩ Resistor RR0620 R7616
2 x 10kΩ Linear Pots RP7510 R2243
1 x SPDT Switch SP0380 S1398
2 x M205 Fuse Clips SZ2018 S5983
1 x 10A Slow Blow Fuse SF2168 S5662
2 x 20 Pin Header HM3250 P5410
1 x 2 Pin Header HM3130 P2028
1 x 3 Pin Header HM3173 P2029
2 x Red LEDs ZD1500 Z0100
2 x 1N5819 Schotkey Diodes ZR1020 Z0040
1 x BC548 Transistor ZT2154 Z1042


The PCB is rather compact; however, we wanted it to use lots of LED strip; after all, this circuit has the ability to control hundreds of LEDs, so why not? But 5V LED strip can start to draw a reasonable amount of current reasonably quickly, so 10A can be drawn by a few metres of densely packed strip (such as 60 LEDs per metre). It’s a double-sided design, with a handful of tracks on the top layer, which keeps things simple. As usual, our Bantam Tools’ Mini Desktop PCB Mill made fairly light work of this PCB.


Firstly, check your PCB for broken tracks, corrosion, or other manufacturing defects. Give it a good clean with some isopropyl alcohol or circuit board cleaner, to help remove any grease or residue that may exist; this will help reduce the incidence of dry joints and other problems. Use the lowest temperature possible for the solder you’re using, to help avoid overheating components. It also helps to avoid overheating the tracks on the PCB, which can quickly be damaged by excessive heat.

As with all our PCB projects, we recommend following a standard construction pattern, which is hardware, passive components, semiconductors, then anything ultra sensitive. That means you should install the terminal blocks, ICSP headers, and fuse holders first (you can install the fuse also, or do it at the end), as well as the switch. We also recommend using an IC socket for the ATtiny85. It means you can remove it for programming in a programmer, and also helps avoid damage via soldering. Then move to the resistors and capacitors, as well as the two potentiometers. Then insert the diodes and LEDs, taking care with the orientation of all polarised components (marked on the overlay).

Before installing your ATtiny85, which is the most sensitive component, we recommend going through the testing process first. If you’ve already programmed your ATtiny85 (or it came preprogrammed via a kit supplier) you can skip the code portions, although there’s some valuable ATmega-to-ATtiny considerations in there, which are worth reviewing either way.

PCB diagrams


We’ve added a new mode of operation in this version of the controller, which was intended but didn’t quite make it into the Acrylic Lamp project in Issue 8. Mode 8 displays a user-selectable single colour. The colour is selected via the rate potentiometer. The brightness pot functionality hasn’t been changed and still adjusts intensity.

With the pot set to minimum, the lamp displays full red. Rotating the pot changes the colour from red, to yellow, green, cyan, blue then to magenta. Changing the colours is achieved by increasing or decreasing the brightness levels of the colours that we are working with. For example, to change from green to cyan we simply gradually increase the blue intensity. Then for cyan to blue, we decrease the green intensity.

This is relatively straightforward until you consider that the Arduino translates the position of the pot to a range of 0 to 1023. Dividing that by 5 (for the 5 colour changes) gives us roughly 205 different values for changing the intensity. That sounds reasonable until you consider that the RGB LEDs we are using have 256 levels for each of their red, green and blue light intensity. So, do we use 0 to 205 producing less than maximum intensity? Do we use 50 to 255, which means the intensity of the red, green or blue light will never be extinguished? Either of these will not provide the correct relative intensity. The solution is to use the Arduino map function.

map() brilliantly allows us to change a range of 0 to 205 (or 50 to 255) to the range 0 to 255. Not only that, but it works backwards too. Consider the range of 205 to 409. map() allows us to convert that to a range of 255 to 0, to allow decreasing the light intensity in a linear fashion. Clearly, using map() in this way will lose a few values during the translation process but this is much more desirable than the alternative.


You can continue to use the Arduino IDE that you are familiar with. Just like non-standard Arduino boards need to be added via the boards manager, the ATtiny85 is no different. Thankfully the process is somewhat familiar and straightforward.

To write our compiled sketches into the ATtiny85 we used a SparkFun Tiny Programmer. This looks like a USB Flash Drive with an 8-pin IC socket to plug the ATtiny85 into.

We now have one further setting to consider, which is how fast do we want to run the device and how accurate does it need to be? Out of the box this is 1MHz compared to the standard 16MHz of an Arduino UNO. The clock speed can be controlled with an external crystal which uses two vital pins out of the six we had, or we set it to use the internal oscillator, which is not as accurate as the external crystal, but costs nothing and saves two pins. For this application we will use the internal 16MHz clock.


As we are using a different programming method to a standard UNO board, we need to configure it appropriately. Several adjustments are made via the “Tools” menu. Select the “USBtinyISP” and set the board to “ATtiny25/84/85”. Set the CPU to “ATtiny85”. On the clock’s sub-menu you can see a range of clock settings. Select “Internal 16MHz”. It’s worth noting that an external crystal can be used with the ATtiny, and for critical timing thus may be better than the internal RC-based clock; but for our purposes it’s more than adequate.

The final setup step is to set the ATtiny85 itself to use that “Internal 16MHz” setting. This is done via the “Burn Bootloader” option. We’re not actually writing a bootloader at all at this point, but this process sets the clock rate.


In most respects, this is similar to using a standard Arduino, with the exception that it has a lot less IO pins, and hardware interrupts are not supported in the same manner. The attachInterrupt() function is not supported, therefore we used the TinyPinChange library.

With a standard Arduino we would use:

SetMode, FALLING);

and an interrupt service routine like:

void SetMode()
  Mode += 1;
  if (Mode > 7)
  Mode = 1;

With the ATtiny85 we use:

virtPort0 = TinyPinChange_RegisterIsr
(ModePin, SetMode);

and an interrupt service routine like:

void SetMode()
  if (TinyPinChange_RisingEdge
(virtPort0, ModePin)) 
  if (Mode >= 9) Mode = 1; 

You can see it’s just a few more lines. The net effect is pretty much the same result, but the change is necessary to remove unsupported code.


As with most of our projects, we’ve provided a convenient 3D printed case file for this one, which has been custom-designed to be as compact as possible, while still providing access to everything. It’s a very straight forward case to help mount the PCB, keep it from accidental shorts, and generally finish the project off. The case also provides relief for the potentiometers to avoid undue stress on the PCB when in use. The print itself, and mounting, is very straight forward.



Before you insert your ATtiny85, visually inspect your finished PCB for any flecks of copper, wire, solder, or anything else that might create a short circuit or other issue. If it all looks good, apply 5VDC to the input terminals. You should see LED1 illuminate (assuming you have installed the fuse). Of course, if the fuse doesn’t blow right away, that’s a good sign there’s no major short circuit anywhere.

Grab your favourite multimeter and run a few basic checks. Firstly, you should have 5VDC on the LED strip power terminals as marked (pin 1 for 5V and 3 for GND). If you don’t, you could still have a short circuit, or a dry solder joint somewhere. You can also check that you have 5V on pin 8 of the socket for the ATtiny85, and GND on pin 4. LED 2 will illuminate when using the ICSP programming header, so don’t expect it to come on right now (we’ll go further into ICSP programming in a future article, but wanted to include it for convenience if you already know how to use it).

If everything checks out, remove power (and give the capacitors time to discharge, the LED should be fully out). It’s now time to install the programmed ATtiny85. Take care of orientation as per the diagram and overlay. Once installed, connect some addressable LED strip to the output terminals, and you should be ready to fire it up!

If you switch everything on and there’s no output, go back through your PCB, looking for any suspect joints. Also go back through the programming steps to ensure your ATtiny85 is programmed correctly.


This controller is fairly powerful, and it provides massive control and versatile display options. However, the benefit of the ATtiny85 is that it’s fully controllable and can be reprogrammed to suit your requirements. It would be feasible to add some music sync or other external influence, or perhaps you could cascade multiple units to sync together. You can easily reprogramme the microcontroller to do whatever you like, within the memory limits of the ATtiny85.