adafruit / Adafruit_DotStar_Pi

DotStar module for Python on Raspberry Pi
GNU General Public License v3.0
60 stars 30 forks source link

Limit number of pixels to BLOCK_SIZE and/or spidev.bufsize #10

Closed fieldOfView closed 6 years ago

fieldOfView commented 8 years ago

With the default config, the hardware spi device can only send 4096 bytes at a time. This becomes a problem if you want to control >1000 LEDs (as each LED takes up 4 bytes). Software SPI is similarly limited by the BLOCK_SIZE define. The constructor should probably check against those limits.

Note that it is possible to increase the hardware spi device buffersize to eg 8192 (enabling up to ~2000 LEDs): https://www.raspberrypi.org/forums/viewtopic.php?p=837140#p837140 (newer kernels/RPI2) https://www.raspberrypi.org/forums/viewtopic.php?p=309582#p309582 (older kernels)

PaintYourDragon commented 8 years ago

Like any file I/O operations, large transfers through spidev should automatically be getting divided into BLOCK_SIZE pieces. Do you have an empirical test case showing this not happening?

BLOCK_SIZE totally doesn't come into play at all in the software SPI case; there are no file operations, just register twiddling.

fieldOfView commented 8 years ago

Do you have an empirical test case showing this not happening?

Jup. I connected 1200 LEDs and ran strandtest.py edited to use hardware SPI. If I set numpixels to 1024, I get 1024 pixels doing their thing. If I set numpixels to 1200 none of the LEDs work. Since then I have increased the bufsize and BLOCK_SIZE, and now I can get all 1200 pixels to work.

tibbon commented 8 years ago

Thoughts on how to work around this? I need to address around 20,000 pixels.

fieldOfView commented 8 years ago

I got it to work very reliable for 1200 LEDs like outlined above (increase BLOCK_SIZE and the size of buf, and increase the hardware gpio buffer); my installation has been running continuously for months now.

I don't know if that will work with 20,000 LEDs though. There may be a hard limit at 16384 leds (65,536 / 4). And if it works, I doubt the rate at which you can address all those pixels will be acceptable.

benpeoples commented 8 years ago

I just wanted to comment a thank you for the issue report. I ran into the problem and had gotten as far as finding 1024 as the limit (1025 = no output, 1024 = works).

I currently have an installation running with 6450 APA102 LEDs in a single chain. We're limited to about a 2MHz as the clock rate due to what I think is clock smearing over the 215m chain (which is limiting our framerate), but otherwise working great.

timonsku commented 8 years ago

@benpeoples I was wondering what you did to get that insanely long strip going? Insert power every meter? Any special modification to the strips?

I'm currently trying to get a 12m a 144 leds per meter strip going but also experience clock "smearing"/shifting at my desired clock of 8MHz. Do you by any chance know what the maximum amount of LEDs was that you could drive with 8MHz?

benpeoples commented 8 years ago

We just used stock strips, but at 30LED/m we were able to inject power every 5m at each end. They worked reasonably well at 10m, so it survived well as the system aged.

We had a weird design requirement that the whole system had to be fed from a single power supply-- it was a 215m spiral with the power supply at the center. We bussed # 6 THHN along both sides of the LEDs and then ran spokes of # 6 out to the bus. I modeled the whole thing in a circuit simulator to size the bus wires. We also didn't need to light up all of them at once, which helped. We were able to do a single color over the whole thing at near to the full current rating of the system.

However, the glitching effects were much more pronounced where we had voltage droop (typically due to broken spoke joints), so I'd start there-- get as close as you can to 5V everywhere-- inject power as needed to do that.

This is a video of the installation (which is no longer there-- was a temporary 6 week installation).

timonsku commented 8 years ago

Thanks a lot for your quick answer! I also noticed the harsh effect a slight voltrage drop has on the LEDs when calibrating my 5V supply.

Cool installation btw! Is the slight stuttering by design or from the low clock speed?

benpeoples commented 8 years ago

That's the low clock speed (and possibly some slightly imperfect animation frames-- it was hand drawn without an overhead view)-- If I remember correctly, this was a 9 frame animation that loops twice to make one revolution.

timonsku commented 8 years ago

Well it makes for a cool effect in this case! Thanks again for your input! I'm still amazed that you could use a single PSU. I'm currently using 2x 120A PSUs for a 8* 144LED.setup to get a flicker free animation at 8MHz.

gaitskell commented 7 years ago

For modern raspberry pi jessie distributions there is now a very simple solution to increase the maximum # of APA102 / DotStar LED being driven by RasPi-Jessie. (I record it here for anyone who is searching for the solution.)

See - https://www.raspberrypi.org/forums/viewtopic.php?t=124472&p=837140

There is now a single boot setup addition (don't need to follow more complex solutions of old)

Quote from notro: The spidev module is built into the kernel proper (kernel7.img), so you have to set the module parameter on the kernel command line.

SOLUTION: As su add to the end of the line of parameters in /boot/cmdline.txt:

spidev.bufsiz=32768

After reboot this raises the SPI hardware buffer default from 4096 bytes (given 4 bytes per LED command this limits write to 1024 LED pixels) to 32768 bytes which would allow 8192 LEDs.

I tested this and it works with hardware SPI. I think you will need to modify .c code further for bit banging solutions (software SPI).

PaintYourDragon commented 6 years ago

Issue is now resolved without having to edit spidev.bufsiz in cmdline.txt. Exceptionally long transfers will be issued in multiple SPI writes if needed.

At least, I think so. Don't have a strip that long to test with, but it's derived from some TFT SPI code that's known to work.