You seem to be asking the same question in multiple threads -- please don't do that as it make those of us the could/would help have to jump through hoops. As I point out in that other thread (where you called me out by name), I am running 40 LEDs without problems; others have run more. There is no reason for things to get truncated at 32 as the driver simply loops through all the pixels it thinks it has and then starts over (i.e., there is no set frame time).
For the next project, I've got to shuffle the PASM code around a bit, as I only need to send a single transmit cycle to several different pins. Sadly there aren't enough cogs to dedicate one to each output.
Will certainly post some pictures & video once it's all done. The final build will be spectacular.
I only need to send a single transmit cycle to several different pins
I whipped up a variant that uses single-shot mode using a new method called .execute(). You specify the pin to use, the number of LEDs in the string on that pin, and a pointer to the array you want to use. If you want to use the object's internal array, specify 0 as the source data. You'll note that most of the methods have been updated (and a couple eliminated) to accommodate the new features.
I've attached a very simple demo with the new driver that uses the internal and an external array. Let me know if that works out.
[Edit] Did some code clean-ups, commenting, expanded the demo a bit.
Hi Jon, this is a dumb question but could you explain the internal and external array,what are they exactly?
Another thing i've been trying search the net to get a data sheet regarding the ws2812 but seem to come back to just the one datasheet that seems to have been poorly translated to english and I understand that you have to transmit 24 bit packets in GRB format what I can't see in the datasheet is what the bits correspond to, ie which part is the position of the pixel in the string (presuming 8 bits for up to 255) , the brightness control for a particular pixel etc.
Sorry for the questions but I don't have the Leds yet to experiment with.
Of course you're code as usual makes it easy to accomplish but I just want a better understanding as to how the WS2812 works
Is there a tutorial rather like your excellent Nuts and Volts DMX one that explains why and how the code is written?
@JohnC: I love programming the Propeller and was intrigued by your need; an hour later there was a single-shot driver -- everybody wins (I had fun writing the code, you get to have fun using it). I will take you up on that lunch offer the next time I'm in SLC.
@Skylight: The internal and external array feature came up interpreting JohnC's need to control multiple strings from a single driver. In most cases, we don't need to do that so you specify the internal array using 0 for the array pointer. Just to clarify... let's say you have a project that wants to control three separate WS2812 strings but only have one cog left. What you can do is use the single-shot driver and create two external pixel buffers. Using the single-shot methods you can update any of your buffers (internal or external) and when updated you can refresh a particular string by calling the execute method with the pin, led count, and pointer to the buffer to transmit. So, yes, there is an extra step to update any particular string but this allows the method to be very flexible and control as many strings of WS2812s as you can connect to a Propeller. Of course, you don't need a buffer for every string; in fact, in many cases I suspect the same buffer will be applied to multiple strings. This is part of the reason I added a count to the execute method -- it just updates the LEDs you have (or want to update).
Controlling the brightness of a pixel involves setting the RGB registers. For example, $FF_00_00 is red at maximum brightness. $3F_00_00 is red at 1/4 brightness. There is no separate brightness byte for each pixel; you're forced to manipulate the individual registers. There is a method in the driver that allows you to manipulate brightness by passing a fourth byte (it's called colorx).
My current (September) column in Nuts & Volts magazine has an explanation of the driver.
[Edit] In case it's not clear, the single-shot driver is a variation of the original, not its replacement. In my "Hollywood" work I do a lot of LED animation and need my string(s) auto-updated, hence I'll use the original driver.
Thanks for the explanation Jon, as for the control of brightness that makes sense now. I shall read your article in Nuts and Volts with interest, that's if I can find it on the new website lol, thanks very much again.
Thanks for the explanation Jon, as for the control of brightness that makes sense now.
The problem with controlling brightness this way is you lose color resolution. This is one downside to the WS28xx drivers. If you're controlling a bunch of LEDs with shift registers you can send a PWM signal to the enable pin to control the brightness. The WS28xx chips just are so darn convenient it's often worth losing the color resolution to save on the rat's nest of wiring required from the shift register option.
The RGB Christmas lights have a brightness component. I haven't played with them enough to know if you can adjust the brightness on those without losing color resolution.
You got it, Red!, Charlotte is a nice city and I haven't been there in ages (used to go from time-to-time when I worked in the golf industry). It pleases me that you're getting use from my code; that's why I do it. Please post a picture of your conference badge when you can.
Note the line of WS2812s along the top :-) They warm the regulators something special when they're at full whack so we're likely going to limit them in software.
We're still working on the IR side of the house, trying to get better distance. Time to upgrade that 0603 IR LED to something more... special.
Can you break this down for me? I'm especially curious why you make that seemingly random byte value equal "?cnt &ff"
What does the ? before the 'cnt' do
That was a feeble attempt to use the counter for a seed for the random operator (?) and the & $ff AND's the 32 bit result with the lower 8 bits to return a random byte. The &3f is to pick a random spot in the buffer to write
That was a feeble attempt to use the counter for a seed for the random operator (?) and the & $ff AND's the 32 bit result with the lower 8 bits to return a random byte.
Why is it a feeble attempt?
The counter doesn't reset to zero when the Prop is turned off. Once the Prop has been used once, the counter value is pretty much random.
It could be done better that was just my first experiment in trying to randomly write bytes to the buffer.
Okay, I see you were calling your own code "feeble". I thought if you were calling someone else's code feeble you ought to at least give a reason why you think so. My mistake.
I personally like the idea of using the cnt counter as a random seed. I know others have thought the counter was reset with each start up so it would always generate the same seed value (which isn't the case).
Time to upgrade that 0603 IR LED to something more... special.
What percentage of time does the IrED spend on? Would an SFH 4715S work? It can take 1A continuous, 5A peak, and has two dies in series, so you can get a lot of radiant energy out of it.
I have a quick question about this driver. From what I can see it appears that most people just start up one instance of this object to control a long string of these LEDs. I've run into a case where some of the LEDs may not be plugged at all times and I don't want to break the chain of LEDs when they aren't there. I have extra I/O pins and extra COGs free. Is anyone using multiple instances of this driver to control multiple strings of LEDs?
I have a quick question about this driver. From what I can see it appears that most people just start up one instance of this object to control a long string of these LEDs. I've run into a case where some of the LEDs may not be plugged at all times and I don't want to break the chain of LEDs when they aren't there. I have extra I/O pins and extra COGs free. Is anyone using multiple instances of this driver to control multiple strings of LEDs?
Robert
Supporting multiple strings of LEDs was not supported by JonnyMac's original driver nor my C translation. Jon has since updated his driver to support multiple strings and I'm in the process of doing the same. Look for an update in the next few days.
I am just trying these out for one of my new robot projects. Are you talking about the driver that you've been writing in C for the Propeller? Is that going to do multiple strings?
I just downloaded JonnyMac's current driver from the OBEX and will see if I can use a couple instances to drive a couple strings.
I am just trying these out for one of my new robot projects. Are you talking about the driver that you've been writing in C for the Propeller? Is that going to do multiple strings?
I just downloaded JonnyMac's current driver from the OBEX and will see if I can use a couple instances to drive a couple strings.
Robert
Yes, I'm talking about my C translation of Jon's Spin driver. Actually, I pretty much use the PASM part of his driver with only a few changes. I've recoded the Spin parts in C and may also provide a C++ API as well since it matches Jon's Spin API better than my current C API does. If you're okay with Spin then Jon's driver is certainly the better choice as it leads mine as far as updates go.
At the moment I have been using SPIN on the Propeller but will definitely try out your driver when I try to use C. I think it is great that you're working on a native C driver for these.
Last night I wired up my first set of these. I have two different versions that I need to use on my project. Most are standard T 1-3/4 sized ones based on the WS2811 that I bought from Pololu:
I am also using some of the surface mount WS2812B LEDs that I bought from ebay. As a quick test I put them all on the same string. There were five of the WS2811 LEDs and then two WS2812B LEDs. Using the DEMO program on the OBEX they all worked the first time. I did notice however that the Red and Green colors are swapped on the two different models. After looking at the datasheets for both I can see where some of the confusion on color comes from in all the threads that I have been reading about these LEDs. It appears that the WS2811 based ones expect the color sent as RGB where the WS2812B based ones expect GRB data. In the driver code it looks like JonnyMac Is targeting the WS2812B and doing the RGB to GRB swap in the ASM portion which spits out the bits to the LEDs.
Since the WS2811 and WS2812B devices will probably be on different strings and each have there own IO pin it looks like I should be able to modify the driver to not swap the RGB to GRB as a different name and use that as another instance of the object. One modified for the WS2811 and the other for the WS2812B as it is.
As you are working on your C version of the driver perhaps it makes sense to add another flag to the portion that starts the driver to tell if the RG portions of the color should be swapped or not. That way a flag can be set when spawning the COG so that it would work for either style of these LEDs.
At the moment I have been using SPIN on the Propeller but will definitely try out your driver when I try to use C. I think it is great that you're working on a native C driver for these.
Last night I wired up my first set of these. I have two different versions that I need to use on my project. Most are standard T 1-3/4 sized ones based on the WS2811 that I bought from Pololu:
I am also using some of the surface mount WS2812B LEDs that I bought from ebay. As a quick test I put them all on the same string. There were five of the WS2811 LEDs and then two WS2812B LEDs. Using the DEMO program on the OBEX they all worked the first time. I did notice however that the Red and Green colors are swapped on the two different models. After looking at the datasheets for both I can see where some of the confusion on color comes from in all the threads that I have been reading about these LEDs. It appears that the WS2811 based ones expect the color sent as RGB where the WS2812B based ones expect GRB data. In the driver code it looks like JonnyMac Is targeting the WS2812B and doing the RGB to GRB swap in the ASM portion which spits out the bits to the LEDs.
Since the WS2811 and WS2812B devices will probably be on different strings and each have there own IO pin it looks like I should be able to modify the driver to not swap the RGB to GRB as a different name and use that as another instance of the object. One modified for the WS2811 and the other for the WS2812B as it is.
As you are working on your C version of the driver perhaps it makes sense to add another flag to the portion that starts the driver to tell if the RG portions of the color should be swapped or not. That way a flag can be set when spawning the COG so that it would work for either style of these LEDs.
Robert
I've already added that flag to my version. However, I don't have any WS2811 LEDs to try it with to verify that it actually works.
I didn't know you've already added that flag. Sounds like you have it all covered! I'm really happy with the 5mm T 1-3/4 WS2811's so far. They seem to fit in all the standard LED holders that I use and are a nice upgrade for projects that need the LED in a standard package. If you get a chance you may want to try one of those 10 packs of them.
I didn't know you've already added that flag. Sounds like you have it all covered! I'm really happy with the 5mm T 1-3/4 WS2811's so far. They seem to fit in all the standard LED holders that I use and are a nice upgrade for projects that need the LED in a standard package. If you get a chance you may want to try one of those 10 packs of them.
Comments
Will certainly post some pictures & video once it's all done. The final build will be spectacular.
I whipped up a variant that uses single-shot mode using a new method called .execute(). You specify the pin to use, the number of LEDs in the string on that pin, and a pointer to the array you want to use. If you want to use the object's internal array, specify 0 as the source data. You'll note that most of the methods have been updated (and a couple eliminated) to accommodate the new features.
I've attached a very simple demo with the new driver that uses the internal and an external array. Let me know if that works out.
[Edit] Did some code clean-ups, commenting, expanded the demo a bit.
If you're ever near Salt Lake City, ping me and I'll buy lunch.
Another thing i've been trying search the net to get a data sheet regarding the ws2812 but seem to come back to just the one datasheet that seems to have been poorly translated to english and I understand that you have to transmit 24 bit packets in GRB format what I can't see in the datasheet is what the bits correspond to, ie which part is the position of the pixel in the string (presuming 8 bits for up to 255) , the brightness control for a particular pixel etc.
Sorry for the questions but I don't have the Leds yet to experiment with.
Of course you're code as usual makes it easy to accomplish but I just want a better understanding as to how the WS2812 works
Is there a tutorial rather like your excellent Nuts and Volts DMX one that explains why and how the code is written?
@Skylight: The internal and external array feature came up interpreting JohnC's need to control multiple strings from a single driver. In most cases, we don't need to do that so you specify the internal array using 0 for the array pointer. Just to clarify... let's say you have a project that wants to control three separate WS2812 strings but only have one cog left. What you can do is use the single-shot driver and create two external pixel buffers. Using the single-shot methods you can update any of your buffers (internal or external) and when updated you can refresh a particular string by calling the execute method with the pin, led count, and pointer to the buffer to transmit. So, yes, there is an extra step to update any particular string but this allows the method to be very flexible and control as many strings of WS2812s as you can connect to a Propeller. Of course, you don't need a buffer for every string; in fact, in many cases I suspect the same buffer will be applied to multiple strings. This is part of the reason I added a count to the execute method -- it just updates the LEDs you have (or want to update).
Controlling the brightness of a pixel involves setting the RGB registers. For example, $FF_00_00 is red at maximum brightness. $3F_00_00 is red at 1/4 brightness. There is no separate brightness byte for each pixel; you're forced to manipulate the individual registers. There is a method in the driver that allows you to manipulate brightness by passing a fourth byte (it's called colorx).
My current (September) column in Nuts & Volts magazine has an explanation of the driver.
[Edit] In case it's not clear, the single-shot driver is a variation of the original, not its replacement. In my "Hollywood" work I do a lot of LED animation and need my string(s) auto-updated, hence I'll use the original driver.
The problem with controlling brightness this way is you lose color resolution. This is one downside to the WS28xx drivers. If you're controlling a bunch of LEDs with shift registers you can send a PWM signal to the enable pin to control the brightness. The WS28xx chips just are so darn convenient it's often worth losing the color resolution to save on the rat's nest of wiring required from the shift register option.
The RGB Christmas lights have a brightness component. I haven't played with them enough to know if you can adjust the brightness on those without losing color resolution.
We're using two of your modules in the firmware for our conference badge, this one and your awesome jm_irtxserial for badge to badge comms.
http://forums.parallax.com/entry.php/3510-SkyDogCon-2013-Badge-The-story-so-far...
Note the line of WS2812s along the top :-) They warm the regulators something special when they're at full whack so we're likely going to limit them in software.
We're still working on the IR side of the house, trying to get better distance. Time to upgrade that 0603 IR LED to something more... special.
Can you break this down for me? I'm especially curious why you make that seemingly random byte value equal "?cnt &ff"
What does the ? before the 'cnt' do
the random byte for 16 of the rgb leds.
Why is it a feeble attempt?
The counter doesn't reset to zero when the Prop is turned off. Once the Prop has been used once, the counter value is pretty much random.
Okay, I see you were calling your own code "feeble". I thought if you were calling someone else's code feeble you ought to at least give a reason why you think so. My mistake.
I personally like the idea of using the cnt counter as a random seed. I know others have thought the counter was reset with each start up so it would always generate the same seed value (which isn't the case).
When, I don't want to be bothered by loading/unloading RealRandom, I use cnt in the .seed method of of Michael Rychlik's (Heater?) PRNG code.
Robert
Thanks,
David
I am just trying these out for one of my new robot projects. Are you talking about the driver that you've been writing in C for the Propeller? Is that going to do multiple strings?
I just downloaded JonnyMac's current driver from the OBEX and will see if I can use a couple instances to drive a couple strings.
Robert
At the moment I have been using SPIN on the Propeller but will definitely try out your driver when I try to use C. I think it is great that you're working on a native C driver for these.
Last night I wired up my first set of these. I have two different versions that I need to use on my project. Most are standard T 1-3/4 sized ones based on the WS2811 that I bought from Pololu:
http://www.pololu.com/product/2535
I am also using some of the surface mount WS2812B LEDs that I bought from ebay. As a quick test I put them all on the same string. There were five of the WS2811 LEDs and then two WS2812B LEDs. Using the DEMO program on the OBEX they all worked the first time. I did notice however that the Red and Green colors are swapped on the two different models. After looking at the datasheets for both I can see where some of the confusion on color comes from in all the threads that I have been reading about these LEDs. It appears that the WS2811 based ones expect the color sent as RGB where the WS2812B based ones expect GRB data. In the driver code it looks like JonnyMac Is targeting the WS2812B and doing the RGB to GRB swap in the ASM portion which spits out the bits to the LEDs.
Since the WS2811 and WS2812B devices will probably be on different strings and each have there own IO pin it looks like I should be able to modify the driver to not swap the RGB to GRB as a different name and use that as another instance of the object. One modified for the WS2811 and the other for the WS2812B as it is.
As you are working on your C version of the driver perhaps it makes sense to add another flag to the portion that starts the driver to tell if the RG portions of the color should be swapped or not. That way a flag can be set when spawning the COG so that it would work for either style of these LEDs.
Robert
I didn't know you've already added that flag. Sounds like you have it all covered! I'm really happy with the 5mm T 1-3/4 WS2811's so far. They seem to fit in all the standard LED holders that I use and are a nice upgrade for projects that need the LED in a standard package. If you get a chance you may want to try one of those 10 packs of them.
Robert
Are they the same as the ones you bought from Pololu?
Those look like they are the exact same ones I used. They should work perfect to test the flag on your drivers.
It seems that Pololu has a bit better price on them now. I'm going to have to get some more of these.
Robert