As it says, "Beautiful light performance"

Well, we did our first performance with the LED strips on Wednesday at Islington Mill in Manchester,and I'm relieved to say they worked flawlessly, even after one of the wheels was dropped just before the performance started! The lighting in the venue was a bit too bright to make a good video, so Andy made a video of the strips in action at Thursday's Travelling Light Circus rehearsal which he's put up on YouTube. Even though I say it myself, I think it's rather good :-)

Seeing the strips in use by the talented TLC performers just gives them an entirely different dimension, and I think the video is really well done as well. For me, one of the best bits of the project has been the opportunity to work with people who have an artistic clue :-)

Categories : Arduino, Tech

Connecting a HL1606 strip to an ATmega

I've been left a comment asking how the HL1606 strips are connected up to an Arduino. The wiring is really pretty simple, but depends on exactly which ATmega version you have, as the hardware SPI pins vary from MCU to MCU. The following assumes it's a ATmega328P as used on the more modern Duemilanoves, you'll need to refer to the MCU documentation and the board schematic to find the correct ports and pins for different Arduino versions.

The 328P uses the following pins for hardware SPI:

/CS    Port B Pin 2    (Arduino pin 10)
MOSI   Port B Pin 3    (Arduino pin 11)
MISO   Port B Pin 4    (Arduino pin 12)
SCK    Port B Pin 5    (Arduino pin 13)

I used Timer 2 to drive the fade clock on the strips. The output of Timer 2 uses the following pin:

TIMER2 Port B Pin 1    (Arduino pin 9)

The strips themselves have the following labelling on the inputs:

S-I    Fade clock input
D-I    Data input
CK-I   Data clock input
L-I    Data latch input

So you need to wire up the strip as follows:

ATmega      Strip
/CS     to  L-I
MOSI    to  D-I
SCK     to  CK-I
TIMER2  to  SI

Note that if you want to wire up more than one strip you'll need to work around the fact that the HL1601 strips don't implement the SPI protocol properly. The easiest way is to gate the SCK signal with the /CS line so that when a strip is not being accessed it doesn't see the data clock. I've detailed the problem and the solution more fully in this earlier post,

Categories : Arduino, Tech

I'm wheely pleased...

Last night I met up with Andy and Colin of The Travelling Light Circus at MadLab to finally finish off some the LED strips that I've been working on for so long. The original plan was for them to be worn, which would have meant splitting the 4 20-LED strips connected to each strip driver in half, to allow for bending at knees and elbows. That would have meant doing an additional 32 joints, so when they said they'd come up with an alternative way of mounting the strips I was not at all unhappy :-)

Andy managed to source some translucent plastic tube that the strips slide neatly inside. The tube does two things, it protects the fairly fragile strip from damage and it also diffuses the light from the LEDs to increase the viewing angle and provide a nice glowy effect. Andy and Colin's plan was to mount a box to contain the strip driver on the hub of a bike wheel and to then attach the four tubes + LED strips to the wheel as if they were 'umbrella spokes' - the picture below makes the setup clear:

LED wheels

Will of TLC fabricated a really good mounting for the box, and the batteries and strips were simply attached to the bike wheel with cable ties. The wheel itself is mounted onto a large diameter aluminium pole, attached to the wheel where the gears would normally be. The really neat thing is that because Will used rear bike wheels he could keep the freewheel mechanism in place, so simply 'flicking' the aluminium pole sets the whole thing spinning. Of course having got them finished, we had to have a play :-) The first video was taken inside the MadLab building by Sam from Girl Geeks when we had the first wheel finished.

The second video is with two wheels and was taken outside MadLab on Edge Street, just across from the Common bar and we caused quite a commotion, with people coming out of the bar to see what we were up to. As you can see from the video, the patterns on both wheels are synchronised. The slightly wobbly video is because I was filming and operating the radio controller for the strips at the same time - you can hear the switch clicks on the audio as I'm changing the patterns. And I love the obligatory enthusiastic American on the video soundtrack - "Awesome!" :-)

Categories : Arduino, Tech

Openbench Logic Sniffer comes of age

Open Logic Sniffer

A while back I bought a Openbench Logic Sniffer from Dangerous Prototypes. Whilst it kind-of worked it was most definitely alpha and really not much practical use - no big deal considering the low price. However everything is field-upgradable so I put it to one side and more or less forgot about it. Over the last few days I've revisited the project and upgraded everything, and it's turning into a fantastic little tool. The first thing of note is that the FPGA core has been completely rewritten by doggsbody, who almost unbelievably has managed to get most of the functionality of a HP16550A logic analyser into the FPGA, although the user interface hasn't yet been extended to allow access to all the new goodness.

The original flakiness between the FPGA and the PIC processor used to glue everything together seems to have been solved as well. The real icing on the cake is there's also a new client to drive it all - the old SUMP client was really getting a bit long in the tooth, and there's a new and much superior version that Jawi has produced. Unfortunately although the client is written in Java, it didn't work Solaris as it didn't include the Solaris version of the RXTX JNI library. Jawi very kindly helped me get it all working, and even better he's integrated Solaris support into the next release as well, so it will just work out of the box. There's still more work to be done, for example, from what I can gather the 200MHz sampling mode still doesn't work properly, but having said that the progress since I last took a serious look a the project is very impressive.

The last thing of note is there's now a buffer wing available that allows you to use all of the available 32 channels with 5V inputs - I'm very tempted to get one :-)

Categories : Tech

Don't delay()

It's very common for Arduino sketches to use the delay() library routine to control timing when performing time-related operations such as LED animations. Unfortunately delay() is toxic if you need to do more than one thing at once - for example animating more than one LED strip - as calling delay() just makes the CPU spin until the required amount of time has passed, and obviously nothing else can happen until the delay() call returns. The same is true for anything that uses any kind of spin-loop to wait for an event, for example polling a switch or a rotary encoder until it changes state (commonly used as a way of debouncing). The Arduino ecosphere is full of such example code and to be blunt all of it is completely useless - unless of course all you want do is dedicate your whole microcontroller to dealing with a single IO device.

It is possible to partially work around this issue by using timer interrupts to trigger actions, because the interrupt service routine will be called even if delay() is currently executing. However interrupts have their issues as well. The issues around interrupt service routine overhead and reentrancy are fairly widely understood. The issues around atomicity are less well understood, even in commercial products. Simply declaring a variable as volatile isn't sufficient - except for very simple cases you need to be sure that interrupts are disabled during all access to variables that are shared between ISR and non-ISR code. And if you are accessing several variables, or a structure, you need to make sure interrupts are disabled around the entire block.

Beyond the relatively simple use of interrupts, the next thing that's often considered is a Real-Time Operating System (RTOS) such as FreeRTOS. This seems like an attractive solution - a preemtive scheduler, interprocess communication and synchronisation all come as standard. Unfortunately when running on a microcontroller such as the ATMega there are a number of issues that a RTOS either doesn't solve or even worse, directly creates:

  • A RTOS may help manage shared software resources by providing features such as thread-safe queues and lists, but it can't really solve the problems related to shared hardware resources. For example, when several tasks need to access the SPI bus they each need to complete their work before relinquishing the bus. If a task is communicating with a peripheral on the bus, scheduling another task in the middle of the operation is not possible so RTOS preemption support is irrelevant - preemption needs to be disabled anyway until the current task has completed its bus transaction.
  • Supporting preemption means that tasks can potentially be suspended and resumed at any point. This means that the complete state of a task needs to be saved somewhere, including all the processor registers and the current stack for the thread. This overhead is significant - the ATMega168 only has 1Kb of SRAM, and the ATMega328P has 2K. Reports say that as few as 3-4 FreeRTOS tasks can be run on Arduino-class microcontrollers.
  • avr-libc, the core of the runtime system, isn't thread-safe, so if you use a RTOS you need either to lock around every call into avr-libc or you'll need a complete replacement for avr-libc. The situation with commonly-used Arduino libraries is just as bad - they weren't written with threads in mind, and will almost certainly break in strange and mysterious ways if used with a RTOS.

All in all, a RTOS isn't a good solution for severely constrained platforms such as the ATMega, yet we really need something to help us manage concurrency. That was the impetus behind the creation of my task library. It has the following features:

  • Non-preemptive, cooperative scheduler.
  • Fixed, priority scheduling governed by task list ordering.
  • Task list fixed at compile time.
  • Small code size - 28 bytes for the Task class and 116 bytes for the scheduler.
  • Low RAM requirements - 4 bytes + 2 bytes per task.
  • No thread stacks required - each task runs to completion, so the stack is fully unwound before task switching.

Whilst the task manager is undoubtedly much more limited than a RTOS, the limitations are ones that can usually be lived with. In compensation it becomes possible to schedule many tens of tasks even on a severely constrained platform such as the ATMega. As long as we can break the workload into small enough chunks, we can just schedule the tasks in a cooperative fashion. By providing priority scheduling we can ensure that even when temporarily overloaded the system will still remain responsive by scheduling the most important tasks first, and deferring the lower-priority tasks until the load drops again. In any case, preemption is no help if the system can't actually keep up with the rate of events it is being expected to handle.

So, in summary don't use delay() when there are better alternatives available! :-)

Tags : , , ,
Categories : Arduino, Tech