Persistence of Vision with APA102
05 January 2019 at 8:27 pm
Back in April 2018 I made a board to play around with a few things I’ve wanted to learn. I added LiPo charging, a voltage boost circuit and the cheapest STM32 microcontroller I could find that offers USB connectivity. The main idea was to use this to make a Persistance Of Vison (POV) setup to play around with. I only had time to test the first iteration eight months later, but the second iteration is now up and running.
I’ve only just gotten it working, but it shows great promise already! The first version had several bugs (as expected), but none so critical that they couldn’t be worked around. I got the LiPo charging and boost working on first try, but it didn’t work just as expected when plugging in USB. To improve on this, I added a switch IC (TPS2113A) that would toggle between USB and battery as needed, but I didn’t read the fine print so this circuit started oscillating and failed. I now have a much simpler and completely fool-proof solution to this using a clever MosFet switch. The shape of the first PCB made it hard to spin, so I fixed also that in the second version.
Why NeoPixels can’t do POV
I’ve used ws2811 and ws2812 (often referred to as NeoPixels) programmable LEDs before, but they’re not suited for Persistance Of Vision applications since the refresh is too slow.
Incorrect refresh produces a dot pattern
NeoPixels also have a lot of issues since they require very precise timing. This makes it very hard to use them with anything that also requires a wifi connection or anything that could disturb the timing. The APA102 is different. It has a dedicated clock channel that you can run at any speed so it will work with any computer, also Rasberry Pi and other things that can’t offer precise timing. This requires an extra pin, but that’s a very cheap price to pay to save all the hassle with NeoPixels.
The APA102 is also called DotStar or SuperLed and it comes in two form factors. The most common one is the 5050 (5x5mm) package, but it also comes in a 2020 (2x2 mm) version that offers the same light intensity in a smaller and cheaper package. The refresh rate of these are super-fast so they’re well suited for POV applications when done correctly. A big thanks to Tim for his great writeups on all types of programmable LEDs! They’ve been of great help throughout the years.
POV with APA102-2020
If you’re working on an Arduino-like platform, you can probably find a good project to start from. There is however no pre-made library for the STM32F0. I found a good place to start with this code, but the setting of max brightness is done incorrectly here so it won’t work. The LED can be dimmed by adjusting the RGB channels, but you also have a power saving feature in the chip that you can set from 0 to 31 (32 steps). For POV, we need the LED to always be on and to do that, we set it to maximum brightness (31). I didn’t fully understand how the first lib did this wrong, but after searching Github for apa102 and disregarding platform I found this code doing it right. Re-reading the datasheet I found that you can easily simplify this quite a bit and ignore storing the INIT and GLOBAL bits since these will always be 0xFF and I came up with this simplified solution.
With full brightness, all LEDs show as a continuous line.
The only thing that is STM32 specific here is the sendRaw-method. Replace this with how the platform of your choice does SPI and you can use it with Atmel AVR, Microchip, Parallax or whatever your favorite MCU is. The code will also work with the larger APA-102 LEDs. The Gist displays a beautiful rainbow pattern thanks to the super-smooth color methods used in many of Adafruit’s libraries.
Next up is displaying text and images, while I wait for the third iteration of the PCB to be fabricated. There’s loads of great tools for converting images to C arrays, but I’ll make some custom code for displaying text also. The third iteration will have 100 pixels as well as an accelerometer/gyro combo so it can be used for POI-applications in addition to POV. For now I’m happy with storing data in the microcontroller itself, but I’ll eventually look into adding a simple Bluetooth wireless transfer to a Flash Memory chip so the device can be updated without USB or STLinkV2 programmer.