New Embedded/Arduino/FastLED ( 3.0.2 ) user, old programmer. Was wondering if there was a reason that the FastLED.delay(ms) loops with delay(1); show(); since that will make it hard to hit a specific timing with the clockless chipsets which do not need refreshing and take a long(ish) time to show. I’m just wondering if there was some logic to this.
void CFastLED::delay(unsigned long ms) {
unsigned long start = millis();
while((millis()-start) < ms) {
::delay(1);
show();
}
}
I ended up writing my own delay which loops on polling buttons and other downtime activities.
The FastLED delay code has evolved over time and you raise a good point: why is that there since we have the rate-limiting controls in show() now. The answer might now be “historical reasons”… or maybe there’s something important that I’m forgetting. I’ll talk with @Daniel_Garcia .
I understand “historical reasons”. Is there an easy way to determine the rate limiting defined for a specific controller ( say the WS2812B )? The default seems to be “50” for CMinWait in ClocklessController2, but given that CMinWait works in micros, I don’t understand how it has enough time to properly latch.
I’ll let Dan speak to the timing details; he’s lived right in the middle of that hurricane for a couple of years now.
Not historical, still somewhat current reasons:
-
FastLED.delay loops with show to allow the dithering engine to run (while you are right that chipsets “do not need refreshing”, they do if you want to run dithering between the frames).
-
FastLED.delay calls ::delay(1) in between calls to show to ensure that the clock gets a chance to advance, at least a little - on some platforms, with few enough leds, because of the blocking of interrupts that happens, the millis timer may not advance (or advance enough) during a call to show, which could cause an infinite loop inside of delay because millis never advanced. On platforms where interrupts are allowed to allow the sysTick timer to advance, this is less needed, and the call to ::delay(1) is gated by a compile time flag for the platform, on whether or not we know that the clock is accurate.
-
CMinWait is less about rate limiting and more about allowing for enough time for the previous frame’s data to be latched in and shown (which is ~50µs).
-
The FastLED3.1 branch adds the beginnings of refresh rate limiting, with LEDS.setMaxRefreshRate(uint16_t refreshRate) which lets you set a ceiling for the refresh rate in Hz, which right now blocks show when it is called to prevent the refresh rate from going above a certain number (which defaults to 400 on the 3.1 branch). I still need to add a method to check and see whether or not a call to show would block so that the caller could decide whether or not to call show or continue doing other things.
Thanks, that would make some sense.
I added a FastLED.show() into my delay loop and I can keep 100-200 fps which should be enough for dithering to be fully enabled.