Shop OBEX P1 Docs P2 Docs Learn Events
Updated WS2812 Driver — Parallax Forums

Updated WS2812 Driver

JonnyMacJonnyMac Posts: 9,104
edited 2016-10-13 21:40 in Propeller 1
I've made a serious change to my WS2812 driver that I'm hoping my friends here will play with before I unleash in ObEx.

Changes:
-- driver no longer uses internal array; this allows the app to set the size of the pixel buffer without waste
-- pixel buffer, buffer size, and transmit pin can be changed on-the-fly

By removing the internal array the application can save memory. Using external arrays also facilitates some animation techniques without artifacts (the current array is transmitted before switching to the new one). And by allowing pin changing, the same array(s) can be sent to multiple strings of pixels (this should eliminate my one-shot driver which I was never very happy with).

Your comments and suggestions are appreciated.

09 OCT 2016 : Per a request, I created an integrated driver for WS2812 (RGB) and SK6812 (RGBW) pixels. In order to keep things as clean as possible RGB values when use WS2812 pixels must now be left justified (in the standard WS2812 driver they are right justified). The driver will support both pixel types in the same project; the use() method requires the bit count for the type of pixels in use for the specified buffer/pin.

Note: As of 09 OCT 16 I have only tested the integrated driver with WS2812b pixels.

Updated jm_rgbx_pixel.spin driver 13 OCT 2016 @ 2:55 PM (Pacific Time)

Redundant drivers removed.
«13

Comments

  • Nice, I will start using it.
  • Can't wait to try it out this weekend. I would love to see RGBW support.
  • Specifically, what RGBW pixels are you referring to?
  • KednerpoKednerpo Posts: 46
    edited 2016-10-08 02:37
    The SK6812RGBW Neopixels from Adafruit or other similar strips.

    Like these.

    https://www.adafruit.com/products/2842

    They are very similar to the 2812b but with a few differences. I was able to modify one of your old drivers to make them work. I didn't know if your revamped "official" version would include support for them.
  • JonnyMacJonnyMac Posts: 9,104
    edited 2016-10-08 16:01
    As that uses a different pixel I made a separate driver. I don't have a string to test with yet, so I'll ask if you'll give it a try.
  • The WS2812works great. Going to spend more time with it a little later today.

    So far no luck with the SK6812RGBW driver. Not sure if it is the way I have it set up in the demo object. Still testing. I will let you know when I find something.
  • JonnyMacJonnyMac Posts: 9,104
    edited 2016-10-08 13:50
    Let me look into it.
  • JonnyMacJonnyMac Posts: 9,104
    edited 2016-10-08 16:02
    Give this version a try. I had neglected to remove the rgfix variable from the object global vars, which doesn't seem to be required for this driver. That's out now, and I did a bunch of doc clean-ups.

    Updates move to original post (top of thread)

  • That works! Awesome!
  • Actually I think the color fix may still be needed for the SK6812RGBW for some reason.
      repeat                                                        ' standard demo
        repeat 3
          color_wipe($10_00_00_00, 5000/STRIP_LEN)
          color_wipe($00_10_00_00, 5000/STRIP_LEN)      
          color_wipe($00_00_10_00, 5000/STRIP_LEN)
          color_wipe($00_00_00_10, 5000/STRIP_LEN) 
    

    Results in :
    Green Wipe
    Red Wipe
    Blue Wipe
    White Wipe

    Still testing!!!
  • KednerpoKednerpo Posts: 46
    edited 2016-10-08 16:02
    Putting the color fix back in and modifying the masks makes it work correctly
    ' Correct placement of color bytes                    
    '   $RR_GG_BB_WW --> $GG_RR_BB_WW                                      
                                                                     
    fix_colors              mov     t1, colorbits                   ' copy for red
                            mov     t2, colorbits                   ' copy for green
                            and     colorbits, HX_0000FFFF          ' isolate blue and white
                            shr     t1, #8                          ' fix red pos (byte1)
                            and     t1, HX_00FF0000                 ' isolate red
                            or      colorbits, t1                   ' add red back in
                            shl     t2, #8                          ' fix green pos (byte2)
                            and     t2, HX_FF000000                 ' isolate green
                            or      colorbits, t2                   ' add green back in  
    

    and further down
    HX_0000FFFF               long    $0000FFFF                     ' byte masks
    HX_00FF0000               long    $00FF0000                         
    HX_FF000000               long    $FF000000
    
  • JonnyMacJonnyMac Posts: 9,104
    edited 2016-10-08 16:35
    That is very interesting as the documentation clearly states that the color order is R, G, B, then W -- everything shifted out MSBFIRST. I put the fix back in (slight modification of your code to match my thinking).

    Thanks for testing the driver.

    I just ordered a reel from Amazon -- I'll have some SK6812s to work with on Monday.
  • KednerpoKednerpo Posts: 46
    edited 2016-10-08 22:52
    Another thought on the SK6812RGBW driver

    Would it be worth considering keeping the "pub start" and "pub start_b" routine from your original ws2812 driver to set up timing and variables to run ws2812 strips and adding a "pub start_c" routine to setup sk6812RGBW strip timing and variables?

    There would also need to be an additional variable to tell the driver to shift 24 bits for 2812's and 32bits for 6812RGBW's.

    I think this would allow the driver to be used for any neopixel product.
  • JonnyMacJonnyMac Posts: 9,104
    edited 2016-10-09 14:03
    I thought about that and 10 seconds later determined it was not a good idea -- in my mind, anyway. They are two different parts, which means both the foreground and background would have to jump through hoops to deal with the differences. I cannot imagine why a designer would mix WS2818s and SK6812s with the same project, hence there is no penalty in having separate drivers. I'm not saying that I won't try it... I'm just thinking at the moment it's not an idea that provides any real benefit.

    Also, my code is written to be functional and to allow others to learn. Have you ever looked at an Arduino library written by Limore Fried? Holy Cow, Batman, following that stuff can be a nightmare at times. I have a different attitude: I want people to do more than use my libraries, I want them to learn from them and build other things.
  • I have seen the Arduino library for these and most definitely agree they are really hard to follow.

    Great advice/reminder on developing simple useful drivers and letting others learn and build on them for there own needs.
  • JonnyMacJonnyMac Posts: 9,104
    edited 2016-10-10 15:29
    Okay, I changed my mind and am working on an integrated driver. I figure JFK once changed his mind, and I have portrayed JFK more than once on TV (Discovery and History channels, as even a Japanese TV show), so changing my mind is okay! :)

    Good bits:
    -- will support 24-bit and 32-bit pixels
    -- can even support both types of SK6812 pixels in same project!

    Caveats:
    -- pixel values for 24-bit types (WS2812) must now be left-aligned

    It's not working at the moment (with WS2812b pixels) and I have to build some PCBs this morning, so I will finish later. My SK6812s will be here tomorrow so I can do a full test. I had a free bit in my connection value so the way it's designed the driver will support 24-bit and 32-bit pixels and even allow you to switch between them in the same project. I don't know if I would do this, but someone might have a special circumstance that requires it.
  • Integrated driver is now working with WS2812b string. Will test with SK6812 string tomorrow. Demo and object are attached to post at top of thread.
  • All my Neopixel dreams coming true!!! Integrated driver working as advertised here!!!

    I'm working on an under cabinet lighting project. For budget purposes I was only going to implement RGBW strips where good quality white task lighting was necessary and the less expensive RGB strips everywhere else but was not sure if I would be able to mix and match them at the time. I ended installing all RGBW just in case. It's great that this driver will offer that flexibility going forward.
  • I wanted to point out that there are two sk6812 products.

    The sk6812RGBW is the 32bit RGBW strips while the sk6812 is functionally the same as the ws2812B

    Some companies are shipping the ws2812B and sk6812 interchangeably.
  • JonnyMacJonnyMac Posts: 9,104
    edited 2016-10-09 22:20
    All my Neopixel dreams coming true!!! Integrated driver working as advertised here!!!
    Excellent! I should treat myself to a cookie!
    The sk6812RGBW is the 32bit RGBW strips while the sk6812 is functionally the same as the ws2812B
    Okay. I made a very small update to the driver, changing the interface for SK6812 pixels (same change in sk6812x driver).
    pub start_6812x(p_buf, pixels, pin, holdoff, bits)
    
    The timing is the same for the SK6812 RGB and RGBW strips, so adding the bit count into this method should take care of everything. The WS2812 and WS2812b pixels have slightly different timing, hence the separate methods in the drivers that support them.

    Update at top.
  • Jeff HaasJeff Haas Posts: 421
    edited 2016-10-10 05:43
    I was trying out some of the new methods and ran into something odd. I put together this small method which shows what I saw, it's just a cut-down version of the main demo with a couple of pauses added and the channels in the second half edited.
    pub test1 | p_pixels, pos, ch 
    
      longfill(@pixels1, $10_00_00, STRIP_LEN)                      ' prefill buffers
      longfill(@pixels2, $00_10_00, STRIP_LEN)
      longfill(@pixels3, $00_00_10, STRIP_LEN)
    
     repeat 
    
       repeat 3                                                      ' demonstrate buffer switching
         strip.use(@pixels1, STRIP_LEN, LEDS)
         time.pause(500)
         strip.use(@pixels2, STRIP_LEN, LEDS) 
         time.pause(500)    
         strip.use(@pixels3, STRIP_LEN, LEDS) 
         time.pause(500)
    
       repeat 3                                                      
         strip.clear
         strip.fill( 0,  7, $10_00_00)
         time.pause(2000)
         strip.fill( 0, 7, $00_10_00)
         time.pause(2000)
         strip.fill(0, 7, $00_00_10)
    
         time.pause(2000)
         strip.clear
         time.pause(250)
    

    I'm using a Quickstart board and a strip of 8 Neopixels with an external 5V power supply.

    When the code loops back to the top and flips through the three colors, blue is missing - I see red, green and then black/off.

  • JonnyMacJonnyMac Posts: 9,104
    edited 2016-10-10 13:52
    At the bottom of your demo loop you have this:
      strip.clear
      time.pause(250)
    
    The last buffer assigned to the LEDs is pixels3 which held blue up at the top for the buffer switching demo. At the bottom of your demo loop the .clear() method is operating on pixels3 which means the blue array is being erased. If you move the buffer filling into the loop the problem will go away.
  • Jon,
    I will try and test your driver today.
    Jim
  • Chris SavageChris Savage Parallax Engineering Posts: 14,406
    I am in the middle of moving (sold my house yesterday), but as soon as I get settled I would be happy to try the new driver. :nerd:
  • I'm interested in the new driver as well. Removing the array sounds like the change that I made when I ported your PASM code to C. I'm hoping that means that I can use your PASM code unmodified now.
  • David Betz wrote: »
    I'm interested in the new driver as well. Removing the array sounds like the change that I made when I ported your PASM code to C. I'm hoping that means that I can use your PASM code unmodified now.

    There are really two drivers: an update to the WS2812 driver, and a consolidated driver that will support WS2812 and SK6812 types. The latter has 24- and 32-bit variants, so the storage is changed for all pixels; the new format is $RR_GG_BB_WW where WW (byte0) is the white channel for 32-bit pixels, and not used for 24-bit pixels.

    At the top of the main loop the PASM code looks for a command which changes its connection settings; this is a packed long that contains the address of the buffer (low word), the # of pixels in the buffer minus one (10 bits of high word), the output pin (five bits), and the 24- or 32-bit type (bit31).
  • JonnyMac wrote: »
    David Betz wrote: »
    I'm interested in the new driver as well. Removing the array sounds like the change that I made when I ported your PASM code to C. I'm hoping that means that I can use your PASM code unmodified now.

    There are really two drivers: an update to the WS2812 driver, and a consolidated driver that will support WS2812 and SK6812 types. The latter has 24- and 32-bit variants, so the storage is changed for all pixels; the new format is $RR_GG_BB_WW where WW (byte0) is the white channel for 32-bit pixels, and not used for 24-bit pixels.

    At the top of the main loop the PASM code looks for a command which changes its connection settings; this is a packed long that contains the address of the buffer (low word), the # of pixels in the buffer minus one (10 bits of high word), the output pin (five bits), and the 24- or 32-bit type (bit31).
    Sounds good. I'd like to try the RGBW pixels but I don't have any at present.

  • Chris SavageChris Savage Parallax Engineering Posts: 14,406
    David,

    They use the WS2812, so I would say yes.
Sign In or Register to comment.