Shop OBEX P1 Docs P2 Docs Learn Events
WS2811/WS2812 driver for the Propeller — Parallax Forums

WS2811/WS2812 driver for the Propeller

David BetzDavid Betz Posts: 14,516
edited 2014-10-28 08:29 in Propeller 1
Has anyone written a driver for the WS2811 and WS2812 RGB LED driver chips? I have a few of these modules and would like to be able to drive them from a Prop board.

https://www.sparkfun.com/products/11820
«134

Comments

  • RaymanRayman Posts: 14,653
    edited 2013-08-02 14:54
    David, Just looked at Sparkfun and the first comment about it was from JonnyMac saying he posted a driver in OBEX...
  • David BetzDavid Betz Posts: 14,516
    edited 2013-08-02 15:06
    Rayman wrote: »
    David, Just looked at Sparkfun and the first comment about it was from JonnyMac saying he posted a driver in OBEX...
    Odd. I searched for WS2811 and WS2812 in OBEX but didn't find anything.
  • David BetzDavid Betz Posts: 14,516
    edited 2013-08-02 15:09
    David Betz wrote: »
    Odd. I searched for WS2811 and WS2812 in OBEX but didn't find anything.
    Okay, I understand now. I did my search earlier and he only posted it an hour ago. Thanks JonnyMac!!
  • David BetzDavid Betz Posts: 14,516
    edited 2013-08-02 15:41
    Okay, another probably dumb question. Can I connect a Propeller pin directly to the DI pin of the WS2812 even though the WS2812 is a 5v device or do I need a resistor in between?
  • David BetzDavid Betz Posts: 14,516
    edited 2013-08-02 15:46
    David Betz wrote: »
    Okay, another probably dumb question. Can I connect a Propeller pin directly to the DI pin of the WS2812 even though the WS2812 is a 5v device or do I need a resistor in between?
    Sorry, that was a dumb question. I just hooked the Propeller pin directly to the WS2812 DI pin and JonnyMac's test program seems to run just fine.
  • JonnyMacJonnyMac Posts: 9,105
    edited 2013-08-02 16:18
    David: Technically, 3.3v is below the Vih threshold of the chip, but I haven't had any problems with it, nor have others that tried the driver. I suggest the connection between the Propeller and the first LED be as short and low-Z as possible.
  • Cluso99Cluso99 Posts: 18,069
    edited 2013-08-02 17:35
    I think tubular posted some info on the WS2812 a week or so ago. Perhaps he will chime in.
  • David BetzDavid Betz Posts: 14,516
    edited 2013-08-04 11:38
    One thing that I find odd about the protocol for controlling these LEDs is that the durations of a "0" bit and a "1" bit are different. This copy of the data sheet has different numbers,

    In high speed mode:

    T0H 0.25 us
    T0L 1.0 us

    T1H 0.6 us
    T1L 0.65 us

    At least both of these add up to 1.25 us.

    http://auschristmaslighting.com/wiki_source/images/b/ba/WS2811.pdf
  • JonnyMacJonnyMac Posts: 9,105
    edited 2013-08-04 15:55
    The documentation for those parts is something less than stellar. I went with the WS2812 numbers and they worked. Note that there is a 150ns (0.15us) tolerance on all timing parameters.
  • David BetzDavid Betz Posts: 14,516
    edited 2013-08-04 17:18
    JonnyMac wrote: »
    The documentation for those parts is something less than stellar. I went with the WS2812 numbers and they worked. Note that there is a 150ns (0.15us) tolerance on all timing parameters.
    Both sets of numbers seem to work for me. As you say, there is a fair amount of leeway. I've run into another problem though. I have three of these LEDs that I'm running with your code and they were working just fine for a while. Unfortunately, the middle LED is now acting strangely and displaying different colors than the ones on either side. I can't see how this could possibly happen given how your code is written so I'm wondering if the middle unit is starting to fail. Have you ever had trouble with these things?
  • TubularTubular Posts: 4,702
    edited 2013-08-05 05:15
    Hi David

    I've seen some strange colors when the data connection is dodgy (how long is that wire?). It may be an idea to terminate it to a resistor and perhaps small capacitor.

    Otherwise, I've tested about 5 different WS2812x products successfully now. I'm using a slightly modified version of Gavin Garner's obex object (to swap the G and R bytes).

    Tonight I've been testing the timing limits and looks like they can be pushed to 1.37 Mbits/sec, or an update rate of ~380 per second for a 150 LED string using symmetric timing. Timing was as follows (these values are right on the edge of working successfully, except Low0) :-
    'Using 6.25MHz XTAL and PLL16x to give 10nsec tick resolution:-
      High1:=63 '0.63us WS2812B
      Low1 :=10 '0.10us WS2812B  total bit cycle time = 0.73us, or 1.37Mbit/sec update rate / 150 leds / 24 bits = 380 Updates/second
      High0:=13 '0.13us WS2812B
      Low0 :=60 '0.60us WS2812B can go as low as 50 ticks successfully, but then its assymmetric depends on data.  
      reset:=5000  '50.0us WS2812B datasheet.  This seems to work with any value. 
    

    As you observed its possible to reduce Low0 to 50, which makes the overall bitrate dependent on the number of 1's vs 0's. However it isn't much of a gain.
  • David BetzDavid Betz Posts: 14,516
    edited 2013-08-05 06:54
    Tubular wrote: »
    Hi David

    I've seen some strange colors when the data connection is dodgy (how long is that wire?). It may be an idea to terminate it to a resistor and perhaps small capacitor.
    My wires are kind of long. Somewhere around two inches. Maybe that's the problem. The odd thing is that it worked just fine initially and also, you'd think that an error receiving data on the second LED in the chain would affect the third LED as well but it seems to be working fine. I'll have to play with your resistor/capacitor idea.

    Thanks,
    David
  • JonnyMacJonnyMac Posts: 9,105
    edited 2013-08-05 09:55
    Two inches with good connections shouldn't be a problem, but 3.3v is below the Vih spec of the chip. An easy solution is to buffer the Propeller output with a TC4427 -- I use this for voltage translation all the time. It's a MOSFET driver hence has a very stiff output. I used it on a project board earlier this year that was driving WS2801 (with clock and data lines) LEDs; it worked perfectly.

    BTW... if you're dealing with individual pixels, you may want to swap them to see if the problem moves; maybe you have a dodgy part. The WS28xx cleans and amplifies the signal(s) before output; if you're getting good data to the first device the rest should be okay.
    837 x 367 - 54K
  • David BetzDavid Betz Posts: 14,516
    edited 2013-08-05 10:02
    JonnyMac wrote: »
    Two inches with good connections shouldn't be a problem, but 3.3v is below the Vih spec of the chip. An easy solution is to buffer the Propeller output with a TC4427 -- I use this for voltage translation all the time. It's a MOSFET driver hence has a very stiff output. I used it on a project board earlier this year that was driving WS2801 (with clock and data lines) LEDs; it worked perfectly.

    BTW... if you're dealing with individual pixels, you may want to swap them to see if the problem moves; maybe you have a dodgy part. The cleans and amplifies the data signal on its output; if you're getting good data to the first device the rest should be okay.
    Thanks for the advise. The odd thing is, the first and the third device seem to work fine. It's just the second one in the chain that is behaving oddly. I actually have a spare LED so I'll try swapping that in in place of the one that is misbehaving to see if that helps.
  • TubularTubular Posts: 4,702
    edited 2013-08-05 14:21
    Yeah definitely try swapping that LED. Unusual that it can be the second one but the third one works fine.

    I've been using about a 12" ic hook test lead for driving the data, so 2" won't be an issue. Your ground wiring could potentially be - I've been delivering the power to the WS2812B strip, since its high current, then running clip leads back to the prop proto board. You can have 5 amps of current running through the ground wire. Some of the strips provide two ground wires which helps here.

    The weird thing is the WS281xx reclocks the data out, so driving the voltage only really affects delivery to the first LED in the chain. While that may help, I would have expected a terminating resistor would also clean up any spurious overshoots.

    When testing the timing limits, when you go below minimum on the top three values, everything simply stops (black everywhere!). However when you go below minimum on the Low0, you get some fancy color shifts happening, and it seems to be worse towards the end of the 5m strip.

    Btw interesting article by Matt on Adafruit this morning on driving these with Beaglebone Black's PRU. The prop1 actually looks like it has a reasonable combination of ram, i/o pins, speed for driving some pretty big installations. I think it would be possible to drive several independent strips per cog, and its only $8
  • ratronicratronic Posts: 1,451
    edited 2013-08-06 19:06
    I have received four of these. I have only tried one strip of eight so far and Jon's code work's great - thanks. I still have to add the other three strips but this code seems to work with only the eight WS2812's connected and I think because of the way they work it

    should work with from 1 to 16 WS2812's using Jon's driver. It is repeating plots of a random byte of color at a random spot in the rgbbuf. Because these are so bright I put a brightness control.

    Edit: This code only randomly plots colors for 1 to 16 WS2812's.
    Con                  'random color plot for to up to 16 ws2812's        
                                                                            
      _CLKMODE = XTAL1 + PLL16X                                             
      _XINFREQ = 5_000_000                                                  
                                                                            
      BRIGHTNESS = 10    'lower# = brighter led's, higher# = dimmer led's   
            WSDI = 7     'prop port for di pin on ws2812's                  
                                                                            
    Var                                                                     
                                                                            
                                                                            
    Obj                                                                     
                                                                            
      ws : "jm_ws2812"                                                      
                                                                            
    Pub Main | addr                                                         
                                                                            
      ws.start(WSDI, 16)                                                    
                                                                            
      addr := ws.address                                                    
                                                                            
      repeat                                                                
                                                                            
        byte[addr + ?cnt & $3f] := ?cnt & $ff / BRIGHTNESS                  
        waitcnt(clkfreq / 100 + cnt)
    
  • ratronicratronic Posts: 1,451
    edited 2013-08-07 10:10
    Ok I goofed up the code I posted above would only randomly plot colors from 1 to 16 WS2812's not 1 to 64. I corrected it above.
  • David BetzDavid Betz Posts: 14,516
    edited 2013-08-07 10:18
    ratronic wrote: »
    I have received four of these. I have only tried one strip of eight so far and Jon's code work's great - thanks. I still have to add the other three strips but this code seems to work with only the eight WS2812's connected and I think because of the way they work it

    should work with from 1 to 16 WS2812's using Jon's driver. It is repeating plots of a random byte of color at a random spot in the rgbbuf. Because these are so bright I put a brightness control.

    Edit: This code only randomly plots colors for 1 to 16 WS2812's.
    Con                  'random color plot for to up to 16 ws2812's        
                                                                            
      _CLKMODE = XTAL1 + PLL16X                                             
      _XINFREQ = 5_000_000                                                  
                                                                            
      BRIGHTNESS = 10    'lower# = brighter led's, higher# = dimmer led's   
            WSDI = 7     'prop port for di pin on ws2812's                  
                                                                            
    Var                                                                     
                                                                            
                                                                            
    Obj                                                                     
                                                                            
      ws : "jm_ws2812"                                                      
                                                                            
    Pub Main | addr                                                         
                                                                            
      ws.start(WSDI, 16)                                                    
                                                                            
      addr := ws.address                                                    
                                                                            
      repeat                                                                
                                                                            
        byte[addr + ?cnt & $3f] := ?cnt & $ff / BRIGHTNESS                  
        waitcnt(clkfreq / 100 + cnt)
    

    Thanks! I just got one of those 8 LED strips today. I'll try your code later.
  • ratronicratronic Posts: 1,451
    edited 2013-08-07 10:27
    David those strips work great with the demo that come with Jon's code also. I like the way he transitions colors with the wheel(pos) method.
  • JonnyMacJonnyMac Posts: 9,105
    edited 2013-08-07 11:37
    To be fair, that .wheel() method is not mine; I ported it from a C demo by Phil Burgess (www.paintyourdragon.com).
  • David BetzDavid Betz Posts: 14,516
    edited 2013-08-08 09:46
    I finally got around to replacing the LED unit that was misbehaving and have determined that it isn't the cause of the problem. The new one did the same thing. Also, I noticed that the last LED in the chain eventually gets into a mode where it doesn't display blue running JonnyMac's program. I'm beginning to wonder if my problem is the way I wired the LED units. I wired the data lines in a chain but I wired power directly to each LED. Should I have wired the power in a chain as well? Would this cause this sort of problem?

    In the meantime, I tried my SparkFun 8 LED strip and it works wonderfully with JonnyMac's code! No LED anomolies so far.
  • JonnyMacJonnyMac Posts: 9,105
    edited 2013-08-08 10:37
    I tried my SparkFun 8 LED strip and it works wonderfully with JonnyMac's code! No LED anomalies so far.


    Whew! Good to know -- I was worried I might have to go in and massage the driver. I prefer the KISS code employed now.
  • David BetzDavid Betz Posts: 14,516
    edited 2013-08-08 10:51
    JonnyMac wrote: »
    Whew! Good to know -- I was worried I might have to go in and massage the driver. I prefer the KISS code employed now.
    Do you think that wiring the power in parallel could have caused my problem with the individual LED units? I'll try wiring them in a chain later tonight to see if that makes any difference.
  • David BetzDavid Betz Posts: 14,516
    edited 2013-08-08 11:06
    David Betz wrote: »
    Do you think that wiring the power in parallel could have caused my problem with the individual LED units? I'll try wiring them in a chain later tonight to see if that makes any difference.
    Couldn't wait until this evening and it only involved switching a couple of wires but it didn't help. There must be something odd about these modules I guess.
  • JonnyMacJonnyMac Posts: 9,105
    edited 2013-08-08 13:05
    Even if you daisy-chain the modules the power lines are paralleled through them. Perhaps you got a few modules that are out-of-spec. Did you by them at RadioShack? ;)
  • David BetzDavid Betz Posts: 14,516
    edited 2013-08-08 13:08
    JonnyMac wrote: »
    Even if you daisy-chain the modules the power lines are paralleled through them. Perhaps you got a few modules that are out-of-spec. Did you by them at RadioShack? ;)
    I bought them from SparkFun. Also, I never tried your suggestion about using a level converter between the Propeller output pin and the DI pin of the first module although I can't see how that would affect anything other than the behavior of the first module in the chain.
  • JonnyMacJonnyMac Posts: 9,105
    edited 2013-08-08 13:10
    You're right, the signal coming out of the first device is clean, but it if misinterpreted data coming in, that error would be rebroadcast.

    I was teasing about RS. A friend told me about a resistor manufacturer that had these bins near a test fixture: 1%, 5%, 10%, 20%, RadioShack.
  • JBWolfJBWolf Posts: 405
    edited 2013-09-16 16:06
    Hey JMac, I have 72 led's on a strip using the WS2811.... I can get up to 32 led's to work great with your program in obex... but any number over 32 and it locks up the prop chip after 3-5sec.
    It loks up in the very first routine which I believe is the 'rainbow cycle'
    Any ideas?
  • Duane DegnDuane Degn Posts: 10,588
    edited 2013-09-16 16:14
    JBWolf wrote: »
    Hey JMac, I have 72 led's on a strip using the WS2811.... I can get up to 32 led's to work great with your program in obex... but any number over 32 and it locks up the prop chip after 3-5sec.
    Any ideas?

    Could you post your code. It seems strange it's locking up. It kind of sounds like a buffer overrun. I'll take a look if you'd like.

    I've used 48 NeoPixels with Jon's code.

    Did you see this section in the driver?
    con
    
    
      MAX_LEDS = 64                                                 ' adjust as required
      LAST_CH  = MAX_LEDS - 1
      
    

    I left it at 64 myself. You'll want to change it when you try to use all your LEDs at once.
  • JBWolfJBWolf Posts: 405
    edited 2013-09-16 17:30
    im using the default code, except I increased the number of led's from 3.
    First I made sure to stay under the max led variable of 64, but anything over 32 and it locks. I also tried increasing max led count to 80 and still get same results with anything over 32.
    http://obex.parallax.com/object/703
Sign In or Register to comment.