We use the APA102 RGB LED pixels on both our Blinkt! and Mote boards now, and recently we came across an interesting quirk when we switched to a new batch of APA102 packages.

The first batch of our Blinkt! boards (including the prototype boards, with which the software library was produced) were assembled with the original batch (batch 1 from here on in). Once these ran out, we switched to the newer batch (batch 2 from here on in) and didn't really think much of it; to all intents and purposes they looked identical.

Die differences

To the naked eye, there was a slight difference in the dies on the two batches of APA102s. Batch 2 were slightly smaller and darker, compared to batch 1.

Here are some microscope images of the batch 1 packages.

Batch 1 APA102 far

Batch 1 APA102 near

And here are the batch 2 ones. Notice the smaller, darker die.

Batch 2 APA102 far

Batch 2 APA102 near

Clock cycles

The batch 1 APA102s performed pretty much to spec., in terms of how the data were written to the pixels. The data consist of an initial start frame of 32 zero bits, followed by a 32 bit LED data frame for each LED, then a final frame of clock cycles to allow the data to propagate to the end of the pixel chain. The final frame of clock cycles is necessary because there is a half cycle clock delay between each pixel to allow the data to be evaluated at each pixel. In theory, with the half cycle delay, the minimum number of clock cycles in this end frame is n/2, where n is the number of pixels. We found that 8 was the minimum allowable number of cycles needed for the batch 1 APA102s to perform correctly though.

When run alongside each other, i.e. two Blinkts! attached to a Mini Black HAT Hack3r, the batch 2 variants would take an extra full data cycle to update with the correct data, meaning that they would always be one step behind the batch 1 variants.

Software fix

It turned out that the solution was just to increase the number of clock cycles in the end frame to the magic number of 36 (!?), and everything behaved as expected. Both the batch 1 and 2 variants tolerate this change and behave properly. The only side effect is a slightly slower refresh rate, because the data takes an extra 28 cycles to propagate, although this will be imperceptible to the user.

To cut a long story short, we updated our Python library for Blinkt! accordingly, and if you're experiencing any strangeness with your Blinkt! then it's probably a good idea to update to the newest version of the library.

Here's the commit that fixed the issue, for those who are interested.