Well, that is, if you’re using a Teensy 3.0/3.1 and the FastLED 3.1 branch. Starting today, the WS2812 (and other, sadly forgotten by most clockless chips like the TM1809, UCS1903, LPD1886 - you live on in our hearts and old installations!) support on Teensy 3’s no longer blocks interrupts[1].
What does this mean, real world for you? Well, for one, the clock goes back to being accurate (as accurate as it ever was) - no more drift from the library attempting to adjust the time for while interrupts were disabled.
[1] To be honest, it’s not that the library doesn’t block interrupts, instead, what it does is allow interrupts briefly between each LED’s worth of data. If an interrupt takes longer than (in the case of the WS2812) 45µs, then it punts on writing the current frame out. If you’re running at a high enough refresh rate, it is unlikely you’d notice this happen. Also, if you have code that is spending more than 45µs in an interrupt handler, you need to set the author of that interrupt handler on fire[2].
[2] this realization brought to you by an as yet unnamed (coughnordiccough) platform provider of a combination bluetooth/cortex M0 setup whose interrupt handlers would run for nearly a millisecond at a time.
Not for the teensy - however there is a company out there, NXP, that makes an 8-pin, 32Mhz, Cortext-M0+ that is on my list of near future platforms to start supporting so that people who want the ATTiny form factor can get more power. (that chip, by the way? Lower power draw than the ATTiny85 - and that’s even before you take into account the fact that being a 32-bit platform you get more per clock cycle, and oh, you’re getting 2-4 times as many clock cycles as you would with that ATTiny
You might consider writing to the ARM BASEPRI register before beginning the timed output. Lower numbers are higher priority. A value like 160 or 192 might be good, to block really low priority interrupts (which might take long times), but allow the higher priority interrupts to run. Of course, restore BASEPRI when you’re done!
Thanks! I’ll dig into playing with that a bit more. Though, for the time being, I think it’s ok to allow any interrupts to run and cut off the frames, mostly because I’ve run across systems where things get really upset if (even low priority) interrupts get delayed for too long - and it’s the kind of thing that’d be really dicey to debug w/a library user remotely. I’ll see how this fans out - I may be able to also make it a configuration options to let people chose their own thresholds.
The audio library is probably the only one right now that takes up a lot of CPU time, at a low IRQ priority. The audio update happens every 2.9 ms, so yeah, if you delay that interrupt for 2.9 ms (less the time it actually needs), you’ll glitch the audio output.
I’m re-enabling interrupts every 30µs to let anything that wants to run, try to run - so hopefully nothing should get starved. How much CPU time does the audio library audio update consume? (I used this trick on a contract job recently where I was sharing pushing out WS2812 data w/a bluetooth stack that was really touchy about delaying interrupts (it would wedge the entire device) and also liked really long interrupts (1ms!). My vote for switching over to APA102’s (starting from months ago, for that matter) was shot down
The audio CPU time depends on how much audio processing you try to do. Really, it depends how many of the objects you drag and wire together on this web-based GUI canvas:
Just drag in the variable filter and you’ve used 2%. Connect a signal to the control input and now it consumes 4%. But for that 4%, you get a low+band+high pass filter with the corner frequency controlled in real time by another signal!
So, does this mean I have a greater chance getting the IR library running at the same time as FastLED with WS2812B’s on an UNO? Or, is this just reserved for those lucky Teensy owners?
Actually just ARM users in general (i’ve been able to make this technique work on a 16Mhz CortexM0 as well as the teensy’s 96Mhz CortexM4, and I’m working on a solution for the Due’s CortexM3). Unfortunately, I have not been able to reliably make this work on AVR based platforms yet (and from what i’ve been seeing, arduino interrupts are really really slow - and the cost of checking the things I need to look at to catch whether or not an interrupt has run too long are expensive enough that it just causes all sorts of fun timing problems). I wouldn’t completely rule it out yet, I haven’t given up on it, however AVR seems to be delighting itself in making this a difficult problem.
All that said, if you’re invested in staying on AVR, I would strongly recommend looking into switching to 4-wire led chipsets, like the APA102 which have no issues with interrupts at all, no matter what the platform is.
@Andrew_Tuline Would you believe I have IRremote on my to-do list for next year, to convert to more fully leveraging DMA transfers and the special carrier modulator hardware on Teensy 3.x? It’s one of the few libraries that still needs very low interrupt latency on Teensy3… and my long term goal is to make all the widely used libraries fully leverage the great hardware capabilities so they can be combined in almost any way without the terrible conflicts that plague 8 bit processors.
I just checked in code on the FastLED3.1 branch that allows interrupts to run w/WS2811’s. As with the teensy, if your interrupt handlers run too long while writing out a frame, that frame will get cut short. Of course, unlike the teensy, you only have a window of about 500 clocks to do your interrupt handling in (as well as the rest of the AVR interrupts).
There’s a potential for conflicts when pins touched by interrupts are on the same port as the LED pin - thinking about ways to mitigate that. (And, actually, have a solution, brb)