FastLED / FastLED

The FastLED library for colored LED animation on Arduino. Please direct questions/requests for help to the FastLED Reddit community: http://fastled.io/r We'd like to use github "issues" just for tracking library bugs / enhancements.
http://fastled.io
MIT License
6.43k stars 1.63k forks source link

Slow performance on Teensy3.0 #168

Closed jsonpoindexter closed 9 years ago

jsonpoindexter commented 9 years ago

Hi,

I recently benchmarked some WS2811 LEDs on the FastLED Library and the Adafruit_NeoPixel library using a Arduino Uno R3 and a Teensy3.0.

The results were an average of displaying a rainbow across 16,32,64, and 128 LEDs 100 times.

The FastLED library benchmarks much better than the Adafruit_NeoPixel library when running on the Arduino Uno R3, but the FastLED library benchmarks BELOW the Adafruit_NeoPixel library when running on the Teensy3.0.

Here is a google spreadsheet of my results, including the sketches I used: https://docs.google.com/spreadsheets/d/1RgUsG_JmDcpWTDbR58tOUuVoOa9vJamnfgR6jG3nF28/edit#gid=0

focalintent commented 9 years ago

What version of FastLED are you using? Also - you can't rely on using micros/millis for timing, especially when comparing adafruit's library (which disables interrupts, which means that the time interrupt isn't ticking while leds are being written out) and FastLED (which disables interrupts but attempts to compensate for timing on, but not always accurately, depends on what version of FastLED you are using).

focalintent commented 9 years ago

Also, be aware that I have some code in place in FastLED that attempts to limit WS2812 led output to 400fps, as refresh rates above that can cause problems for the leds.

CSMR-DB commented 9 years ago

Following this thread with interest for possible Ambibox performance increase. Do you happen to have a string of APA-102's and/or a Pro Micro 32u4 laying around to bench by any chance? Or would you say this would not improve screen grabbing performance?

On Thu, May 21, 2015 at 11:51 AM Daniel Garcia notifications@github.com wrote:

Also, be aware that I have some code in place in FastLED that attempts to limit WS2812 led output to 400fps, as refresh rates above that can cause problems for the leds.

— Reply to this email directly or view it on GitHub https://github.com/FastLED/FastLED/issues/168#issuecomment-104207521.

focalintent commented 9 years ago

Also - some math to help show how your adafruit library numbers are whacked. Writing a single WS2812 led takes 30µs. There's no negotiation on this, you write data faster than that, you get corrupted data. This means that your frame of 128 leds will take 3.84ms to write. Which means your maximum frame rate for 128 leds, assuming you're spending 100% of your time writing led data is 260fps. Your neopixel library numbers claiming 485fps are completely out of line with the physical timing constraints of the leds. (Though, again, this makes perfect sense with the fact that you can't trust millis/micros timing across calls to write led data with WS2812 and friends w/the adafruit library. I'll look into the discrepancy on the teensy 3 numbers, but I suspect that has more to do with my timing adjustment attempts than real world clock differences).

@Fid3lity, I don't think this ticket will be useful for you to follow at all. A Pro Micro won't change the timing numbers on an arduino uno, the 328p and 32u4 are effectively the same for all purposes other than serial vs. usb. APA102 leds will help you a lot with frame rate, but that's because you can write an APA102 in as quickly as 4µs on an uno/pro micro and 1.3µs on a teensy 3/3.1.

CSMR-DB commented 9 years ago

Sounds fair. I can tell that from my experience the Pro Micro helped somewhat over the Uno. Don't have exact numbers since I played with the settings and all in the meantime. But running on a Teensy 3.1 did not seem to help as much as the Pro Micro did when upgrading from the Uno. So here's me hoping to get some Eureka moment in this thread. Who knows :)

On Thu, May 21, 2015 at 12:00 PM Daniel Garcia notifications@github.com wrote:

Also - some math to help show how your adafruit library numbers are whacked. Writing a single WS2812 led takes 30µs. There's no negotiation on this, you write data faster than that, you get corrupted data. This means that your frame of 128 leds will take 3.84ms to write. Which means your maximum frame rate for 128 leds, assuming you're spending 100% of your time writing led data is 260fps. Your neopixel library numbers claiming 485fps are completely out of line with the physical timing constraints of the leds. (Though, again, this makes perfect sense with the fact that you can't trust millis/micros timing across calls to write led data with WS2812 and friends w/the adafruit library. I'll look into the discrepancy on the teensy 3 numbers, but I suspect that has more to do with my timing adjustment attempts than real world clock differences).

@Fid3lity https://github.com/Fid3lity, I don't think this ticket will be useful for you to follow at all. A Pro Micro won't change the timing numbers on an arduino uno, the 328p and 32u4 are effectively the same for all purposes other than serial vs. usb. APA102 leds will help you a lot with frame rate, but that's because you can write an APA102 in as quickly as 4µs on an uno/pro micro and 1.3µs on a teensy 3/3.1.

— Reply to this email directly or view it on GitHub https://github.com/FastLED/FastLED/issues/168#issuecomment-104210431.

focalintent commented 9 years ago

Well, for ambilight type stuff, likely where you are seeing the improvement is switching from serial to native usb support, allowing data to get pushed to your controller faster. (which has nothing to do with what the person who opened this ticket Is attempting to measure)

jsonpoindexter commented 9 years ago

Thanks for the reply focalintent.

I am using FastLED 3.0. I was not aware of the problems when using millis/micros timing across the WS2811 and that makes a lot more sense now.

kriegsman commented 9 years ago

Thanks for the detailed ticket-- always great to see someone willing to dig in and get down to the next level.

So after looking at it all, I basically agree with what Dan said:

I'm curious to learn what you see when you use an external timing source. Please let us know!

jsonpoindexter commented 9 years ago

Thanks kriegsman. Can you suggest a valid external timing source?

Would using something like Processing work via Serial? Arduino/Teensy Sends start signal to processing > processing timing starts > LED animation runs on Arduino/Teensy > Arduino/Teensy sends signal stop signal to processing. Seems like with this method it could open the bench-marking up to more variables such as time it takes to send serial communication between the devices.

Another thought I had was to set a IO pin to go high/low before and after running the animation with another Arduino/Teensy that uses the high/low as a stop watch. (From this thread I gather the Micro/Mili inaccuracy is due to LED librarys. If I run a sketch that only reads an IO pin should this improve the accuracy?)

Thanks for the input!

kriegsman commented 9 years ago

That would work... And as you pointed out, it has some "noise" in the data too.

Me, I tend to do things this way: write a loop that does the task-to-be-timed repeatedly forever-- but with a simple counter in the loop. Every 100 (or 1000 or as needed) times through the loop, have it print the loop counter.

Then I sit there with a stopwatch and push Start, let it go 10,000 iterations, and push Stop.

Basically: manual testing! The overhead of printing and serial comm is minimized. There is some noise in the data from my reaction time, but I tend to do several trials and take the median. Also, having each print be 10,000 loops (or 1,000 or whatever) tends to dilute the noise down to a point where it's less than 1%, which is all I usually care about.

When I need better-than-1% accuracy, I either just let the loop run 1,000,000 times, and time that manually, or use an on-board realtime clock. Of course, they're typically only precise down to one second resolution, so you still need a large number of trials before "1 second of error" is less than (say) 0.1%.

Short answer I guess is: use a large number of trials in each run -- and a stopwatch!

jsonpoindexter commented 9 years ago

Hi everyone,

I finally got around to running, and documenting, some benchmarks using an external timer. I ended up using Processing.

focalintent was correct. When using an external timer the results were no longer outside the physical limitations of the WS2811, and also were more consistent with what we would expect: the FastLED being faster on than the Adafruit_NeoPixel library and faster on the Teensy than the Arduino.

Technical documentation can be found here: http://www.kentuckyfriedfrank.com/2015/05/benchmarking-led-libraries-fastled-vs.html

marmilicious commented 9 years ago

Nice work Frank Jason. Thanks for putting that together.

jsonpoindexter commented 9 years ago

No problem! Seems like the external timer method using Processing can come in useful in the future, especially for those freaks who want make sure they are doing everything as fast as they can (which should be everyone).

I am still a little confused about why the performace switch when comparing the Arduino Uno and Teensy External and Internal timing methods using the FastLED library. On the Uno it showed a slower bench-mark when using the External timer compared to the Internal timer and then on the Teensy it showed a higher bench-mark on the External timer compared to the Internal timer. It was the only case that was not consistent. Makes me wonder if maybe some of my data is wrong.