Radio-controlled HL1606 strips

Well, I've finally finished the design and implementation of the radio-controlled LED strips I've been asked to make for The Travelling Light Circus. It's taken far longer than I expected, but I've learned an immense amount in the process. The remaining tasks are to construct some more boards, put the boards into suitable enclosures and to sort out how best to package and connect the strips, so now seems like a good point to write up what was involved in the project. Some of the items are worthy of posts of their own, but first I'll give an overview of how everything fits together. The system is composed of two parts, a single controller and a number of LED strip drivers. The controller is used to select the required pattern and to synchronise the LED drivers, with the communication being done with 2.4GHz radio transceivers. I've put a video together to show everything in operation, and there are some annotated photos of the controller and LED strip drivers at the start.

Hardware

As I've said, the hardware consists of two parts, the controller and the LED strip driver. At the moment these are made using discrete parts on a hand-built breadboard, but version 2 will be a PCB with most of the components mounted directly on the PCB.

Controller

The controller consists of the following parts:

  • Arduino Pro Mini. This uses a ATMega328p microcontroller and runs the controller software.
  • 4-digit 7-segment display, from SparkFun. Whilst this works, getting it to work cause me an inordinate amount of problems, as I documented in an earlier post.
  • Voltage regulator - a 7805, which I've discussed in an earlier post.
  • nRF24L01+ radio transceiver. This a a reasonably complicated SPI device, capable of working in several different modes. I'm using a breakout board from SparkFun, but in future revisions the radio chipset will probably be integrated onto the controller PCB.
  • A rotary encoder/switch used to select and activate the required pattern. I've already discussed this in an earlier post.
  • A simple voltage divider to sense external battery voltage and shut down when the battery is discharged.

LED strip driver

The LED strip drivers consist of the following parts:

  • An Arduino Pro Mini. This runs the software that drives the LED strips.
  • A nRF24L01+ radio transceiver, which receives the control and timing messages from the controller.
  • 74125 glue logic to make the HL1606 strips behave like proper SPI devices. Despite the manufacturer's claims they aren't true SPI devices, a topic that I covered at length in an earlier post.
  • Voltage regulators - two 7805 linear regulators. Two are needed to provide the 4 amps that is required to drive the 4 LED strips. In future revisions this will probably be replaced by a switched-mode supply as the 7805s get very hot under high load and are quite inefficient, both of which are issues for portable use.
  • A simple voltage divider to sense external battery voltage and shut down when the battery is discharged.
  • A thermistor used to sense the temperature between the regulators. When it reaches 60C the strips are turned off to protect the hardware. When it drops back below 40C the patterns are resumed.

Software

The software is the most complicated part of the system, and it's divided into four main parts, described below. The various parts of both the controller and LED driver are implemented as tasks, implemented using the task manager described in the library section below.

Library code

This is code that is used in the LED strip project but that is used in other projects as well.

SPI master library

The nRF24L01+ radios, the 7-segment display and the LED strips are all SPI devices, so it seemed useful to abstract the core SPI master functionality into a separate library.

nRF24L01+ driver

This driver builds on top of the SPI master library and provides access to the low-level nRF24L01+ functionality such as device configuration and message transmit/receive.

Task library

This library has been described in an earlier post. It is a simple non-preemptive task scheduler with fixed priority scheduling and a 1 millisecond timer tick. It is available for download from here.

Common code

This is code that is specific to the LED strip project, but that's shared between both the controller and the LED strip drivers.

Global configuration and LED strip colours

Some aspects of the system such as the colour definitions for the HL1606 strips, timing intervals, radio channels etc are shared between the master controller and the slave LED strip drivers.

Radio message

This is a simple definition of the control messages that are sent from the master to the slaves.

Pattern animator

Both the master and the slave units run the same pattern animation code. In the case of the master, the output is a series of synchronisation radio messages that keep the slaves in synchronisation. In the case of the slaves, the output is a series of SPI commands that drive the LEDs. This means that if a slave temporarily loses the radio signal from the master, it will continue to display the pattern. The resonators used on the Arduino pro Mini boards are not very stable, so in early testing it became apparent that the slaves would have to be kept in synchronisation by the master. To achieve this, the master sends a constant stream of synchronisation messages no more than 13 milliseconds apart to ensure the pattern generators in the slave remain in step.

Animation output and animation fade clock base classes

As the master and the slave are both running the same animation code, the animation output and fade clock output code were implemented as empty base classes, with the master and slave providing implementations appropriate to their roles in the system.

Pattern definitions

As has been noted, both the master and the slave run the same pattern animation code, so they both need access to the pattern definitions. Each of the 4 strips on the slave are animated separately, so the pattern definitions are a reasonably complex tree of data structures containing colour, movement and timing information that are interpreted at run-time. The pattern definitions are too large to fit in the ATmega's limited 2Kb of SRAM, so they are stored in program memory and the subset necessary for the current pattern step is extracted into SRAM and interpreted at run time.

Master controller

The software in the master is implemented as a set of tasks, implemented using the library descried above. The main program simply initialises the tasks before transferring control to the task scheduler. The tasks are as follows:

Display driver task

This manages the 7-segment display described in the hardware section above. Updating the display is not time-critical, so updates are made by saving the new display contents and scheduling the display update when no other high-priority tasks need to run.

Radio transmitter task

The radio task is responsible for transmitting the synchronisation messages via the nRF24L01+. Transmitting a message consists of storing the message details and scheduling the transmitter task to run. When it runs the message is transferred to the radio via SPI and transmitted. As synchronisation is key to the correct operation of the slaves, this is the highest-priority task.

Four animation synchroniser tasks, one per strip

These are derived from the Animation output base class that is defined in the shared code section. They are called by the pattern animators when the next step for an animation pattern needs to be output, at which point they queue a synchronisation message that is subsequently send by the transmitter task to the slaves.

Four pattern animator tasks, one per strip

Each strip is animated separately, so each requires its own animator instance. The animators extract the pattern definitions from PROGMEM and interpret them. At each new step the animators call the synchronisation tasks to output the appropriate synchronisation message.

Encoder/switch handler task

The rotary encoder and switch need to be read and debounced as described in this post. This task is responsible for doing that.

Voltage monitor task

The voltage monitor task samples the battery voltage every second via a voltage divider. Once the battery voltage drops below a certain level, the subcomponents of the master are powered down and the ATMega is put into suspend mode.

Interaction and pattern switching objects

These objects simply marshal and redirect the internal messages between the various tasks. They are called directly by tasks and call non-blocking operations on other tasks, although they themselves are not implemented as tasks.

Slave LED strip driver

As in the master, the software in the slave is implemented as a set of tasks, implemented using the library descried above. Again, the main program simply initialises the tasks before transferring control to the task scheduler. The tasks are as follows:

Four LED strip driver objects, one per strip

These are called by the pattern animators when the next step for an animation pattern needs to be output, at which point they output the new LED settings to the strips via SPI. They aren't tasks as they merely transmit the LED setting bytes to the strips.

LED clock object

The LED strips need a fade clock to drive the pattern fades as described in this post. This object manages the internal ATMega timer that is used to generate the fade timing clock pulses.

Four pattern animator tasks, one per strip

Each strip is animated separately, so each requires its own animator instance. The animators extract the pattern definitions from PROGMEM and interpret them. At each new step the animators call the LED strip driver objects and the LED clock object to output the appropriate synchronisation message.

Radio receiver task

This task receives the incoming radio messages from the master, decides which strip they refer to and makes any necessary adjustments. This could be to switch to a new pattern, to adjust the current pattern step of a strip if it leads or lags the controller, or to adjust the delay until the next pattern step if the clocks on the master and the slave have drifted.

Voltage and temperature monitor task

This task samples the battery voltage and temperature every second via a voltage divider and a thermistor. Once the battery voltage drops below a certain level, the subcomponents of the slave are powered down and the ATMega is put into suspend mode. If the temperature exceeds 60C the strips are turned off until the temperature drops below 40C, at which point the pattern output will be resumed.

Summary

This project is reasonably complex for a microcontroller - about 5000 lines of code with the master and slave binaries both being 13K in size. There are a number of non-obvious design constraints and decisions that I haven't had space to fully explain in this post, I'm intending to write some follow-ups to explore those areas in more depth.

Categories : AVR, Tech


Re: Radio-controlled HL1606 strips

Hi Alan,

I'm working on an act that involves led strips that have to be controlled individually through Quartz Composer. I've build the interface in Quartz Composer but I'm not skilled enough to make the routing to the led strips with Arduino. A colleague of mine made everything using DMX controllers and a whole bunch of cables but I want it to be simple and small. 

Could you please contact me at patrickweel@live.nl so we can work things out. I'm willing to finance the whole project.

Kind Regards,

Patrick

Re: Radio-controlled HL1606 strips

Hi Alan

These strip lights would look good as necklaces or headbands in nightclubs and bars etc, could they be made for that purpose and could the controller be synched to music?

Would be good to have a chat about this my email is lee@vendandglow.com or phone on 07929001494.

 

Thanks 

Re: Radio-controlled HL1606 strips

I think they wouldn't be practical for that use - the battery packs and controllers are too bulky and the strips themselves are probably too fragile.

Re: Radio-controlled HL1606 strips

 Dear Alan,

I am working on project, where 200+ odd performers perform music and dance show. i am intrested in your product and wish i can implement LED strip on the all 200 performers, controlled by single controller, dstance to controll is about 1000 meters max. all 200 in similar pattern at given time. more than 32 effects needed, pls advice. even with pricing. 

look forward to hear from you soon. pls mail me on soham.solu@gmail.com.

 

best regards

Sandeep