Raspberry Pi and NeoPixel Library

EL Wire/Tape/Panels, LEDs, pixels and strips, LCDs and TFTs, etc products from Adafruit

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
User avatar
jer
 
Posts: 13
Joined: Wed Sep 03, 2014 10:13 am

Raspberry Pi and NeoPixel Library

Post by jer »

I just wanted to share some code that makes it possible (and very simple) to drive NeoPixels directly from a Raspberry Pi. This uses hardware in the Pi to drive the signal without software intervention. Timing isn't a problem. The signal timing is very accurate. Please see:

https://github.com/jgarff/rpi_ws281x

I've got more that I want to do including:

- Better Code Commenting
- Start a Wiki page
- Making this work with Python
- Finishing a kernel driver with interrupt support
- Finishing a Debian Package

Anyway, please let me know what you think. I'm very open to comments, bug fixes, and suggestions. Please spread the word. I hope you find it useful.

Jeremy

User avatar
adafruit2
 
Posts: 22148
Joined: Fri Mar 11, 2005 7:36 pm

Re: Raspberry Pi and NeoPixel Library

Post by adafruit2 »

w0000 this is so cool, we were thinking of using the SPI DMA core to do it but didn't get a round tuit. This is awesome!

we'll try it ASAP and report back :)

User avatar
jer
 
Posts: 13
Joined: Wed Sep 03, 2014 10:13 am

Re: Raspberry Pi and NeoPixel Library

Post by jer »

Cool! Let me know if you run into any problems. Just FYI, I made a very simple level shifter with a couple resistors and a NPN transistor to bring the signal to 5V. Because of this additional circuit, I had to invert the signal. You may want to double check that setting depending on your signalling. It's in main.c in the ws2811_t invert field. Set to 0 if you don't want it inverted.

User avatar
tdicola
 
Posts: 1074
Joined: Thu Oct 17, 2013 9:11 pm

Re: Raspberry Pi and NeoPixel Library

Post by tdicola »

Wow this looks really nice. I'm having a little trouble getting it to work though--when I run the main program it's getting to the ws2811_render() function call but gets stuck inside when it calls ws2811_wait(). I'm using the stock main.c on a Raspberry Pi model B and B+, and have a hex buffer hooked up as a 3.3->5V level converter. I just added a little bit of instrumentation to the ws2811_render function to see where it's getting stuck, my modified function looks like:

Code: Select all

void ws2811_render(ws2811_t *ws2811)
{
    volatile uint8_t *pwm_raw = ws2811->device->pwm_raw;
    int bitpos = 31, wordpos = 0;
    int i, j, k, l;

    printf("Starting render of %d pixels\n", ws2811->count);

    for (i = 0; i < ws2811->count; i++)          // Led
    {
        printf("Do pixel %d\n", i);
        uint8_t color[] =
        {
            (ws2811->leds[i] >> 8) & 0xff,       // green
            (ws2811->leds[i] >> 16) & 0xff,      // red
            (ws2811->leds[i] >> 0) & 0xff,       // blue
        };

        for (j = 0; j < ARRAY_SIZE(color); j++)  // Color
        {
            for (k = 7; k >= 0; k--)             // Bit
            {
                uint8_t symbol = SYMBOL_LOW;

                if (color[j] & (1 << k))
                {
                    symbol = SYMBOL_HIGH;
                }

                for (l = 2; l >= 0; l--)         // Symbol
                {
                    uint32_t *wordptr = &((uint32_t *)pwm_raw)[wordpos];

                    *wordptr &= ~(1 << bitpos);
                    if (symbol & (1 << l))
                    {
                        *wordptr |= (1 << bitpos);
                    }

                    bitpos--;
                    if (bitpos < 0)
                    {
                        wordpos++;
                        bitpos = 31;
                    }
                }
            }
        }
    }

    printf("Render loop done.\n");

    __clear_cache((char *)pwm_raw,
                  (char *)&pwm_raw[LED_BYTE_COUNT(ws2811->count, ws2811->freq)]);

    printf("Cache cleared.\n");

    ws2811_wait(ws2811);

    printf("Wait done.\n");

    dma_start(ws2811);

    printf("DMA start done.\n");
}
I can see it hits one iteration of the loop but gets stuck in the while loop of ws2811_wait, here's an example output:

Code: Select all

pi@raspberrypi ~/rpi_ws281x $ sudo ./test
Starting render of 64 pixels
Do pixel 0
Do pixel 1
Do pixel 2
Do pixel 3
Do pixel 4
Do pixel 5
Do pixel 6
Do pixel 7
Do pixel 8
Do pixel 9
Do pixel 10
Do pixel 11
Do pixel 12
Do pixel 13
Do pixel 14
Do pixel 15
Do pixel 16
Do pixel 17
Do pixel 18
Do pixel 19
Do pixel 20
Do pixel 21
Do pixel 22
Do pixel 23
Do pixel 24
Do pixel 25
Do pixel 26
Do pixel 27
Do pixel 28
Do pixel 29
Do pixel 30
Do pixel 31
Do pixel 32
Do pixel 33
Do pixel 34
Do pixel 35
Do pixel 36
Do pixel 37
Do pixel 38
Do pixel 39
Do pixel 40
Do pixel 41
Do pixel 42
Do pixel 43
Do pixel 44
Do pixel 45
Do pixel 46
Do pixel 47
Do pixel 48
Do pixel 49
Do pixel 50
Do pixel 51
Do pixel 52
Do pixel 53
Do pixel 54
Do pixel 55
Do pixel 56
Do pixel 57
Do pixel 58
Do pixel 59
Do pixel 60
Do pixel 61
Do pixel 62
Do pixel 63
Render loop done.
Cache cleared.

Have you run into any issues with the wait before starting DMA? I'll poke around a bit more to see if I can find the value that dma->txfr_len is staying at in the while loop of the wait function.

User avatar
tdicola
 
Posts: 1074
Joined: Thu Oct 17, 2013 9:11 pm

Re: Raspberry Pi and NeoPixel Library

Post by tdicola »

If it helps it looks like dma->txfer_len is staying at a value of 568 in the while loop.

User avatar
jer
 
Posts: 13
Joined: Wed Sep 03, 2014 10:13 am

Re: Raspberry Pi and NeoPixel Library

Post by jer »

I haven't seen that issue on mine. I'm wondering if the DMA channel is conflicting with some other driver. Does it work if the wait loop is taken out completely? It shouldn't matter with 15 frames a second. If it doesn't work without the loop, I suspect there is a DMA channel conflict. Try using a different dmanum in the ws2811_t structure passed to the init.

User avatar
adafruit2
 
Posts: 22148
Joined: Fri Mar 11, 2005 7:36 pm

Re: Raspberry Pi and NeoPixel Library

Post by adafruit2 »

tdicola - you may want to try with a freshy fresh raspbian - the pitft-installed raspbian uses a DMA for SPI, btw!

User avatar
tdicola
 
Posts: 1074
Joined: Thu Oct 17, 2013 9:11 pm

Re: Raspberry Pi and NeoPixel Library

Post by tdicola »

Oh good call on the PiTFT image, I'll try a fresh Raspbian one since this is a PiTFT image.

User avatar
tdicola
 
Posts: 1074
Joined: Thu Oct 17, 2013 9:11 pm

Re: Raspberry Pi and NeoPixel Library

Post by tdicola »

Hrm, just installed the June 2014 Raspbian image from here: http://www.raspberrypi.org/downloads/ but am still having trouble with it getting stuck in the DMA wait loop. The good news is if I comment out the DMA wait it works great! I had to update the main program to use a frequency of 800khz & disable inversion to work with my setup, but here's a quick pic of a ring:
Image

I'll poke around a bit more later today to see if I can understand more about the DMA wait loop getting stuck.

Looks like really nice code though that would be great to turn into a library for more folks to use! Do you mind if I look at adding a simple python interface on top of it? Something like SWIG might be easy to generate a library without much work, or worst case I can just roll one by hand.

User avatar
jer
 
Posts: 13
Joined: Wed Sep 03, 2014 10:13 am

Re: Raspberry Pi and NeoPixel Library

Post by jer »

Glad commenting out the wait got it working. I'll look into why that might be the case. I'll see if there is a better way to check to see if the DMA is still busy. This is the whole reason I was going to write a kernel module for it. I'd much rather use the interrupt to signal DMA completion. Polling for it just burns CPU time.

As for adding a python interface, go for it! I was going to add a C extension in python to call the ws2811 library underneath. I'm happy to take code submissions, so please feel free to contribute.

User avatar
jer
 
Posts: 13
Joined: Wed Sep 03, 2014 10:13 am

Re: Raspberry Pi and NeoPixel Library

Post by jer »

Just thought I'd share a pic of my setup. You can see my ugly hack of a level shifter in the background, lovingly crafted from old RadioShack parts. The rise time on my signal isn't very good, hence the 400k signal rate in the code.
Attachments
neopixel_rpi.JPG
neopixel_rpi.JPG (366.02 KiB) Viewed 1193 times

User avatar
jer
 
Posts: 13
Joined: Wed Sep 03, 2014 10:13 am

Re: Raspberry Pi and NeoPixel Library

Post by jer »

Please pull the latest from github (https://github.com/jgarff/rpi_ws281x). I've added library generation, and some DMA debug to see if we can track down the DMA problem. Thanks.

User avatar
tdicola
 
Posts: 1074
Joined: Thu Oct 17, 2013 9:11 pm

Re: Raspberry Pi and NeoPixel Library

Post by tdicola »

Awesome, thanks! I'll give it a shot a little later today.

User avatar
tdicola
 
Posts: 1074
Joined: Thu Oct 17, 2013 9:11 pm

Re: Raspberry Pi and NeoPixel Library

Post by tdicola »

Sorry got a little busy with other stuff and just now had a chance to try the updated code. It actually works out of the box for me with just a tweak to the frequency (up to 800khz) and invert = 0, very cool! Interesting that I'm not hitting the DMA timeout anymore. Will take a quick look to see what might have changed.

edit: Hrm actually I still do see it sometimes locking up in the wait. It's kind of intermittent and tough to tell what might be causing it. Let me play around with trying different DMA channels to see if perhaps something is conflicting.

User avatar
jer
 
Posts: 13
Joined: Wed Sep 03, 2014 10:13 am

Re: Raspberry Pi and NeoPixel Library

Post by jer »

Cool! I did change the way I detect for DMA busy. I'm now polling the active bit instead of the bytes transferred. This should be a uncached region of memory, but it's acting like it's cached. It might simply be that the DMA logic isn't designed to poll bytes transferred and returns a previous value if both the DMA and the CPU are trying to access the register in the same clock. Dunno. Glad it works though.

Doh. Did that previous paragraph before I saw your edit... Yeah, try a different DMA channel. Might be conflicting. On mine it works great.

Here's some additional info on my setup in case it helps:

- Linux ledmaster 3.12.22+ #691 PREEMPT Wed Jun 18 18:29:58 BST 2014 armv6l GNU/Linux
- Raspberry Pi Model B w/512MB DDR
- Nothing overclocked
- Not running X. Text console only.
- Fresh Raspbian install as of a couple days ago, as I was trying to reproduce the problem.

Locked
Please be positive and constructive with your questions and comments.

Return to “Glowy things (LCD, LED, TFT, EL) purchased at Adafruit”