drive NeoPIXEL / ws2812 leds?



  • Anyone tried (will it be possible) to drive some neopixel aka WS2812 led strips from the pycom boards? there is already an onboard one, so I would say that it shouldnt be very hard to make it possible to drive a string of them as well on any pin?

    Thx!



  • @LoneTech Yes, thanks! I read the reference manual to understand how it works, and I managed to drive the 16 LEDs of my ring.
    I re-wrote your code into a class so that I can use it in my project. I created a Github repo if you want to take a look : https://github.com/JF002/lopy-snippets/tree/master/WS2812.

    Thanks for your help!



  • @JF002 Each RMT channel has a RAM block of 64 words, and each bit of WS2812 takes one word, so more than two LEDs will require more than one block of RAM. I think you get larger capacity by setting mem_size>1 and mem_owner needs to be se to 0 for transmit. That's how I got to 21 LEDs, by the way; 8*64=512, 21*24+1=505.



  • @LoneTech Thanks a lot for your code! I didn't even know that we could access to the low level register with micropython, this is awesome! And this RMT device is very interesting!

    I managed to lit the onboard RGB LED and the first LED of my 16 LEDs ring connected to another GPIO.
    Now, I'll try to figure out how to control the other LEDs of the ring!



  • @aureleq The ring is already powered by an external power supply, and works perfectly on another board (I developped a driver on an STM32F4 using timers and DMA). The power supply is able to provide enough current for the 16 LEDs.
    And I observe the same behaviour when I drive only 1 LED at a time : some colors are not displayed, some are not correct, some are good... I think that there are some timing error. I think that the driver mentionned previously in this post uses the onboard SPI controller, but I don't know much about it, and cannot check the timings.

    Anyway, I was asking the question because it seems that some people managed to use this code to drive WS2812, and I don't know why it's not working for me.

    @LoneTech Thanks for the information about the RMT. I don't know the internals of the ESP32, but it could be a better fit to generate the signals to the WS2812 than the SPI. I'll check your code as soon as I have the time.



  • I just managed to drive the onboard WS2812 using the ESP32's RMT (remote) peripheral. This is an 8-channel modulated pulse train transceiver, capable of accelerating many single wire protocols including servos, neopixels and onewire, if tricked out just right. This example drives one neopixel, but the peripheral could drive 21 of them before running out of memory (at which point we need an interrupt to feed it).

    The sample code is in esp32rmt.py at https://github.com/lonetech/LoPy (it relies on the esp32.py file as well).



  • @JF002 it's probably too much for the board to lit up all LEDs at the same time, I usually set 3-4 LEDs max.
    Each LED can draw up to 60 mA at maximum brightness, times 16 this is a lot of current.

    From the topic below, it looks like the max current load is 1.2 A but not exceeding 500 mA is a safe bet:
    https://forum.pycom.io/topic/62/3-3v-output-max-load-current

    I would try by powering up the neopixel with an external power supply to verify the behavior.

    Aurelien



  • @aureleq I'm not sure if it's the best place to discuss about this, but I didn't find another way to contact you...

    I tried your WS2812 driver on my Lopy but it doesn't work as expected : the color are not always what I expected.
    For example, I ran this simple code on my Lopy connected to a ring of 16 WS2812:

    from ws2812 import WS2812
    from utime import sleep_ms
    
    chain = WS2812( ledNumber=16, brightness=100, dataPin='P22' ) # dataPin is for LoPy board only
    data = [(0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0),
            (0, 0, 0), (0, 0, 0), (0, 0, 0), (0,0,0),
            (0, 0, 0), (0, 0, 0), (0, 0, 0), (0,0,0),
            (0, 0, 0), (0, 0, 0), (0, 0, 0), (0,0,0)
           ]
    chain.show( data )
    
    
    value =  0
    while True:
        
        for i in range (0,  16) :
            data[i] = (value,  value,  value)
        chain.show( data )
        value = value + 1
        if value == 256:
            value = 0
        sleep_ms( 150 )
    

    It's supposed to set all the LED in white, with the brightness increasing at each iteration of the loop.

    However, while the all the other LEDs are white, the first one is yellow. Moreover, it seems that some value are not displayed correctly, and, in this case, sometime, the LEDS are fully OFF or ON and this, the brightness does not increase as expected.
    For example, the tuple (85, 85, 85) result in a totally OFF LED.

    Note that this ring of WS2812 works fine on another project (bare metal programming on STM32F4).
    I don't have any logical analyzer or oscilloscope to diagnose the signal on the wire..

    Do you have any idea why it doesn't work as expected?

    Thanks!



  • @nielsoo there was an existing library for WiPy. I did minor modifications to add support for LoPy, you can find it here: https://github.com/aureleq/wipy-lopy-WS2812



  • It is certainly possible; the remote control module can do it with hardware acceleration, and the RGB LED already on the current Pycom boards is in fact a WS2812. You could software bitbang it like the micropython onewire module does, and the ESP32 can keep running the radio stacks on the protocol processor. Lots of options, though considering the pycom.rgbled module already does it I think it'd be nice to export that same function for use on other pins.


Log in to reply
 

Pycom on Twitter