I've been playing around with a single WS2801 25 LED strand from adafruit coupled

I’ve been playing around with a single WS2801 25 LED strand from adafruit coupled with an Arduino Uno for the past few days. If I understand it correctly, the FastSPI code would be beneficial to someone who would like to drive a large number of LEDs at the maximum refresh rate. However, due to the latch time of the WS2801, isn’t there a maximum refresh rate that can be achieved? I can’t seem to drive the WS2801 strip at faster than ~1.68 ms/refresh, even though the latch time is listed in documentation as 500us.

So, let’s say I was going to point an ultra-high speed video camera at the LED strip (40,000+ frames per second), is there any way to push the WS2801 faster?

Granted, my usage case may be a rare one, but it seems to be a puzzling problem nonetheless.

The WS2801, esp. the 5v strips doesn’t like getting pushed too hard, data wise. I think above a 1Mbit data rate gets it pissy. So - for 25 leds, that’s ~600 bits of data, which at 1Mbit gets you about 1666 updates/s max, using 100% of your CPU, and it’s possible data rates are going even lower - 500Kbit would be about 800fps, which if you factor in time spent in between pushes is probably close to what you’re getting.

The LPD8806 can push at higher speeds, i’ve been able to get strands under 150 up to over 20Mbit, which is closer to ~33,000 fps update rates, again, using 100% of your CPU time, however. Also - that is on the ARM based teensy 3, not AVR chips (which max out at somewhere around 4-8Mbit).

However - that said, I’m working (when I get the spare time! $DAYJOB and $LIFE are taking up a lot these days) on adding support for DMA data output on the teensy 3 - which, in theory, would let you hit that max data rate, saturated, then it’s just a matter of can you prep your frames fast enough?

Hi Daniel,

Thanks for the response and information. I’m seeing right around 600 fps, with the scale for the WS2801 controller set at 32 (anything less starts to get funky), and the delay between successive showRGB calls set at 1000 us. I don’t think I can go much faster with the WS2801

I’m thinking I’ll just have to switch to the LPD8806 with a teensy. I’m only worried about pure refresh rate, as I’m only displaying a single pixel at a time, racing around in a circle. Thankfully, I ordered a Teensy 3 a few days ago.

Yeah, because of the way these strips work, you have to write the whole frame at once. Out of curiosity, are you using FastSPI_LED or FastSPI_LED2? If the former, what value are you putting into setDataRate, if the latter, what value are you using in the template defintition for the WS2801?

I’m using FastSPI_LED2, with the template definition at 32. At 24, I only get ~18 LEDs lit up, and at 16 I just get general flickering around the strip.

Is there a way to latch the data on the WS2801 without using the 500us delay?

Yeah - that’s running the SPI clock at 1Mhz, which I can never remember if that gives an effective data rate of 500kbps or 1mbps (is the 1Mhz counting clock transitions or total cycles for SPI?), and is equivalent to a data rate of 3 with the old library.

(random aside, for hardware SPI on avr, only powers of 2 matter for speed selection - for software SPI the per-bit timing ends up being a lot finer because i can control how long i delay between each bit - and on the teensy 3 I play some games with some of the higher speed numbers and could get more density in place, but haven’t had a chance to, yet).

Interestingly, 24 and 16 should be the same if you’re using hardware SPI - because both have bit 4 as the highest bit set. Weird anyway, something else to look into…

No, the WS2801 really wants that delay - it might be as low as 50µs though. However, depending on how much work you’re doing - you can probably take some of that latching time up in, well, doing your work.

In fact, I think I already have code in the most recent FastSPI_LED2 preview release, that tries to ensure that a minimum of 50µs has past since the last time you finished writing data out to the leds and the next time you start writing data out to the leds - so you may not need to be doing any explicit delaying in your code.

(that’s another reason to like the LPD8806 - that uses a predefined bit sequence to make everything ready to listen for new bits, rather than time passing).

Also, it looks like that delay is 24µs for the ws2801, not 500 µs, at least that’s what I have in my code from what someone gave me in a data sheet at one point.

Indeed. I’ll double check the 24 vs. 16 tomorrow when I have the setup in hand again.

Interesting note on the 50us latch though, I’ve seen conflicting numbers for the actual delay needed to latch. I haven’t been able to get it running without a 1000us delay in the for loop. I’ll throw the rough code up tomorrow also, with some delays that are working for me.

One thing to keep in mind when running with no delays is that you are going to run into limits of human perception.

If I take code that turns one led out of a strip of 32 on at random, with the rest off, and run that at about 20000fps, it looks like the entire strip is just flashing white. If i then turn around and take a photo of that strip with a really fast shutter speed, I can see single leds turned on, with the rest off.

Anything beyond 50-100fps, and you stop being able to trust everything that you can see as far as updates, things start blurring together! :slight_smile:

Oh indeed! I wasn’t kidding when I said I had an ultra-high frame rate camera to point at it! :slight_smile:

I’ll be imaging the LEDs with a video camera capable of 100,000+ frames per second (I think it goes to 1.4 million fps, but it requires an insane amount of light). Will be interesting to see the results even with the WS2801, to see how close the timing is to advertised.

Eventually, I’d like to use the LEDs as a demo and setup calibration for the cameras, as its generally tough to get something very fast, repeatable, and easy to set up, in the field of view.

Here’s another problem you’re going to have, then - the ws2801’s do their color by PWM - I forget how many Hz the ws2801 PWM engine runs out - but now you also have the fun of where the individual leds are in their pwm cycle when you take video :slight_smile:

There’s a new chipset and leds out there that let you either change color by PWM or by current draw (TM1829, i think?). I have a couple chains of these on order and will be adding support for both modes. That might play nicer with application you’re thinking of - as it can do 32 levels of brightness by current (so, if the led is on, it’s no - not pwm/flashing to give an illusion of brightness) or 254 levels of brightness by PWM.

Hmm. I may be able to use that for imaging instead of blinking them - and by changing the brightness I could possibly change the delay they ‘blink’ at. Definitely something to look into tomorrow morning!

I’ll also look into the TM1829, that sounds promising. Thanks!

It also looks like some of the TM1829 products have the same form factor as the 12mm LED strips from adafruit. Huge bonus for me, considering I’ve already laser cut an enclosure. Phew.

I took at look at the 16 vs. 24 vs. 32 rate definition. Code below. Set at 16 and 24, only 18 of the 25 LEDs would light up, while 32 provided full color.

#include “FastSPI_LED2.h”

#define NUM_LEDS 25
struct CRGB { byte r; byte g; byte b; };
struct CRGB data[NUM_LEDS];

WS2801Controller<11, 13, 10, 24> LedController;

void setup() {
memset(data, 255, sizeof(struct CRGB) * NUM_LEDS);
LedController.init();
}

void loop(){
race();
}

void race() {
memset(data, 0, sizeof(struct CRGB) * NUM_LEDS);
data[0].r = 255;
data[0].g = 255;
data[0].b = 255;
delayMicroseconds(1000);
LedController.showRGB((byte*)data, NUM_LEDS);

for (int i=1; i<=NUM_LEDS; i++){
memset(data, 0, sizeof(struct CRGB) * NUM_LEDS);
data[i-1].r = 255;
data[i-1].g = 255;
data[i-1].b = 255;
delayMicroseconds(1000);
LedController.showRGB((byte*)data, NUM_LEDS);
}
}

ok - so I think it should be taking about 1.2ms per frame (500kbps is . .5 bits per µs, or 2µs per bit, 600 bits, 1200µs, 1.2ms). Combined with a 50µs delay that’s 1.25ms per frame - which should top you out at about 800 frames per second. What happens if you change the delayMicroseconds timing down to closer to 50-200 microseconds?

Also - what platform are you running on? I have a variety of arduino platforms here, and I believe I have a 5v ws2801 strip that I can run your test code against, but i’d like to play on as close to the hardware that you have as possible

Hi Daniel,

Running on an Arduino Uno R3, hardware SPI.

At 250us delay, the strip may be blinking - visually, it’s solid white. I’ll have to set the camera up and point it at it.

At a 250µs delay, that’s about 690 frames per second, or, to put another way, each led is lit 28 times (or once every 35ms, that becomes important below). Human vision is nominally 10-12 frames per second, but short bursts of bright light can stick around in vision for 100-400ms, hello persistence of vision - and now your leds are getting lit frequently enough that POV is burning the image in your perception long enough for the next 2-11 instances of that led being lit - and you now have given yourself a solid white :slight_smile:

Good times, no?

(btw - the timing numbers for persistence and such come from here - http://en.wikipedia.org/wiki/Frame_rate - so take them with a grain of salt).