FastLed vs Neopixel vs Audio library - CPU overload?

Status
Not open for further replies.

Phyxtra

Member
Hey there!
I try to point out my problem short - I have a ws2812b neopixel led strip with 144 led / m. I want to let them flicker and do some animations. Working great on pin 7 of the teensy 3.2.

I also have the prop shield generating some sine waves mixed together based on gyro data. (and yes, it'll be a lightsaber :D finally managed to synthetically generate the lightsaber sound using 14 sine waves having the values of the fft of the original from the movies)

Both working fine, but individually. I put together both codes to have the led control and the audio output, first try with the fastled library. Problem: only half the led strip is on, seems the audio processing takes too much CPU usage to be fast enough to cycle all the LEDs.

Then I tried it with the neopixel library. There, LEDs are working fine but the audio output cracks every time leds.show() is called (in every loop iteration for the animation).

The prop shield buffer is just meant for apa102, as I read. The buffer could fix the problem when using fastled again, but I just have ws2812b and they stay off when connected to the prop shield.

Any ideas if this really is a CPU overload problem or other ways to solve this issue, maybe with "pseudo" threads?

Thanks and cheers,
Daniel
 
Last edited:
I suspect you have several things going on.

Note, that ws2812b LEDs are timing sensitive. There is only one data pin, and you HAVE to deliver the data in the timing window specified. The Adafruit library does this by turning off interrupts while the whole 144 LED string is updated. I believe the FastLED library tries to be clever and allow interrupts, but as you mention things get messed up.

You mentioned using pin 7 for the neopixels. If you are using the prop shield, the prop shield uses pin 7 as a control of whether to do level shifting for pins 11 and 13. So you can't use pin 7 with the prop shield. If you wanted to use the prop shield level shifter, you would have code like:
Code:
void setup (void)
{
  pinMode (7, OUTPUT);
  // anything else
}

void loop (void)
{
  // other code
  digitalWrite (7, HIGH);   // enable LED level shifting
  pixels.show ();     // do the neopixel thing
  digitalWrite (7, LOW);  // allow pins 11 and 13 to be used for other things
  // other code
}

The prop shield uses:
  • Pin 2 for i2c interrupts;
  • Pin 5 for audio enable;
  • Pin 6 for SPI CS for the flash memory controller;
  • Pin 7 for enabling/disabling the level shifter for the LEDs;
  • Pin 11 for SPI MISO and for level shifting;
  • Pin 12 for SPI MOSI;
  • Pin 13 for SPI SCK and for level shifting;
  • Pin 18/A4 for i2c SDA;
  • Pin 19/A5 for i2c SCL; (and)
  • Pin A14 for DAC output.

Now, there is the issue I had when I tried to mix using the Adafruit neopixel library with things that do SPI (flash memory on the prop shield, TFT displays, etc.). If you look in my query, KurtE replied on how to switch from SPI mode to normal digital write mode, and back:

One kludge way to solve the problem is add a Teensy LC that just does neopixels. Do everything else on the 3.2. Have some simple communication from the two teensys, of what sequence to use (i.e. use i2c, serial uart, or just have a few pins that when set high mean start an action). You would need to connect at least the grounds (you presumably can connect VIN too if you are careful to only have one power source at a time). The advantage is the LC has a builtin level shifter that converts pin 17/A3 to 5v output for the neopixels.

Another way is to think about switching to APA102 (dotstars) which are less timing senstive, but need both a data and clock pin to do the LEDs. It is probably cheaper to get an LC, though whether you have enough space for both teensys, I dunno.
 
Last edited:
For more than about 50 WS2812 LEDs together with the audio library, OctoWS2811 is really the only viable path. The others all conflict with the interrupts needed for audio. Only OctoWS2811 leaves the CPU free and interrupts enabled during the LED updates.
 
Thank you both very much :) Paul, I now use the OctoWS2811 library, but as soon as show() is called, the audio stops at all. Did I do something wrong?

EDIT: Ok it's the pin layout as I read from other threads. Might need to make some adjustments
 
Last edited:
Is it possible to modify the Octo lib so it just outputs at pin 7? I commented out the other pins, but that didnt change anything. For the rest of the librarys code, I'm not familiar enough with registers, DMA and the bitshifting stuff.
 
Is it possible to modify the Octo lib so it just outputs at pin 7? I commented out the other pins, but that didnt change anything. For the rest of the librarys code, I'm not familiar enough with registers, DMA and the bitshifting stuff.
Yes you can I have a hacked copy of the octo lib that I used with the prop shield. If you want to try it out i can post it on github?
 
Alternative that unfortunatly means ordering different LEDs are the SPI based ones that work much better with interrupts active (hence prop shield having the level converter on the SPI port).

When you get it settled would be interested in seeing how you modulate against the sensors. I used what I suspect is a similar bank of sine generators, but didn't find a way I was happy with to parse motion sensing into modulation of the sound effects that didn't end up over driving into noise at least some of the time.
 
Yes you can I have a hacked copy of the octo lib that I used with the prop shield. If you want to try it out i can post it on github?
Oh wow, that would be awesome! Thanks :)

When you get it settled would be interested in seeing how you modulate against the sensors. I used what I suspect is a similar bank of sine generators, but didn't find a way I was happy with to parse motion sensing into modulation of the sound effects that didn't end up over driving into noise at least some of the time.
The essential of all sine waves are their amplitude and their frequency, I'd say even the amplitude is more important on the lightsaber. I used Audacity to make a fft (or in later versions I guess it's called spectrum) and took the 14 first peaks starting with around 25Hz. The corresponding amplitude is given in db, to make it easer, I just made a function to convert from db to linear.
Now having these, the should interact with the gyro data. I used the example, where roll, pitch and heading are computed. Roll isnt necessary for a lightsaber (I guess at least, when you just roll it, sound should remain the same).
How to do that? Easy, just use the derivative of heading and pitch using tmp variables for both, first derivative value will be available not at time 0, but time 1. Ok, then I had the derivative for both and used sqrt(deriv_pitch^2 + deriv_heading^2) to modulate the frequency and the amplitude of ALL sine waves, such that freq = freq * (1 + sqrt(deriv_pitch^2 + deriv_heading^2) * scale_factor) and the same for the amplitude with maybe a different scale factor.

The derivates I computed shows some peaks, I filtered them out "by hand" (if > threshold) use old value
 
Ok, I've been intending to make a single pin non-blocking WS2812 library for years.

Well, here it is! :)

https://github.com/PaulStoffregen/WS2812Serial

So far the only documentation is the BasicTest example. Hopefully it's easy to understand?

Most testing as been on a Teensy 3.2 using pins 1, 5, 8 and 10. The other pins are untested. Teensy 3.5 & 3.6 are untested, but are likely to work. Teensy LC definitely does not work.

This new library uses DMA without blocking interrupts at all. It should be possible to update 1 (perhaps long) strip of LEDs without disturbing audio or other interrupt sensitive libs. Pretty much the same as OctoWS2811, but using only 1 pin.
 
Ok, I've been intending to make a single pin non-blocking WS2812 library for years.

Well, here it is! :)

https://github.com/PaulStoffregen/WS2812Serial

So far the only documentation is the BasicTest example. Hopefully it's easy to understand?

Most testing as been on a Teensy 3.2 using pins 1, 5, 8 and 10. The other pins are untested. Teensy 3.5 & 3.6 are untested, but are likely to work. Teensy LC definitely does not work.

This new library uses DMA without blocking interrupts at all. It should be possible to update 1 (perhaps long) strip of LEDs without disturbing audio or other interrupt sensitive libs. Pretty much the same as OctoWS2811, but using only 1 pin.

Wow, thanks Paul :) Was very excited testing it, unfortunatelly the BasicTest shows Rainbow colors fading from beginning to end, after 3 to 4 rainbows, the desired code runs through, lighting up the leds in the specified color. When orange is reached, it begins with some crazy rainbows again. The only stable color I could figure out was (0, 30, 0) and (0, 10, 0), a green. (0, 20, 0) and anything else causes again some crazy rainbows. Several power supplies tested. I used pin 1, prop shield connected (because soldered directly on). Is it a timing issue in the library?
 
I'm finishing up some stuff and I'll post my single wire OCTO hack that worked for me. Took at look at pauls serial version thats pretty cool also.
 
Have you measured the voltage at the far end of the LEDs while it's running? Does it really stay at or near 5 volts?

Normal minimal voltage drop, even connected the end to power source, no difference. Even with just 5 LEDs the rainbow effect appears. I edited the code to FastLed and everything is fine, I thought myself it could be a power issue, but now I think it's not. I'm not familiar with DMA unfortunatelly, otherwise I'd been invastigating on finding a solution and help you a bit after all that work :)

I'm finishing up some stuff and I'll post my single wire OCTO hack that worked for me. Took at look at pauls serial version thats pretty cool also.
Cool, I'm gonna try that too!
 
Hmmm... I'll try changing the timing. But it's going to mean the frame buffer grows to 12 bytes per LED instead of only 8.
 
Would be nice! :) shouldn't be too much of a problem, I will be (and I think many others too) very happy if the library runs stable with all sorts of ws2812b strips. I friend told me there are two versions with an identical datasheet but a different protocol and one can't instantly see which version they have, but I don't know if he's right there
 
Ok, here's a change to alter the timing.

https://github.com/PaulStoffregen/WS2812Serial/commit/abb72e07ecce528ee1fb59f5c5707a2c9835e8a4

When you update the code, please be sure to reopen the example. The new version uses 12 bytes per LED in the frame buffer, so obviously you don't want to use the old example with only 8 bytes allocated.

Oh man, you can't believe how happy I am right now. It's working, working like a charm - even with the prop shield running and all the animations and the sound synthesis. Thank you sooo much, honestly, I can't even believe that it's all working right now :D You are such a cool guy and a genius, THANKS! :D
 
Ok, ... Pretty much the same as OctoWS2811, but using only 1 pin.

Except octows2811 is blocking?
Does octows2811 block during setup of dma stuff or during sending of ws2811 data for duration of data?

Is there no hope for octows2811 to be non blocking?

Is the Serial part of ws2812 the key to all this?

thanks.
 
OctoWS2811 is also non-blocking. Technically, it does block interrupts for a very brief time while configuring the timer, but that is at most a couple microseconds. During the lengthy transmission of data to the LEDs, interrupts are *not* blocked. The show() function returns as soon as the DMA transfers are set up.

WS2812Serial doesn't block interrupts at all.
 
Hi,
Great work.
So if I understood well, the pin 17 of Teensy LC (that can directly drive WS2812 LEDs) can not be used with this library ?
 
Oh sorry I didn't see the end of the readme. I thought of this solution (connecting pin 24 to 17), but I was wondering if there is any risk of damaging the MCU if the code configures these 2 pins as outputs ? (shouldn't happen with the proper code though, as I guess all pins are initialized in Hi-z or input when cpu is started).
 
I can confirm that wiring pin 24 to 17 works fine. Can also confirm that the timing change by Paul does work.
See my other thread.

A stable, external powersupply is required: when trying to display full white on a 24-LED NeoPixel Ring, the +1000mA is too much for my desktop USB port and the Teensy LC goes haywire...

Regards,
Paul
 
Status
Not open for further replies.
Back
Top