I'm attempting to build a spherical persistence of vision display using a 26" bicycle

(Gabriel Levy) #1

I’m attempting to build a spherical persistence of vision display using a 26" bicycle wheel mounted axially at top and bottom on a 36" shaft. I have 40 WS2801 leds mounted around the wheel (20 on a side) such that the lights trace out a sphere when the shaft spins. The system is driven with an Arduino Uno. I’m hoping to achieve 16fps on the full image which requires the wheel to spin at 480rpm. That means the wheel makes a full turn every 125ms So, to draw an image 40 pixels wide, I need to refresh the entire strip of 40 leds 80 times within 125ms. (one update to draw the column and another to draw black before drawing the next column).

It seems the best I am able to achieve with FastLED using hardware SPI is ~170ms for 80 calls to show() on a strip of 40 pixels or 2.125 ms per show() call. This is with a very simple loop to cycle through a static array of color values. Does this sound like expected timing? Can someone help me understand how to calculate the expected refresh rate? (datasheet says 2.5khz but I’m not sure how to interpret that).

Any suggestions to speed things up?

Any help is much appreciated!

LEDs: https://www.adafruit.com/products/1547

(Daniel Garcia) #2

WS2801 leds are run at 1Mhz, - or a maximum of 41,000 rgb led updates/second (or ~1000fps for 40 leds) - you want 640fps for your update rate. One thing that is possibly limiting you is that FastLED has some code in it to block frame rate from being above 400fps (to work around some issues with the WS2812) - grab the most recent FastLED3.1 branch, that frame rate limiter is now only on by default if you’re using WS2812’s. That might help up your frame rate a bit.

Also, you can try driving the WS2801’s at a higher speed (just watch out, they might start glitching out) - by doing:

LEDS.addLeds<WS2801, RGB, DATA_RATE_MHZ(2)>(leds, NUM_LEDS);

You can use that DATA_RATE_MHZ parameter to try increasing the SPI data rate, and hopefully your 2801’s will be able to handle cranking it (the maximum meaningful value for DATA_RATE_MHZ will depend on your hardware, max data rate for the uno is 8Mhz, max data rate for the teensy 3/3.1 is ~24Mhz).

Finally, make sure that you are using the hardware SPI output, and not another pair of pins (which will result in bit-banging the led output which will slow things down)

(Gabriel Levy) #3

@Daniel_Garcia Thanks so much for the response! I am using the latest FastLED3.1 as of last night. And I am using the Uno’s hardware pins (11 data, 13 clock). Sounds like I’m within spec for a 1Mbps data rate. 40 px * 24b/pix * 80 f/rev * 8rev/s = 614kbps < 1Mbps. There must be some delay I’m not considering? In any case, I really appreciate the suggestions and I’ll try upping the data rate.

Does FastLED provide a way to turn all pixels black without actually signalling each one? e.g. cutting power to the entire strip and restoring it after some delay. If so, it would effectively halve the # of frame updates.

Really impressive library btw. It’s well-designed, easy to use, and incredibly powerful. Thank you for all your work.

(Daniel Garcia) #4

So this is why I double checked on the FastLED version you’re using, because it’s sounded like it might’ve been throttling - also, show does have some overhead (though I’m pretty sure it shouldn’t be a full ms).

(It’s also possible that gcc is doing some code re-ordering on things internally that are interfering with some optimizations i have around prepping data for sending out/sending out data - i’ll do some more testing on that) - but in the meantime, try playing with juggling the DATA_RATE_MHZ values.

As for turning all the pixels black - the only way FastLED has to do it is pushing data out. You’d need to add hardware to your setup to be able to cut power to the leds. Be aware, some led chipsets (I don’t remember offhand if WS2801 is one of them) will remember the last value they were set, and come up with that when power is on. Also - I’ve seen some led chipsets take a little bit of time to come up, so you can’t just turn them on and immediately start sending data (so you’ll want a little bit of a gap between when you turn them back on and when you start pushing data to them).

(JP Roy) #5


Very interesting project, I hope you come back and show what you have built !

I would swap out that UNO with a Teensy3.1. Just remember they operate at 3.3V and you will need logic level converters to 5V.

You also mentioned… (datasheet says 2.5khz but I’m not sure how to interpret that)

This is the PWM frequency that the WS2801 uses to control the pixel brightness. Even without any data updates, the ws2801 will pulse the LEDs 2,500 times per second. The ON to OFF ratio of that pulse is controlled by the last RGB brightness data it received.

Not at all experienced with POV projects but would think that since it is 4 times faster than your planned 640fps, that should be good !

(Gabriel Levy) #6

@Daniel_Garcia Pleased to report that changing the data rate worked. 2 Mhz brought the time down to 133 ms. 4 Mhz brought it down further to 121 ms, under my 125ms threshold. Now to add adaptive delays to try to stay steady at 640fps regardless of the image complexity.

BTW, the template instantiation for addLeds<ESPIChipsets CHIPSET, EOrder RGB_ORDER, uint8_t SPI_DATA_RATE> is ambiguous with addLeds<ESPIChipsets CHIPSET, uint8_t DATA_PIN, uint8_t CLOCK_PIN>. I used addLeds<ESPIChipsets CHIPSET, uint8_t DATA_PIN, uint8_t CLOCK_PIN, EOrder RGB_ORDER, uint8_t SPI_DATA_RATE> to work around. Might need to rearrange or add params to disambiguate.

Thanks so much for your help. I’ll post a video once this beast is done.