FastLED show stripes from the middle

Hello guys,

After a long time trying to find an answer on Google and the forums I couldn't find one.
Basically I have Processing analysing music, it scans the volume, bass and mid tones and it will send them through, and it's all working great, I'm using the FastLED library with a WS2812B led strip (120 LED's) and an Arduino Uno, all the lights show up from the middle of the LED strip with the fill_gradient function.

Now I implemented a beat detecter in Processing which will send through a true or false, when the Arduino receives it I would like to send out a moving dot/stripe from the middle of the LED strip to both sides, the beat detecter could give like 5 times true a second, so my LED strip have to show 5 of these moving white lines at once and all at a different place.

Now getting that moving line from the middle is absolutely no problem from me, but I'm walking against 2 problems:
1- If I work with a delay in a for loop to run that line my code will pause of course and the LED strip will actually freeze while the music is still playing, so you will only see that moving line, this is not what I want, I want the moving line while the other loops keeps going.
Also if I use blink without delay it still won't work since I need to run the code over and over and if I have multiple of these lines it will reset the position probably of the line.
2- If I got 1 line working, how can I get multiple working (like 5 times a second detects a beat, then you want 5 lines with a small interval coming out of the middle), how do I get this?

Anyone with a lot of experience with FastLED or just loop not interfering with each other?

All help would be appreciated!

FastLED information: Click

Look for beat == 1 in the code, this is where the moving dot needs to run.

The longer I try to fix the problem the more errors and problems I get...

I just tried to add 10 switch cases, while everytime it detects a beat, it will activate 1 of them and play the loop.. looks like it worked for a second but it keeps crashing over and over and the code looks really terrible with it, it's really hard to find something for this due to the not use of delays etc..

After going through all the FastLED math functions I still can't find a solution for this due to the multiple stripes at the same time..

  1. Don't use delay(), use millis()

akatchi:
Also if I use blink without delay it still won't work since I need to run the code over and over and if I have multiple of these lines it will reset the position probably of the line.

Then you're doing it wrong ::slight_smile: It's you coding, then only reset the position when you want to.

  1. Just do it 5 times and store all variables you use for it also 5 times. I would suggest an array.

Talking about arrays, that would simplify your code as well. One you start numbering things, arrays :wink:

But I would suggest going over that code... A lot of use of useless Strings... Did you look at Robin2's excellent Serial Input Basics?

Also, use one name scheme, one language as well (ouwe Nederlander ;)) and more descriptive names, that really makes things easier to read (including for future you ;)) and easier to remember.

And just use (const) variables instead of macros (defines) and make them the size you need them max, not just randomly all int.

septillion:

  1. Don't use delay(), use millis()
    Then you're doing it wrong ::slight_smile: It's you coding, then only reset the position when you want to.

  2. Just do it 5 times and store all variables you use for it also 5 times. I would suggest an array.

Talking about arrays, that would simplify your code as well. One you start numbering things, arrays :wink:

But I would suggest going over that code... A lot of use of useless Strings... Did you look at Robin2's excellent Serial Input Basics?

Also, use one name scheme, one language as well (ouwe Nederlander ;)) and more descriptive names, that really makes things easier to read (including for future you ;)) and easier to remember.

And just use (const) variables instead of macros (defines) and make them the size you need them max, not just randomly all int.

Thanks for all the tips, I'm really terrible with arrays and giving good names for strings that are actually useful..
Anyway I have been trying to make a code over and over to get this working and I'll show you in the next post what I got (I'm on a different computer right now), basically I made a switch case with 10 timers, everytime beat is true, it will activate one and goes to the next beat, once it hit the last timer (10), it will go 1 again, so that way I can have at least 10 stripes coming out of the middle, but it's working really terrible and really slow due to Processing sending that string every 40ms, if I let it send faster the Arduino will stop 'working', so sending them faster isn't really an option, also because of the 40ms delay in Processing the Arduino will also automatically have a 40ms delay (not in the code tho), so that means the FastLED.show() will be runned every 40ms, but when I try to run that every 10ms (in the Arduino) code, it will instantly crash.. so problem after problem.

I'll also try to keep my code in 1 language haha :D.

If needed I could also make a video showing what the LED strip is doing right now to give you a better idea of what's going on.

(Code will be posted...!)

akatchi:
basically I made a switch case with 10 timers, everytime beat is true, it will activate one and goes to the next beat, once it hit the last timer (10), it will go 1 again,

Pfff, that's why we have arrays... Then you just need an index to that array, not a long switch, and just circle through the array. Then you can actually call it a circular buffer :wink: Nothing hard about an array. Instead of writing whatever5 you write whatevers[5]...

akatchi:
if I let it send faster the Arduino will stop 'working',

That's probably due to the very very very very pore serial parsing using String :wink:

And a tip to makes thing easier, break it up in smaller pieces :wink: And then start making functions to fulfill the tasks of those little pieces.

With the arrays, for example I have boolean timer1, timer2 and timer3, can I do something like timer + 1 = true;? Well I'm pretty sure this looks stupid and won't work since you can't do String + int, but I'm pretty sure there is a way how to do this...
Alright looks like I deleted the code.. I will re-write a part of it so you get the idea.

That's probably due to the very very very very pore serial parsing using String :wink:

Do you have tips to improve/fix this when you look at my code?

So this is the code that I wrote, but then with 10 of these timers and it worked terrible, the code just stops and it goes very slowly due to the 40ms delay...

I want the stripes to show/update (with FastLED.show()) every 10ms and the other every 40ms (which it is now), but it's really brainbreaking, and I have no idea!

Well have a look at the code I think... (for now everything works, I just want to have those small white striped coming from the middle going to both sides, so from 60-0 and from 60-120 LED's).

akatchi:
With the arrays, for example I have boolean timer1, timer2 and timer3, can I do something like timer + 1 = true;?

If you make an array of timers it's as simple as

unsigned long timers[3]; // array of timers. Note, computers start counting at 0 ;)

//and checking
if(timers[2] > 5){
  
}

Yes, you can also make an array of bools. But calling a bool variable a timer is a bit weird :wink:

akatchi:
Do you have tips to improve/fix this when you look at my code?

septillion:
Did you look at Robin2's excellent Serial Input Basics?

So yes :wink: Use that approach.

akatchi:
and it goes very slowly due to the 40ms delay...

Now I think about it, 40ms is not even that slow... 25fps

akatchi:
I want the stripes to show/update (with FastLED.show()) every 10ms and the other every 40ms (which it is now), but it's really brainbreaking, and I have no idea!

That's 100fps. That IS very fast. Then the Arduino needs to output 360 bytes to the leds every 10ms aka more then 3kB per second... That's a bit to much I think.

akatchi:
Well have a look at the code I think...

Yeahhh, just don't know where to start... You have a very long list of globals (you don't need to have all variables at the top you know ;)) with very vague names. And you do time consuming serial parsing with String...

I would start by sorting those two things out. That would make expanding (and understanding) the code a lot easier.

And can you give me an example of the data coming from the the PC? Or better, the template how you send it.

Oh woops I completely forgot about those arrays, thanks for clearing out.

I will check Robin's tutorial as well, forgot it in your first post to check it out, thanks :D!

septillion:
I would start by sorting those two things out. That would make expanding (and understanding) the code a lot easier.

And can you give me an example of the data coming from the the PC? Or better, the template how you send it.

Oh my bad I completely forgot to mention that!

Processing sends a string like this:
s 20 485 300 1 (without spaces, but just so it will be a bit more clear, S204853001)
s = start signal for string
20 = amount of LED's from mid that will light up (60+20, 60-20)
485 = bass (it adds always +200, so it will be a 3 digit in the string, the Arduino will remove it
then once received)
300 = mid tones
1 = (0 or 1, 1 is beat = true, 0 is beat = false).

That's 100fps. That IS very fast. Then the Arduino needs to output 360 bytes to the leds every 10ms aka more then 3kB per second... That's a bit to much I think.

That's right, but imagine, sometimes the beat will go true over 10 times a second, and you all want to see those stripes smoothly, with 25FPS in less than a second it looks terrible.. (maybe it's not even the FPS but just the animation + the smooth effects).

I'm aiming for an animation like from this video, you see that from the middle there comes out multiple stripes very quickly.
Click here for video

Note that my animations are completely different, but I just want only the stripe effect to be on the beat like this.

So I tried this code and it's really just not working, it's so hard to find a solution.

.......
if (timers[0]) {}
    else {
      if (timers[beat] < 2) {
        timers[beat] = 60;
        beat = 0;
      }
      else {
        timers[beat]--;
        fill_gradient_RGB(leds, timers[beat], CRGB::White, timers[beat], CRGB::White);
        fill_gradient_RGB(leds, 120 - timers[beat], CRGB::White, 120 - timers[beat], CRGB::White);
      }
    }
....................

I had if(timer[0]) {} because when there is no beat I don't want to see those white lights, and when there is I want to see the stripe moving, but if it goes fast I want to see multiple, and this is just not working..
Any tips on how to code this?

septillion:
If you make an array of timers it's as simple as

unsigned long timers[3]; // array of timers. Note, computers start counting at 0 ;)

//and checking
if(timers[2] > 5){
 
}

akatchi:
Processing sends a string like this:
s 20 485 300 1 (without spaces, but just so it will be a bit more clear, S204853001)

Thanks! Mm, it's nice and fixed length. Although I find the +200 a bit of an ugly hack. You could just send 0's :wink:

Ow, I would just use a separator for each value. For example A for amount (of leds), L for bass, M for mid, B for beat, b for no beat. Then you don't even need to receive all the data all the time.

akatchi:
That's right, but imagine, sometimes the beat will go true over 10 times a second, and you all want to see those stripes smoothly, with 25FPS in less than a second it looks terrible..

I have the feeling you're not even outputting 25fps at the moment. 25fps is not super smooth but it should do. Most cinemas still use 25fps or 30fps... (Alright, played at 50 or 60Hz.)

And are your effects always split in the middle? Otherwise you can also just split the strip in two and connect them both to the same output and just use code as if you just have half of the leds.

And without all your code this snipped doesn't make real sense. We're not Snippets R Us...

And

if (timers[0]) {}

What the?! Just learn to count from 0 as well :wink:

And I said it before, clean up the code first. Now it's just rowing upsteam...

septillion:
Thanks! Mm, it's nice and fixed length. Although I find the +200 a bit of an ugly hack. You could just send 0's :wink:

Ow, I would just use a separator for each value. For example A for amount (of leds), L for bass, M for mid, B for beat, b for no beat. Then you don't even need to receive all the data all the time.
I have the feeling you're not even outputting 25fps at the moment. 25fps is not super smooth but it should do. Most cinemas still use 25fps or 30fps... (Alright, played at 50 or 60Hz.)

The LED's, bass and mid have to update every 40ms with it owns valua, only the Beat or no beat depends, but since that's only 1 character I don't think it will make sense.

And yes I am outputting 25FPS, I'll try to post a video of what I've got so far!

And are your effects always split in the middle? Otherwise you can also just split the strip in two and connect them both to the same output and just use code as if you just have half of the leds.

Ehm that's not really an option for me ^_^.

Also, sorry for the snippet but I posted the whole code above it and I thought maybe it would be easier to read if I only posted a snippet.

And to be honest, I don't really see where I can clean up my code.. what could be written better? :open_mouth:

Let's start by giving things a sensible variable name? Or by not dumping all variables in global... Splitting the code in smaller understandable functions. Do I need to go on? :wink:

septillion:
Let's start by giving things a sensible variable name? Or by not dumping all variables in global... Splitting the code in smaller understandable functions. Do I need to go on? :wink:

Alright I'll do that, video is loading btw!

Alright here is the video so you get a better idea (sorry for bad quality lol): Video

It's a start but not really.

Alright, for now I'm willing to overlook the terrible parsing via String. But still

  • English and Dutch mixed
  • Bad variable names (what is bass and mapBass for example? Or eind, end of what?)
  • Mix of variable and function name styles (BassStart, volume, convertIncomingData() fadeall() )
  • And not chopped into little pieces
  • Multiple statements on a single line

It's not to be mean, it just makes it very hard to read and to edit. I just don't know where to start to edit it (or help you) to integrate the desired function. So I would really suggest to make the code better, including switching to proper serial reading because I see a couple of problems already. For example, you start parsering the serial data when you receive a 's', not when you received all data... And what do you try to achieve with fadeall()?

septillion:
It's a start but not really.

Alright, for now I'm willing to overlook the terrible parsing via String. But still

  • English and Dutch mixed
  • Bad variable names (what is bass and mapBass for example? Or eind, end of what?)
  • Mix of variable and function name styles (BassStart, volume, convertIncomingData() fadeall() )
  • And not chopped into little pieces
  • Multiple statements on a single line

It's not to be mean, it just makes it very hard to read and to edit. I just don't know where to start to edit it (or help you) to integrate the desired function. So I would really suggest to make the code better, including switching to proper serial reading because I see a couple of problems already. For example, you start parsering the serial data when you receive a 's', not when you received all data... And what do you try to achieve with fadeall()?

Alright I will give all the functions a better name, but the names will be longer, I will also try to add in the comments what it does..

I will make the code variables in Dutch, and parsing will start when you receive a 's' and ends on a 'n' from now on. Let me fix it!

Alright well, I think that changing the variables still wouldn't really explain a lot, so I decided to add a comment to every line of the code, I recommend you to start reading the SerialEvent loop, then the 'convertIncomingData' loop and then the main loop..
This should make everything a lot more clear.

akatchi:
Alright I will give all the functions a better name, but the names will be longer, I will also try to add in the comments what it does..

Not a problem. Longer but descriptive names are easier to remember. It's the same with passwords :wink:

For example, why do you call it volumeIn? What it actually tells you is if you received new data...

And "high", high of what? Or "eind", end of what? "nieuweLeds", why are they new?

akatchi:
I will make the code variables in Dutch, and parsing will start when you receive a 's' and ends on a 'n' from now on. Let me fix it!

That's a weird fix... Especially because you post on the English section. And still mixing languages... (convertIncomingData(), beat) and mixing formats (without reason) (beat, StringBass)

 Serial.print("Beat: "); Serial.println(beat);
  Serial.print("Mid: "); Serial.println(mid);

Nope nope nope nope :wink: Nothing follows the ; :wink:

And yeah, adding a 'n' is a fix but it's fixed length so you could also use that :wink:

I'm sorry, I still don't know where to start when I want to help you. So I'm afraid I'm out.