Author: Arnaud

Some time ago we decided that it would be nice to have a name for the Crazyflie expansion boards, a bit like the Arduino shields or the Beagle bone capes. We organized a poll on our website, that ended with cheating so we organized a local vote and flykit won. In second place was the deck. Over time we started liking deck more and more since it fits better with the actual look of the boards. Finally we pushed ourselves to decide on one and we went with deck. This comes from the naming of floor in ships, planes and (more importantly) space ships. We also though we could write a bit about the Crazyflie 2.0 expantion capabilities and the deck architecture. In this post we are forcing ourselves to say deck instead of expansion port, lets see how it goes :-).

On Crazyflie 2.0 decks can be installed both on top and bottom. Each deck we make has a symbol indicating its correct orientation:

deck_conf  Expansion board orientation

 

Lots of signals and functionality has been routed from the Crazyflie 2.0 to the deck port:

Connector_multiplexing

 

The OW pin is used to connect a One Wire memory with a specific data format, this allows Crazyflie 2.0 to know which board is connected and to activate automatically the right driver, so this is kind of plug-and-play. This is currently used to enable the LED ring deck driver. The aim is to develop an API that will allow anyone to easily create decks that would be automatically detected by Crazyflie.

The deck architecture opens lots of possibility. We’ve already made the LED ring that faces down, but it would be possible to make one that faces up as well. In the future we hope to have have ground facing camera, GPS boards, Camera boards. And more than one can be installed at the same time. We also investigate doing bigger expansion board for example to have Crazyflie acting as the brain for a bigger quad.

On the firmware front, we are finishing the merge of Crazyflie 1 and Crazyflie 2 firmware. Currently the source code for Crazyflie 1 and Crazyflie 2 is on two different branches which makes it harder to maintain both of them. We have come so far that we have a working merge that can compile and fly either for CF1 or for CF2. There are loots of cleaning up to be done before it can be pushed though but we are giving a heads up as the changes will affect forks that are doing rebase as well as pull requests.

The Crazyflie 2.0 supports two types of radio protocols out of the box: ESB (Enhanced ShockBurst) for Crazyradio/Crazyradio PA USB dongle compatibility and  Bluetooth LE for mobile devices. All Crazyflie 2.0’s are shipped with a radio bootloader, able to update virtually all the different parts of the firmware running in Crazyflie 2.0. We thought we would do a post to explain a bit further how it all fits together. Even though the Crazyflie 2.0 supports Bluetooth LE, the preferred way is to use the Crazyradio/Crazyradio PA when doing development. Flying via Bluetooth is very practical since there’s no additional hardware needed except for a mobile device, but the Crazyradio/Crazyradio PA has minimal latency, more bandwidth and works easily with computer. This makes it ideal for development and other advanced usage.

(On a side note, some of our products are currently out of stock (like the Crazyradio PA and LED-ring). We have started the next batches, so they should arrive soon. Until then have a look at our distributor page to find our products.)

Crazyflie 2.0 architecture

For the radio of Crazyflie 2.0 we choose the nRF51822. The great thing with this chip is that it integrates a radio compatible with our existing Crazyradio USB dongle as well as with Bluetooth Low Energy. The nRF51 also integrates an ARM Cortex-M0 MCU enabling radio protocols to be implemented directly in the chip. However this MCU is not powerful enough to be used by itself in our quadcopter development platform, so we put a powerful STM32F4 Cortex-M4 168MHz on the side to do the heavy work.

The nRF51 mainly handles radio and power management and the STM32F4 handles all the rest: flight control, expansion port, log, param, etc. As far as the radio is concerned the nRF51 act as a bridge: CRTP packets are received by the nRF51 and sent unmodified to the STM32F4 and the STM32F4 sends raw CRTP packets to the nRF51 that transmit it by the radio. This means that the STM32 firmware is unaware of the physical communication protocol, it can be Bluetooth, Shockburst or something else, it makes no difference it is still CRTP packets. CRTP is the protocol used to control Crazyflie, it encapsulates all commands and messages exchanged between the client and the Crazyflie.

Enhanced Shockburst (ESB)

Enhanced Shockburst is a radio physical protocol implemented in some Nordic Semiconductor 2.4GHz radio chips. In the nRF24 chip, used by Crazyradio (PA) and the original Crazyflie, this protocol is implemented in hardware and we have little control over it. The nRF51 used in Crazyflie 2.0 offers more control on the radio physical packet and ESB since it’s implemented in software instead.

ESB handles ack and retries: The Crazyradio sends a packet on a given channel and waits for an ack. If a Crazyflie receives the packet without error it sends an ack packet. If an ack is received, the Crazyradio can send the next packet. If no ack is received Crazyradio will automatically retry by sending the same packet again. The current implementation will retry to send a packet forever, so all packet are guaranteed to be transmitted as long as a Crazyflie is in range. Packets are sent back by the Crazyflie by adding a data payload to the ack packet. Close to 80 different channel can be used and every packet is sent with an access address, so more than one Crazyflie could share the same channel.

Enhanced Shockburst using the Crazyradio (PA) offers the lowest latency that can be expected. The minimum latency to send a packet is estimated to about 2ms (1ms minimum for USB and 1ms measured latency for the radio at 2Mbps without any retries). With the Crazyflie 2.0 and the Crazyradio PA it also offers the maximum range with 20dBm power output.

For the original Crazyflie there is an implementation of the E-sky RC transmitter protocol. This permits controlling the Crazyflie directly from an RC transmitter. It is technically possible to implement this protocol in the Crazyflie 2.0 nRF51, but it hasn’t been done yet.

Bluetooth Low Energy

In the Crazyflie 2.0 Bluetooth low energy is implemented as a CRTP bridge: CRTP packet are written and read using Bluetooth. This simplifies greatly the implementation, but does not make full use of the Bluetooth LE functionality. It is planned to add more Bluetooth capabilities for things like communicating the battery status and being able to switch ON or OFF the Crazyflie with a mobile devices.

On the nRF51 side the Bluetooth functionality is implemented using the Nordic Semiconductor S110 Bluetooth stack. This stack runs independently of the firmware. Nordic calls this a softdevice and it’s a fitting description of how it works. It almost looks like a hardware device from the firmware point of view as it is not linked into the main firmware.

However we do not currently have the right to distribute the supporting files for the stack, so unfortunately you will have to download them yourself if you want to compile your own nRF51 Bluetooth firmware. To do so you must own a Nordic Semiconductor development kit. Even though some of the kits are pretty cheap, we do not like this situation at all so we are working on solving it. However we made sure that it is possible to compile the nmRF51 firmware without Bluetooth, to avoid the added dependencies. This means that you can still build your own nRF51 firmware to work with a Crazyradio/Crazyradio PA.

Bootloader/firmware upgrade

The Crazyflie 2.0, like the original Crazyflie, is upgradable wirelessly with radio. The radio bootloader has been enhanced to work both with ESB and Bluetooth LE. Both nRF51 and STM32F4 can be upgraded and it is even possible to upgrade the nRF51 Bluetooth stack and bootloader.

Currently the bootloader is working with Crazyradio on ESB. Bluetooth implementation for iPhone and Android is still work in progress. The STM32F4 can also be upgraded via USB and so, for people that does not have a Crazyradio, the first Crazyflie 2.0 firmware upgrade has been released for USB DFU as well as the classical radio bootloader update package.

It seems that many have received their Crazyflie 2.0 now. It is a very exciting time for us, tell us what you think about your Crazylie 2.0 and if you have any problems. We wish you Merry Christmas, a Happy New Year, and a lot of fun with your new Crazyflie 2.0!

Getting started

The instructions and documentation are not really as finished as we would like them to be but we hope it is good enough for everyone to get started. For convenience we have put together a sets of links to find the information easier.

Crazyflie 2.0 – Getting started
Crazyflie 2.0 – Wiki
Crazyflie 2.0 – FAQ
Crazyradio/Crazyradio PA – Wiki
Crazyradio/Crazyradio PA – Windows driver installation
Android App
iOS App

Expansion port

The expansion port is a core functionality and it is important that it is easy to work with. The hardware part of the expansion port allows to easily attach custom electronic to the Crazyflie 2.0, making it a very versatile platform. We want to bring this convenience to the firmware and software development as well. We are not really there yet but would like to share our ideas of how we think, but also as an inspiration and to get valuable feedback.

As you might know we have added One-Wire memories on all our expansion board so that CF2 is able to detect which expansion board is connected. The intent is to automatically initialize the expansion board driver when a board is detected so that the firmware can contain all the expansion board drivers. Other benefits are that the resources easier can be shared but also blocked if there are conflicts between boards.

Currently we are in a state where we have made a prototype of how we want the driver to look like and work. The example/mock-up driver we have put together is for the traffic light hack we have written about earlier. The driver would just declare which expansion board it is supporting and it would be loaded automatically. Also some enhancement to the parameter API would allow for more declarative and short code.

Things will be a little bit slow here at Bitcraze during Christmas period as we are focusing on support and on our families. This is however definitely one or our focus when we start 2015. We will create issues to track this work in the Crazyflie firmware bug tracker, contributions are welcome :).

Bluetooth support

We have also published the rest of the Crazyflie firmware, the nRF51 has firmware, bootloader and a ‘Master Boot Switch’. The STM32F4 has bootloader and firmware. The nRF51 bootloader and firmware supports bluetooth low energy using a proprietary stack from Nordic Semiconductor. This stack architecture should play well with open source software as it is completly isolated from the firmware, it runs on the background and is interfaced with syscall (ie. the same way a program communicates with an OS in computers), Nordic call that a Softdevice. The problem is that the supporting libs that allows to access the softdevice is currently proprietary and we do not have the right to publish it.

Currently you can compile the nRF51 firmware in ESB (Enhanced Shock Burst) mode (ie. to communicate with Crazyradio) out of the box. To compile with BLE support you should download the S110 Softdevice and nrf51_sdk from Nordic Semiconductor and this requires you to have one of the Nordic kit. We are in communication with Nordic to fix this situation and will keep you updated. One nice thing about the nRF51 is that the radio is well documented so one way or another this is going to be solved: either we can distribute supporting files for the Nordic stack, or we make our own stack ;-).

Virtual machine

The virtual machine for the Crazyflie 2.0 is on its way, but as we have run into some problems, it has been delayed a bit. Now most of the problems has been fixed and we hope to release it any day now.

The workload is still huge and now it is starting to take its toll, we are really looking forward to a short vacation around Christmas! But even though we will be off, we will still be checking the support forum. Meanwhile we are doing our best to continue to march on and we managed to write some new documentation and also pushed some new releases. Please have a look at last week post which we have updated and will continue to update as we push them out.

Unbalanced CCW propellers

After receiving the final production version we have found that many of the CCW propellers (not marked with an A) shipped with Crazyflie 2.0 are a bit too unbalanced. This might cause vibration that will affects the flight performance. To get the best flight performance the propellers, especially CCW, might need to be balanced. Balancing the propellers is pretty easy, all you need is a needle and some office tape. We have put together a step by step guide on how to balance them and also updated the general assembly instructions to include balancing. We are currently investigating this with the propeller manufacturer and we will keep updating about it. If you have any questions or concerns drop by our support forum.

Firmware update

Yesterday we released a new version of the Crazyflie 2.0 firmware. This version fixes an issue that was triggered by the motor PWM frequency interfering with the one of the voltage regulators causing the Crazyflie 2.0 to shut-off if the thrust increased too fast. Doubling the PWM frequency fixed this issue completely. We also adjusted the gyro and accelerometer low pass filters a bit to handle vibrations from unbalanced propellers a bit better.

Crazyflie 2.0 can be updated with Crazyradio using the latest version of the Crazyflie client, with the update zip. Documentation of the update process is on the wiki. We also made a USB dfu update zip for people that do not have the Crazyradio. Instruction for the DFU is in the README.txt file in the zip file. In the future it will be possible to update Crazyflie 2.0 with the Android and iPhone client as well. This time around the update is for Crazyflie 2.0 only but the plan is to merge both Crazyflie firmware together in order to release everything at the same time.

New Android release

The Android client is also going forward thanks to Fred. This evening we are releasing an update that enhance the GUI and allow the app to run full screen on Android 4.4+. The update is going to be released on the play store.

android client 0.2

 

Feedback

We are really eager to hear what you think about the new Crazyflie 2.0, the instructions and everything else around it. So please drop by our feedback topic in the forum, or post your feedback here, to let us know what you think.

We kicked off the Crazyflie 2.0 production about one week ago and we are still working hard on ensuring the best possible quality of the production. To do so we have a test specification/plan that is executed on all the produced units. Making test protocols is something we have had some experience of in our former day-jobs, but it is always a challenging and time consuming task. However the reward is great, good tests ensure good quality to the end user. The higher the production quality is, the happier everyone is, and the more time we have to do other things like developing new features :-).

The tests runs on an assembled PCB and first thing to verify is an electric test checking that voltages and current consumption are normal. Then the board gets programmed.

For the original Crazyflie, the testing was heavily based on the power on self-test. This is still the case with the Crazyflie 2.0 which allows to make sure that everything is working in factory as well as every time a Crazyflie gets powered (this power-on-self-test is the first thing to run before assembling the Crazyflie).

For Crazyflie 2.0 we also needed to create new tests for the expansion port. First of all we needed to check that the connector is mounted properly and that the pins for the expansion port are able to pass though the PCB. Secondly we also have to test the electrical connectivity. For this we have created a special expansion test board which, allows the Crazyflie to self test all expansion connections. This board is detected by the 1-wire memory which is mounted on the test board. When it is inserted it will automatically trigger the test code which checks all connections.

To do tests on a limited budget you will have to get creative. E.g. to do output power and frequency test for the radio communication on the Crazyflie and Crazyradio we are using the rfExplorer. It is a neat cheap 2.4GHz spectrum analyzer that we control from Python which can measure the radio frequency and output power. ICT or bed of nail tests are also very expensive and instead we use test fixtures with pogo-pins to test the electronics. It doesn’t get as extensive as a net checking ICT but with some clever testing using the software most components can be tested anyway. We have added some photos of the original Crazyflie test rig to this post. We will soon travel to the Seeedstudio office in Shenzhen in China and we will take photos of the new production and test equipment.

One of the nice new functionality of Crazyflie 2.0 is the Bluetooth 4.0 low energy (BLE) connectivity. In Crazyflie 2.0 we are using a radio microcontroller chip from Nordic semiconductor, the nRF51822. This radio chip allows us to keep compatibility with the existing Crayradio (and future Crazyradio PA), and to support BLE connectivity as well. The radio chip is a bit bigger that the one we used so far, and with the Power amplifier, we end up having the radio taking more space on the PCB:

The extra footprint is offset by the fact that we are now using smaller sensors and that the nRF51 is also handling the power management thus freeing pins on the main CPU.

The main usage of BLE will be to fly Crazyflie from a compatible mobile device like an Android phone or an Iphone. This could be used both to ‘just fly’ or to develop crazyflie control apps using the mobile phones capabilities. For example the phone camera could be used to detect and control Crazyflie autonomously. We have prototyped the BLE communication both on the existing Android client and for IPhone. The plan is to provide basic apps for the Crazyflie 2.0 release so that the copter can be flown from a mobile device out of the box. So far we have got the copter to fly from both Android and IOS:

We are not planning on implementing any BLE support for the PC client, so Crazyradio is still the main way to communicate with Crazyfle. It is possible to have BLE on PC but it would require a major effort to get it to work for Linux, Windows and Mac (there is no cross-platorm Python BLE lib as far as I know. If there is some please tell me in the comments!). Also Crazyradio is lower latency and has an higher datarate which makes it better for flying and communicating with one or many Crazyflie 2.0 from a PC.

We are also implementing BLE in the bootloader. This means that it will be possible update the Crazyflie 2.0 firmware from both a PC or a mobile device.

Technically we are using the Nordic Semiconductor soft device BLE stack. The stack runs a little bit like an operating system, behind and independently of the firmware: the firmware is not linked to the stack. This will make things a little bit easier to have an open-source firmware even though the nordic bluetooth stack is closed. Another nice thing about the nordic chip is that the radio peripheral is well documented so implementing open source stacks in the future is potentially possible.

Practically we where originally planning to have two modes for the firmware: one Crazyradio and one bluetooth mode. However the new release of the Nordic BLE stack allow to mix BLE and Crazyradio at the same time. So we are working on having a seamless connection procedure between Crazyradio and BLE: when starting Crazyflie 2.0 it will be accessible both via BLE and with the Crazyradio. When connected the unused mode will be disabled until disconnection. Also the name of the copter will be communicated both in BLE and Crazyradio mode and can be changed by the user. This will help a lot people having more than one Crazyflie (us first!) to differentiate them.

As we said in previous post, with Crazyflie 2.0 one of the focus has been on enhancing the current Crazyflie platform. The radio range and power is one of these things that is good enough on the current Crazyflie but that could be made much better. So on Crazyflie 2.0 we added a +20dB power amplifier that increase the output power up to +20dBm.

The logical move was to add a similar amplifier on the Crazyradio dongle and that is what we did. We made Crazyradio PA (power amplifier) and we intend to release it with Crazyflie 2.0

The output power is now of 20dBm for Crazyradio PA, which will dramatically increase the control range. Even though Crazyflie was originally intended for indoor use, Crazyflie 2.0 is pretty capable outside, mostly with the expansion capability that could allow to add things like GPS, so the extra range could be put to use. But maybe the biggest advantage is indoor where Crazyradio is now playing equal with Wifi in term of TX power. This increases the link robustness and allows for flying in other rooms (could be useful with a powerful FPV for example).

Preliminary tests show much better performance compared to the first Crazyradio and Crazyflie both indoor and outdoor. So far, we mesured a stable link two floors down about 20m away indoor and about 150m outside range (the uplink has been tested up to 450m). Of course we are continuing to work on it and final specs will come later.

As for the radio dongle mechanic we have changed nothing: the connectors and LEDs are still at the same place. This was made possible by using smaller SMD components and so existing 3D-printed cases for Crazyradio still work for Crazyradio PA.

While designing the Crazyflie 2.0 one of our focuses has been enhancing the current Crazyflie functionality. As a flying development kit the current Crazyflie already has a JTAG debug port that allows to flash and debug the STM32F1 microcontroller. The design uses a standard ARM 10-pins cortex debug connector. The connector is shipped with the Crazyflie control board, but it is not soldered. So before doing any advanced debugging with the Crazyflie the user will have to solder the debug connector (it is always possible to flash new firmware using the radio bootloader).

With Crazyflie 2.0 we wanted to make it easier to debug it out-of-the-box, without needing to solder. But the issue is that standard debug-connectors tend to be fairly large, so to fit the connector on the board we used a different connector that connects to an adapter board.

Aside from having a reset button, the adapter board will have 3 JTAG/SWD connectors:

  • 20-Pins HE10 ARM JTAG with 2.54mm spacing: The most commonly used connector
  • 10-Pins ARM Cortex with 1.27mm spacing: Used in some modern ARM board, the same as the current Crazyflie
  • 6-Pins SWV with 2.54mm spacing: Compatible with the connector present on ST Discovery boards

The smaller 6-pin connector connects to the Crazyflie 2.0 for flashing and debugging of its 2 MCUs: The STM32F405 and nRF51822. The connector for debugging the STM32F4 is mounted on the Crazyflie 2.0. For the nRF51 we are still working to get a solder-free solution using the same cable/connector on the debug-adapter. Why not just put two connectors, or one big with all the signals on the Crazyflie? There’s just no more space on the board. The connector looks very small, but when you bring the footprint into KiCad it’s like parking a minivan in your bedroom :-)

Since all the connectors are wired together the board can also be used in a number of other combinations, like using it as a 20-pin to 10-pin Cortex JTAG adapter or any other combination of its connectors.

Early on in the Crazyflie 2.0 design we decided on using a double-MCU architecture. The main reason for this was to add Bluetooth low energy (BLE) to the platform to permit new use-cases like controlling the Crazyflie 2.0 directly from a mobile device. It just so happens that Nordic semiconductor some time ago released a chip that perfectly matched our requirement: the nRF51822 can run a BLE stack and is still compatible with the nRF24Lx1 that we are using in the current Crazyflie and Crazyradio. This nRF51 chip contains an ARM Cortex-M0 microcontroller, powerful enough to implement the radio functionality and power management, but not powerful enough to run a fully featured Crazyflie. The resulting system architecture can be seen here:

Crazyflie 2.0 system architecture


The nRF51822

The two main tasks for the nRF51 is to handle the radio communication and the power management. We use the radio for both CRTP and BLE, but the hardware also supports other protocols like ANT. The CRTP mode is compatible with the Crazyradio USB dongle and it provides a 2Mbit/seconds data link with low latency. Our initial tests of the Crazyflie 2.0 implementation shows that the latency of the radio link is between 360us and 1.26ms, at 2Mbps without retry and a packet size of respectively 1 and 32 bytes. The main benefit of the CRTP link with the Crazyradio is that it’s easily implemented on any system that supports USB host which, makes it the first choice to hack and experiment with the Crazyflie. To that we have added BLE, mostly with the use case of controlling the Crazyflie 2.0 from a mobile device. The idea is of course to be able to fly easily and on the go with BLE, but we also see lots of opportunities for fun hacks and experimentation with mobile devices. One idea we came up with is to be able to place the mobile device up-side-down on a table and to autonomously hover the Crazyflie above it using the camera on the back.

One of the other particularities of the nRF51 chip is that it was designed to run from a coin battery, which means that it is pretty well suited for low energy operation. So we decided to give the nRF51 the responsibility for power management as well. In the current version of the Crazyflie we have a small chip handling the ON/OFF button and cutting power to the complete board. On Crazyflie 2.0 the button is connected to one GPIO pin on the nRF51 and power to it will never be cut, it just goes in “power down” mode. This permits to reproduce the current ON/OFF functionality and the button can be used for more function like long press and double click. We have also added the possibility to wake up the system from one of the pins in the expansion connector, which allows wake-up by an external source. It also adds more possibilities like waking up the system at regular time-intervals to perform some function.

The STM32F405

We also updated the main MCU to a fast Cortex-M4 with a lot of memory. The CPU power is not a big limitation in the current Crazyflie, but the memory could become a limitation if users would like to implement new functionality that needs a lot more memory. We ran into this problem when we were trying to implement SD-card support for logging, as this required too big buffers. The new MCU has 196kB of RAM which should be enough for anyone (famous last words…). The MCU power will also allow for more computationally intensive algorithms, the first that comes in mind is sensor fusion between inertial sensors and the GPS data.

This amount of memory and computational power also open the doors for new things: the STM32F4 has a Memory Protection Unit, which allow to run tasks in a protected environment and intercept bugs before they can crash the full Crazyflie control firmware (like what  happens on PC operating system). One use of this could be to to allow for “user code” that runs in a protected environment to allow easier development of advanced behavior. As always this kind of functionality spawns lots of crazy ideas :-) The leading one is to run a Lua interpreter in such a protected task. If there was a good API that could be used from Lua you could imagine lots of fun stuff to do. Like adding a new board with sensors, reading them and then controlling the Crazyflie from that, without having to go into the actual control algorithms or risking to crash the firmware. This is of course still a dream but at some point in the future we will definitely give it a try (when we have the time for it that is :-) ).

Inter-MCU communication

Working with a system with multiple MPU is hard. As embedded system developer we know that, so we designed the Crazyflie 2.0 with at least some idea of how to limit the problems related to debugging two inter-dependent MCUs. We have defined as precisely as possible the responsibility of each MCU, which permits to develop and test things independently:

  • The nRF51 is responsible for
    • ON/OFF logic
    • Enabling power to the rest of the system (STM32, sensors and expansion board)
    • Battery charging management and voltage measurement
    • Master radio bootloader
    • Radio and BLE communication
    • Detect and check installed expansion boards
  • The STM32 is responsible for all the rest, among other things:
    • Sensor reading and motor control
    • Flight control
    • Telemetry (including the battery voltage)
    • Additional user development

The nRF51 will act as slave and the STM32 as master. Using a radio bootloader it will be possible to wirelessly update the firmware for both MCUs.

We will write more details and post photos in the following weeks. Do not hesitate to tell us what you think about it, we appreciate all the feedback we get and we already have a couple of verification that we made after previous feedback (ie. radio latency and magnetometer usability).

A couple of weeks ago we found the NeoPixel ring from Adafruit at a local shop, we had to attach this neat board to our copter and see what cool effect we could make with it. The ring has 16 RGB LEDs that can be driven independently with only one data wire. The LEDs the Neopixel contains are called WS2812.

This post is describing the development of a WS2812 driver for the Crazyflie. A later post will show the usage we did of it (fairly limited in comparison of the seemingly endless possibility, as usual we have more ideas than time to execute them :-).

The WS2812 LED

First of all we needed to see how to control the LEDs. The protocol used by the WS2812 is quite simple but special. All LED on the ring have a data input and a data output pin in a chained manner. Colors of the LED is send over the Data line to the first LED that will save it internally. When sending a second color the first LED will send the saved color to the second LED. And so on, by sending 16 color data we can set the color of all LEDs of the ring independently. Colors are sent as 24 bits (8 bits per component).

Up to there nothing is really peculiar, the system is pretty neat and allows to control a lot of LEDs with just one IO. The problems comes with the Bit encoding:

ws2812_format

Bits are encoded with pulse width: a short pulse means 0 and a long pulse means 1. The bitrate is of about 800KHz and the tolerances on bit timing is pretty tight. As there is no hardware peripheral dedicated for this (on common microcontrollers), this bitstream needs to be implemented either by bit-banging or by being a bit creative with the peripheral we actually have at our disposal.

Driver implementation

Adafruit did implement a driver for the WS2812 for Arduino, this is a software implementation that uses the CPU to implement the signal. However at that bitrate a software/bit-bang implementation have to be timed carefully and the easiest for that is actually to implement it in assembler. Arduino runs on an AVR processor and these processor are very predictable: each instruction runs in a specified number of clock cycle which makes it possible to implement a timed loop like the one of Adafruit. However this becomes impractical on bigger CPU that implements caches and other optimization that makes it really hard to predict how much cycle each instruction will take.

The Crazyflie runs a STM32F103 based on an ARM Cortex-M3. This is just complex enough to make the ASM-timed loop impractical: The CPU core runs at 72MHz but the flash is slower so a simple cache memory is inserted in the middle and depending of the state of this cache it may take from 1 to 3 cycles to execute an instruction. There is an even bigger problem: a CPU timed loop requires to stop all interrupt and to have the CPU running exclusively on updating the WS2812. We cannot allow that on the Crazyflie that require a 250Hz control loop to stay (controllably) airborne.

We asked Google to see if someone already came with a solution and actually someone did. The Elia’s Electronics Blog posted a neat, well documented, solution using the STM32 Pulse Width Modulation (PWM) capabilities of the STM32 to generate signals that the WS2812 understands. All we needed was a timer/pwm output then. It happens that we have one timer1 output on the Crazyflie extension port:

crazyflie_neopixelring

This is only 3 wires: VCOM for the battery voltage, GND and the timer output.

I started porting the Elia’s code to the Crazyfle. The only free timer we could easily use was different and much more complex than the one Elia uses. So part of the frustrating implementation was to figure out WHY the signal was looking weird on the scope! Finally after an hour or so the code was working:

IMG_20140411_202251

Enhancements

Now that was not quite enough. The driver is using the PWM to generate the 1’s and 0’s pulse width and the DMA is used to feed the bit width independently of the CPU (so that it can do something else, like controlling the copter attitude…). It requires all the 16 LEDs data to be written in the memory buffer before starting the DMA. Each LED has 24 bits color data and each bit will be encoded as 16bit pulse length for the timer. It means that the full ring will take 768Bytes in RAM. It sounds small but its a bit too much for us and, most importantly, it does not scale: if we want a second ring the ram requirement will double.

To fix this I implemented two things: An easy one is that the DMA can do some type conversion and one of these is that it can read 8 bit in memory and write 16 bit in the peripheral. This allows to store only 8 bits pulse width in memory and so divides by 2 the memory requirement, but it still doesn’t scale.

The fix to scaling is double buffering. The STM32F103 does not implement DMA double buffering as such but what it has is close enough: circular DMA with half-transfer interrupt. The idea is to load the 2 first LED in a buffer and to start the DMA for 42 bytes in circular mode. When the DMA has transferred the first LED it triggers the half-transfers interrupt which allows the CPU to replace the first LED data by the 3rd. When the 2nd LED is transferred the transfer-complete interrupt is triggered by the DMA and the CPU fills in the 4th LED in place of the 2nd one. The DMA roll-over at the beginning of the buffer and sends what is now the 3rd LED data. This continues until all the LEDs has been  sent. This solution scales: it requires a 42 bytes buffer for as many LED as we want!

Conclusion

All that process was not really simple. However the result is simple, now the only thing required to control a Neopixel ring in the Crazyflie is:

 

#define BLACK {0x00, 0x00, 0x00}</span>
static uint8_t color[][3] = {{40, 40, 40}, {32, 32, 32}, {16,16,16}, {8,8,8},
                             {4,4,4}, {2,2,2}, {1,1,1}, BLACK,
                             BLACK, BLACK, BLACK, BLACK,
                             BLACK, BLACK, BLACK, BLACK,
                            };

/* ... */
ws2812Send(color, 16);

And it will run nicely without interrupting other tasks like control and communication. Replace 16 by 32 to control 2 Neopixel rings. The current implementation has been pushed in the crazyflie-firmware neopixel_dev branch (still require some clean-ups!). Actual implementation is in ws2812.c and neopixelring.c.

neopixel_flying

The only problem left is not software: At the end of the battery life, the voltage is not enough to fully lit the blue LED. That make all white look orange-ish. The only way to fix this problem would be to step-up the battery voltage higher then the forward voltage of the blue LED. Though it works well enough without that.

Stay tuned for a following post about actual usage of the ring.