millis() and EVERY_N_MILLISECONDS on a Particle Photon This may be related to the weird

millis() and EVERY_N_MILLISECONDS on a Particle Photon

This may be related to the weird behavior I am seeing with the EVERY_N_MILLISECONDS function (https://plus.google.com/111050398964612063307/posts/cpg64983KDL)

I’m trying a bpm (beats per minute) pattern with ~680 LEDs on a Particle Photon, but it’s animating super slowly. So I added millis() printouts at the beginning and end of the pulse() function to see how long it’s taking. The results are bizarre – it’s like the millis() timer jumps back and forth by 36 seconds!

See the attached screenshot for the weird timing results. The code is in the link below, and also in that thread, someone indicates that FastLED’s delay function may mess/conflict with Photon’s timer though

Anyone have experience with this on the Particle Photon (formerly Spark Core), or ideas on what could be causing the weird timer printouts? My next step will be to try eliminating all uses of EVERY_N_* and replace them with just the raw millis() function.

1 Like

Maybe you’re using WS2812 LEDs, and maybe the WS2812 driver is disabling interrupts to bitbang the precise WS2812 timing?

Some of the WS2812 drivers for some platforms try to undo the damage they did to millis by manually incrementing it by the amount it should have increased during the amount of time they used to send all the WS2812 bits. But that often doesn’t work out well, especially if the driver hasn’t received a lot of testing on a particular platform (pretty much anything other than AVR).

On some platforms there are non-blocking drivers/libraries for WS2812. Not sure about Photon. If there isn’t, your options may come down to 3 undesirable choices: dig into the driver’s millis fixup algorithm, or use different LEDs (like APA102), or use a different board with non-blocking drivers.

Of course, this is all based on a blind guess you’re using WS2812 and the driver which blocks interrupts…

Thanks @PaulStoffregen . I am using WS2813’s, so your explanation certainly seems feasible. Plus I didn’t have this problem on Arduino, so it definitely seems platform-specific.

What really puzzles me is how I can run code like this:

void pulse() {
unsigned long time1 = millis();
uint8_t BeatsPerMinute = 62;
CRGBPalette16 palette = PartyColors_p;
uint8_t beat = beatsin8( BeatsPerMinute, 64, 255);
for( int i = startPixel; i <= endPixel; i++) {
leds[channel][i] = ColorFromPalette(palette, gHue+(i2), beat-gHue+(i10));
}
FastLED.show();
unsigned long time2 = millis();
Serial.println(String(time1) + " - " + String(time2));
}

And get output like this:

280696 - 316490 <-- 35794 milliseconds!
280796 - 316588 <-- 35792 milliseconds!
280896 - 316688 <-- 35792 milliseconds!

I’m calling this function every 100ms. My function is definitely not taking 35 seconds to run. :slight_smile:

Re-reading the http://particle.io forum thread that I linked in my original post-- someone states:

Looking at the FastLED library2 in your code, I see two things of interest:

1) It seems to be playing with the value of DWT->CYCCNT for timekeeping purposes. This is also used by the Photon’s time functions, so there may be some bad interactions happening.

2) It looks like interrupt enabling is disabled1 for STM32 devices for whatever reason, which may be a bug in the library, so you might want to change that and retry to see if you recover more time.

So I’m wondering if this is actually something in the FastLED library (and if so, what?)

More data here. I’ve narrowed it down to FastLED.show() that is causing the weird output of millis() data, where it increases and then later decreases (at the beginning of the next function call).

From the http://particle.io forum thread, it sounds like the problem could be caused by FastLED.show:

According to the FastLED docs I linked you to, show() disables interrupts, which in turn means a SysTick timer interrupt is potentially dropped if interrupts are disabled for > 1ms.

I tried adding #define FASTLED_ALLOW_INTERRUPTS 0 but it didn’t make any difference.

Any other ideas for how to address thid with FastLED? What really puzzles me is how millis() gets temporarily advanced by 37 seconds, but then gets reset the next loop. Though maybe that’s indeed reset on every loop?

maybe re-read my prior comment?

@PaulStoffregen – yes, based on narrowing it down to FastLED.show(), I suspect you are correct and was hoping there would be a way to address this without messing with the guts of FastLED (your option 1) which I could see turning into a rabbit-hole.

After posting, I also realized that I was thinking incorrectly about the FASTLED_ALLOW_INTERRUPTS flag.

options 2 & 3 are much easier, though perhaps unpleasant if you’re already deeply invested in those LEDs and that particular microcontroller.

Yep, and we are. I’ll just work around this limitation by avoiding patterns that need to run so quickly. The strange thing is, my chase pattern is able to run faster, so I’m not sure why it isn’t equally as affected. More research needed. Thanks for your help, Paul, I appreciate it.

Well, at least you know you can end the pain anytime, by buying APA102s or adding another microcontroller with better driver support.