Overview

Author Gravatar Image FRANK ZHAO
Good news for Netduino users who have been eyeing the glamorous NeoPixels strips and shapes in the Adafruit shop! We have managed to get NeoPixels working on the Netduino Plus 2 (shown below with a NeoPixel 8x8)
Even though there is lots of example code for NeoPixels for AVR, Propeller and PIC chips, it's a bit of challenge getting these LEDs to work with the Netduino. With the default firmware of the Netduino (any variation, Plus or no), it is not possible to send data to NeoPixels.

The reason is due to the special high-timing-specific nature of the data sent to the pixels. NeoPixels, or WS2812/WS2811, use a single wire protocol that encodes bits as pulses, the time width of the pulses determine whether each bit is a binary 1 or 0. The following is a screenshot from the WS2812 datasheet.
But Netduino runs .NET Micro Framework, which means two important things: your code is interpreted, and there is a garbage collector.

(note: neither of these are over-all disadvantages! In fact, they exist to make your code safer, and makes coding easier)

Interpreted code means that you write your code in C#, but instead of directly being compiled to ARM assembly code (and subsequently, machine code), it is first compiled to "bytecode", and the processor runs an interpreter to read the bytecode, instead of directly executing machine code. The advantage of this is that the code is safer, you can detect errors like overflows, bad memory access, and check object type info. The disadvantage is that it is much slower than directly executing machine code.

(note: from Wikipedia: "Managed code is a term coined by Microsoft to identify computer program source code that requires and will only execute under the management of a Common Language Runtime virtual machine (resulting in bytecode).")

(note: microcontrollers do not normally run interpreted code until you put a interpreter on it, the Netduino is a STM32 microcontroller with a C# CLR interpreter, the BASIC Stamp is a PIC microcontroller with a BASIC interpreter. Arduino is an AVR microcontroller and it does NOT use an interpreter.)
To illustrate my point, I wrote a simple loop in C# that toggles a pin, and observed the time it takes on an oscilloscope:
Copy Code
using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;

namespace Blinky
{
    public class Program
    {
        public static void Main()
        {
            bool pinState = false;

            OutputPort x = new OutputPort(Pins.GPIO_PIN_D0, pinState);

            while (true)
            {
                pinState = !pinState;
                x.Write(pinState);
            }
        }

    }
}
Here is the observed signal on the pin. This is a Netduino Plus 2, which runs at 168 MHz, the other Netduino variations all run at different speed.
It takes 17.6 microseconds to toggle that pin. Now go back to the WS2812 datasheet, and you'll realize that it is impossible to meet the timing requirements using Netduino because the signals needs to be under 1 microsecond.

The other problem is the garbage collector, which runs "once in a while". The garbage collector basically prevents memory leaks when you don't explicitly free memory you don't need anymore. But if it runs while we are pulsing signals to the WS2812, it might extend a pulse and violate the timing requirements. This problem can be solved by making sure that interrupts are disabled when we communicate with the WS2812.

Fortunately, .NET Micro Framework and the Netduino firmware are open source. This means it is possible to write native code functions into the firmware, and call these functions from the managed code.

(note: calling functions between managed and unmanaged code is referred to as interop, you might have come across this term if you tried to use DLLs in C# before)

Our goal is to write a function in C or C++ that will toggle a pin with strict uninterruptable timing, in order to communicate to WS2812 NeoPixels. This function will then be compiled as a part of Netduino's firmware, and we will update the Netduino with this new modified firmware. After that, we should be able to call our new function from within the C# code.
Last updated on 2014-04-05 at 05.20.18 PM Published on 2013-09-12 at 07.32.27 PM