On the bitcraze blog, Arnaud Taffanel posted an entry about a way to drive Adafruit’s NeoPixel Ring off the crazyflie’s STM32F103 ARM Cortex MCU. Obviously there were some technical hurdles to get over before they could implement support for driving the NeoPixel’s WS2812 LED chain. Adafruit’s well optimized drivers work great on Arduino but use the CPU for signal timing which doesn’t work so well on the more complicated crazyflie MCU. Not to mention the CPU can’t spare precious cycles on non-essential work like flashing LEDs when there’s critical duties (ie. flight performance) to attend to! Fortunately they found a solution using the STM32’s pulse-width modulation to create a signal the WS2812s understand and even more fortunately, they had a free timer output on the crazyflie expansion header to devote to the signal. Now, most of this is totally over my head (after all, I’m a layman with mostly software knowledge) but fortunately Arnaud detailed the solution quite well in the blog post and Marcus Eliasson posted a follow-up on it about a week later. Since the Bitcraze boys so graciously branched the crazyflie-firmware repository to implement the NeoPixel driver, I decided I could maybe accomplish this hack, so I set out to do it.
According to Adafruit’s website, the NeoPixel 16 LED ring weighs in at 3.03g. As it turns out, that’s incorrect. When I weighed it, I found it to be just over 4.0g. That’s nearly the entire payload capacity of the Crazyflie! I attached the ring and flew around a bit. I very quickly realized the drastically reduced flight time and sluggish flight performance was bad enough to cause me to abandon the project. I decided I’d look at other modding projects to pursue. Eventually, after poking around the Adafruit store a while, I found they actually had NeoPixel ring with 12 LEDs. The specs for that one said it weighed 3.3g. I went ahead a bought one. The 12 LED ring weighs about 3.4g according to my scale, but that’s still much better than the 4.0g of the 16 LED ring. It also made a significant difference in both flight time and performance. I decided I could still pursue the LED ring modification!
I set about mounting the rings to the Crazyflie. For both the 16 pixel and the 12 pixel ring, the µUSB socket gets in the way so I figured that had to be one of the four mount points. I decided I’d just use some of the double-stick, battery mounting tape that came with the kit. Actually, I had a roll of my own but it was basically the same stuff. Fortunately, it seemed I could stack two pieces of tape to reach the height of the µUSB socket, so that’s what I did for the three other mount points on both of the rings (one at a time, of course). The mounting tape held the rings surprisingly well, so I was happy with the setup — even though I was at first afraid it wouldn’t be permanent enough. The pieces hold well enough to be semi-permanent. They’re strong enough to hold the ring on even after multiple crashes and they’re small enough to peel off when I wanted to try a different sized ring. Keep in mind, at this point I haven’t wired up the rings yet, they’re just inert (won’t light up) and mounted for experimental flight and data collection only.
To better understand the impact of the weight of the ring, I ran some tests by watching the battery discharge rate while hovering at a relatively stable altitude. There wasn’t much “flight” during these test, only minor attitude and altitude corrections so the discharge rate remains pretty stable. The following graphs were created with CFClient UI and demonstrate pretty clearly the impact of the rings on performance. The top graph is the unladen Crazyflie, followed by the NeoPixel x12 payload and lastly the NeoPixel x16 payload. I imagine the discharge rate will be a bit more when the rings are actually powered.
The driver Bitcraze created was made for a 16 LED ring but after looking over the class, I decide I could re-tool it for 12 LEDs pretty easily (even as rusty as my C skills are). Fortunately, I already knew how to compile the firmware on my Mac so I simply cloned out the HEAD of the master branch from GitHub and merged the neopixel_dev branch into it. I made a few easy tweaks to the code and after compiling, and flashing the custom firmware, I temporarily wired up the ring and proceeded to set the ring effect parameters in the CFClient UI. I was giddy when I got both the color ring and white spinner to show up. It all just worked. The Bitcraze boys had done a good job making this mod easy — even when I diverged from the hardware they had used!
In my next installment on this mod, I’ll detail what I did to get the hardwire wired up, the firmware built and flashed, and the neopixel.c class doing what I want. In a later installment, I’ll write about the hacking in support for cycling through the LED effects via the controller.