Adafruit NeoPixel?

I’ve been playing with this library http://developer.mbed.org/components/Adafruit-NeoPixels/ to drive a adafruit NeoPixel stick (8 LEDs). I got it working great on a LPC1768.

I can’t seem to get it to work on the mbuino. I have updated the burstSPI library that it uses and it states that it is LPC11u24 compatible. I have created a mbuino project and a separate lpc11u24 project and tested both. I am driving the mBuino and LEDs with an external EXTECH power supply at 5+V.

The first LED in the program lights but that is all. I even put some status led statements in it that can cycle LED1 on the board on and off and they don’t cycle.

I’m wondering if anyone has gotten the mbuino to work with the above library.

Later I will create a smaller program and post it here.

thanks

Eric

Here is the program

It is supposed to light up 8 leds as white
wait 1000ms
then clear the pixel buffer and light the 5th pixel as blue
wait 1000 ms
start over

I am trying to toggle led1 but that led is not flashing.

When I run this I get all white LEDs that stay on

If I reverse the instructions I get the 5th one as blue and that stays on

I suspect that I need to set the default Protocol protocol=PROTOCOL_800Hz paramter to PROTOCOL_400Hz from the neopixel.h file in this call but for the life of me I haven’t figured out the syntax. I am pretty much a cpp newbie.





```cpp
#include "mbed.h"
 #include "neopixel.h"

// This must be an SPI MOSI pin.
 #define DATA_PIN P0_21

// this program has the number of LEDs fixed at 8 for the Adafruit NeoPixel Stick

void setPixel(neopixel::Pixel * buffer, uint32_t index, uint8_t red, uint8_t green, uint8_t blue, uint32_t length)
{
    if (index >= length ) {
        return;
    }
    buffer[index].red = red;
    buffer[index].green = green;
    buffer[index].blue = blue;
}

int main()
{

    DigitalOut led1(LED1, false);

    // Create a temporary DigitalIn so we can configure the pull-down resistor.
    // (The mbed API doesn't provide any other way to do this.)
    // An alternative is to connect an external pull-down resistor.

    DigitalIn(DATA_PIN, PullDown);

    // The pixel array control class.

```cpp]    neopixel::PixelArray array(DATA_PIN);[/code


    uint32_t numLeds = 8;
    neopixel::Pixel buffer[numLeds];
    int waitMs = 1000;

    while (1) {
        led1 = 1;

        // All LEDs white
        for (int i = 0; i < numLeds; ++i) {
            setPixel(buffer, i,0x12, 0x12, 0x12, numLeds);
        }
        //display
        array.update(buffer, numLeds);
        wait_ms(waitMs);

        led1 = !led1;
        // All LEDs off
        for (int i = 0; i < numLeds; ++i) {
            setPixel(buffer, i,0x00, 0x00, 0x0, numLeds);
        }
        // Turn on blue for the 5th LED
        setPixel(buffer, 4, 0x00, 0x00, 0x12, numLeds);
        // display
        array.update(buffer, numLeds);
        wait_ms(waitMs);
    }
}

I bet you I know what the problem is. We have fixed an error with the stack and waiting for mbed to accept the pull request. Maybe another week till this is publicly available.

This bug causes the board to crash.

Gus,

I hope that is the case. I really want to be able to use the mBuino for some projects (POV first) that use neopixels and will be moderately complex code wise. The footprint of the physical device and the price are unbeatable if it works.

Eric

I took a look at this a while back, I ended up writing my own version of the LED library with a few more features, the long term aim is to support 5 rows of 100+ LEDs and then display and animate text, but the core code for pushing the data out ended up being very similar. It was using the same busrtSPI library to drive the data line.

It would run fine, I could see the data coming out at the repeat rate I’d set on the scope.

So no fundamental problem with the SPI code and the NeoPixel library is fairly simple so that shouldn’t cause issues.

The issue I ran into is that the neoPixel worst case voltage threshold for an input to count as high is above the mBuino GPIO output voltage, the data wouldn’t reliably get past the first LED, when it did some pulses got skipped so and the data and timing get messed up.
I’m sure there is a lot of part to part variation so most of the time it’ll probably be ok but watch out, if the first LED on the chain is at the upper end of the range it may not quite work right.
The timing is too fast to just use a pullup to get the extra voltage so the whole thing got put on hold until I get around to adding a 5V buffer to the data line and then I got too busy to play.

AndyA,

Dang. Thanks for the info. I’m not skilled enough (yet) to write my own library. I wonder if a level shifter can help? But at some point the cost and complexity of more components would force me to look at other options.

I’ve gotten the library I reference in my OP to work reliability with an NXP LPC1768 but putting that large device on a platter spinning at ~3,600 RPM would be challenging due to size and weight. Also the form factor is pins and not through holes solder connections.

I can go the arduino route and I know there are a lot of cool POV demos using AVR devices. I’m just trying to focus on ARM right now and I really hate the IDE for arduino. But I know I can make that work.

Hummmmm! Need to ponder more design decisions.

I really like the mbed approach (mostly)…

thanks all

Eric

I’ve not seen anyone else mention problems with driving neoPixels so I think it was mainly bad luck on my part to get a part at the end of the tollerance range. It only matters for the first one in a chain, after that they re-generate the signal so if the first LED is reliable they will work after that.
And it shouldn’t cause any problems to the mbed CPU, if the LED on the mBuino isn’t flashing then something else odd is going on.

The way the mbed power is done on most of the boards means that the CPU is running at about 3.1V not 3.3. The current is minimal so you’ll get about 3.1V on an output.

The LED datasheet claims they need 0.8*Vcc or 4V (assuming a 5V power source) to count it as a high. You can drop that a little by running off a lower voltage (I should try that, I have a good variable power supply, if I get a chance I’ll ramp it down later today and see if it springs to life.)

I’ll try and have a quick look at getting it going later today and if I can verify something that works I’ll let you know so you can try it on your setup.

AndyA

Thanks. I will try the lower voltage trick as well. That will be about all I can get done today with life getting in the way of fun projects.

Later this week I will try using a level shifter as well. And of course when the new version of the mbed library for mBuino is released will try that.

Cool stuff

Eric

I had a chance to have a quick look.

Using the latest released versions of the burstSPI library and the mbed library the code was stable and I got exactly the same timings out on the SPI pin using the mbuino as I did running the same code on an LPC1768.

The mbuino SPI output voltage was about 0.3V lower than the LPC1768.

If I drop the LED supply voltage down to 4V so that the mbuino output is within the 0.8*Vdd that they specify then I get the correct number of LEDs light up.
The colours are completely wrong but there is a fair chance that that is a software issue on my side, the basic communication seems to be there.

I’m certainly not seeing the software crash you were getting. Could you have been getting a voltage drop when the NeoPixels turn on that caused the crash? They do pull a fair amount of current.

BTW one debugging tactic I use rather than just flashing an LED on and off is to define all 7 at once:

BusOut LEDs(LED1, LED2, LED3, LED4, LED5, LED6, LED7);

You can then display a number indicating where the code is by simply assigning LEDs a number between 0 and 127. Or you can do LEDs = LEDs + 1 in a loop to get a count rather than just a flashing light (++ and +=1 don’t work with a BusOut).

AndyA

Thanks for the great information. I did not get a chance to try this last night. I hope I can on Wednesday. I like the 7 LED scheme for debugging as well.

Eric

AndyA

Okay a reduced voltage worked. 4.2 to 4.5 V seems to do the trick. If I push it to 4.7 or so the leds stop cycling. I may put a level shifter on this to see what happens. Thanks so much for your feedback.

Eric

I got my version of the LED library working.

No documentation included at this point but it’s fairly simple if you want an alternative library to use. The end result should be identical the the PixelArray library.

The driver is here:

And a program that uses it to move a glow up and down the LED strip is here:

1 Like

And as an FYI I need to keep the LED supply voltage at 4.3V or less for it to work reliably so there is definitely some unit to unit variation going on.
At 4.4 the whole chain starts to flicker like crazy as bits start to drop out at random.
At 4.5 it stops updating completely.

I have the WS2812B version of the LEDs, 4 pins rather than 6.

Any reason this wouldn’t work with other WS2811/WS2812-based LEDs, such as the RGB-123?

http://rgb-123.com/product/88-8x8-rgb-led-matrix/

I had the panel above (or at least a subset of the pixels) running off 3.3v on an Espruino board as a glowing/fading light for my jack-o-lantern this year. Would love to get it running off mBuino, as that would make the overall project even smaller, and probably slightly lower power.

Thanks all,

I’m using the WS2812B 4 wire ones and will have 4 boards of 8 LEDs chained together. I have other 5 volt cards to drive at the same time so I will be supplying voltage form 3 AA batteries (~4.5 to 4.8ish when full). I want to run with new batteries so that the POV platter can be used for as long as possible.

Once I test the level shifter with this I will report back. I was able to drive the leds with a 1ms delay between displays with the lower voltage so I’m thinking this is going to work for a POV display.

Thanks for everyone’s help and suggestions. Using a mBuino for this now is great due to the size/weight/cost of the device.

wOOt!

Eric

Other than the voltage issues mentioned above I can’t think of any reason why it wouldn’t work.

If you have a grid pattern then you may want to define the pixel data as a 2 dimensional array to make it easier to address pixels. As long as they are wired in order and you pass the driver the start pointer and total length it will work fine.

Another trick I’ve played with is having two buffers and switching between them each frame, that makes animations based in the current state a lot easier.

@ AndyA - Thanks…I will probably try to get it working with the existing code/lib first, since I’m very much a noob when it comes to C++.

If I can get that working, then I’ll look at the 2 dimensional array idea. One potential challenge with that is that the RGB-123 matrix is wired in a zig-zag fashion, like so:

0 1 2 3 4 5 6 7
15 14 13 12 11 10 9 8
16 17 18 19 20 21 22 23
etc.

rather than top-to-bottom, left-to-right.

In that case I’d go with something like this:

#define rows 8
#define cols 8

pixelInfo pixelData[rows*cols];

int xy2index(int x, int y) {
if (y%2==1)
Return (y+1)cols - x - 1; // odd rows
Else
Return y
cols + x; // even rows
}

Main(){
PixelData[xy2index(0,0)].R = 128; etc…
}

(Minus the inevitable syntax errors and it may be a good idea to check the x and y passed to the function are within range etc… I only have a tablet available right now, not the best platform for coming up with code)

If your array or other LED setup is more complicated then you can build a mapping function that takes logical positions and converts them into physical LEDs. That is what the GuggenHat does. I did not write the mapping function but extended the overall library.

http://daddyoh.us/blog/2014/09/11/guggenhat-with-default-messages/

I will write a mapping function from cartension coordinates to polar coordinates to LED position when I do the POV prototye.

@ AndyA - Thanks again, Andy.

Had a look at your library, and realized that this may not work for the RGB-123 after all, as it is WS2812-based, and only has +5v, Gnd, and Data pins (no MISO/MOSI/CLK).

Unless I’m missing something, I may have to find a different library.