Multiple animation zones on 1 pixel strip with FastLED

Hi guys,
This is my first post here so please take it easy on me.

I apologise if my question appears to be dumb and easy for you, I have searched this forum, other forums and the net, but I can't seem to find what I need. I have a little experience with Micro Controllers and RGBs, but not with Neopixels. I may not be using the right words in the searches.

All projects I have done in the past have had the code provided. I have been doing 3D printing for a while now and thought I'd like to put some illumination in my prints.

In a nut shell my project is 3x sections containing 45 pixels each, made from various length pixel strips, wired in series (but each section is routed different) arranged as three No 7 digits (7 L 7).

As I am trying to learn the code I have a 3 stage learning plan, my first goal is to have all three sections display there own sequence (listed in the code), at the same time but in different colours (red, yellow and blue).

After nearly 3 days of trying the closest I have got is they all display the correct colours, but they light up the sections as if it was a single full strip (1 section after the other according to strip direction).

My second goal is to take some of the animations from some of the FastLED examples and run them as a full strip, followed by all 3 sections running my own animation at the same time using there own colour palettes, and with the leds lighting up in pairs, instead of individually .

This is the latest code I have

 #include <FastLED.h>
 // Set data pin and led count

 #define LED_PWR_LIMIT   500     // 500mA limit
 #define LED_PIN           7     // data pin
 #define NUM_LEDS        135     // single section for testing
 #define BRIGHTNESS       50     // brightness level 
 #define LED_SECTIONS      3     // number of sections in display
 
 CRGB  leds [NUM_LEDS];      // initialize all pixels

 int section1[ ] = {44,0,43,1,42,2,41,3,40,4,39,5,38,6,37,7,36,8,35,34,33,32,9,31,10,30,11,29,12,28,13,27,14,26,15,25,16,24,17,23,18,22,19,21,20};
 int section2[ ] = {79,78,80,77,81,76,82,75,83,74,84,73,85,72,86,71,87,70,88,89,69,45,68,46,67,47,66,48,65,49,64,50,63,51,62,52,61,53,60,54,59,55,58,56,57};
 int section3[ ] = {111,110,112,109,113,108,114,107,115,106,116,105,117,104,118,103,119,102,120,121,122,123,101,124,100,125,99,126,98,127,97,128,96,129,95,130,94,131,93,132,92,133,91,134,90};


void setup() {
/*******************************************************************************
************************** only runs once at start-up **************************
*******************************************************************************/

 FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);  // pixel count, type and data pin
 
 FastLED.setBrightness(BRIGHTNESS);  // set brightness level
 FastLED.clear();
}

void loop() {
/*******************************************************************************
************************** main code runs repeatedly ***************************
*******************************************************************************/

 for(int section1 = 0; section1 < 45; section1++){
  leds[section1].setRGB(128, 0, 0);
  FastLED.show();
  delay (30);
 }
 for(int section2 = 45; section2 < 90; section2++){
  leds[section2].setRGB(128, 128, 0);
  FastLED.show();
  delay (30);
 }
 for(int section3 = 90; section3 < 135; section3++){
  leds[section3].setRGB(0, 0, 128);
  FastLED.show();
  delay (30);
 }
  delay (1000);
  FastLED.clear();
}

I have read about the delay function and tried the EVERY_N_MILLISECONDS but could not get that to work either.

I have tried using 'i' instead of 'section1/2/3' in the 'for' loops, this makes all pixels show red.
I have tried to define each section separately, this causes errors with the sections.
I have combined the 'for' loops, doesn't work at all.

I have spent nearly 3 days on this now and seem to be going nowhere.

I know the solution will be easy for some of you but it is a real head scratcher for me.
Please help, with part 1 at least. Parts 2 and 3 would be amazing, although I'm not going to be greedy on my first post.

Here's hoping :crossed_fingers:

All the best and Happy New Year to everyone,
Xant247

To make different pixel sections simultaneously do different things you should send all your pixel logic to all the pixels on the strip and only call fastled.show() once, then repeat. Think of it as stop-animation movie made with a still camera... you slightly move all your objects around to their new position, then take one picture, and repeat 24,000 times. Start with three pixels. Make one blink blue every second. Make one fade red max to min to max over five seconds, and make one do every color in half a second.

@xfpd
Thanx for the reply. I can control individual pixels ok.
What I need first is to get all 3 sets of pixels to do the same thing at the same time (in their own specified order and colour).

Regards
Xant247

I can control individual pixels ok.

Awesome! All you need to do is repeat that 24,000 (or 300) times.

Use a for() loop from pixel zero to last pixel.
If you have 300 pixels, and want equal sized sections, make 0 - 99 do thing#1, 100 - 199 do thing#2 and 200 - 299 do thing#3.

for (int i =0; i < 300; i++)
{
    if (i < 99) {thing#1};
    if (i>99)&&(i<199) {thing#2};
    if (i>199) {thing#3};
    Fastled.show();
}

Maybe put thing#1, thing#2 and thing#3 in their own function for easier code reading.

@xfpd
I think your example is beyond my skill level for now.
The code side is a new venture for me so only the most basic things manage to make some sense to me for now.

Is there an easier way for me to achieve step 1, similar to the code I have posted ?

You are fine. You can control one pixel. You are one line of code from controlling any number you want. Put "control one pixel" code in a loop, and you will control all the pixels. Give a look at "how to write a loop" for arduino. I will catch up with you tomorrow. Others will be here to help. Experiment! Have fun!

Will do, thanx.

Small steps. You are doing fine. Keep trying.

Your code works as is:

  1. the first 45 pixels sequentially light red
  2. the next 45 pixels sequentially light green
  3. the next 45 pixels sequentially light blue
  4. all pixels turn off.

The arrays that you declared seem to do different patterns...
a. section 1 starts at the ends with red, then moves toward to the middle
b. section 2 starts at the middle with green and moves toward the ends (** SECTION 2 NEEDS WORK - LOW-SIDE STARTS LATE **)
c. section 3 seems to do the same as section 2 with blue

To make a, b, c happen rather than 1, 2, 3, the three "sections" need to be in the same loop to do their thing at the same time (right now, they are in different loops, making them do their thing at different times).

So... (he thinks)... aha! (to be continued)...

 for(int thestrip = 0; thestrip < 45; thestrip++){
  leds[section1[thestrip]].setRGB(128, 0, 0);
  leds[section2[thestrip]].setRGB(0, 128, 0);
  leds[section3[thestrip]].setRGB(0, 0, 128);
  FastLED.show();
  delay (50);

Comment-out your three "sectionx" inside void loop() and paste the above few lines... is that what you expected?

You want the indexing variable to run from 0 to the number of pixels in a section.

Then that index should be picking something out of the global section array.

By saying

   for  (int section3... 

you are introducing a new variable, so the global section3 mapping is ignored.

I think you want

for(int i = 0; i < 45; i++) {
  leds[section3[i]].setRGB(0, 0, 128);
  FastLED.show();
  delay (30);
}

Your current code "works" only where the map happens to be equal to the index. Which is true, it looks like in sections 2 and 3, but def not in section 1.

All the section 1 LEDs will light up, but not in the order you laid out in the map (section3 global array).

HTH

a7

OMG guys,
This is exactly what I wanted for step 1.

@xfpd
Your example works perfect as is, and looks soooo much better than mine.
I removed all my 'viod loop' statements (14 lines) and replaced with your 6 line loop statement, I am amazed to see my (our) creation coming to life.
I understand now how the loop works in this case.

@alto777
If I add 'leds[section#[ i ]].setRGB ....' for all 3 sections, this also works perfect.

Only difference I see between your 2 examples is @xfpd uses 'for(int thestrip = 0;'
and @alto777 uses 'for (int i = 0;'

Thanx to my 2 new best friends, I call step 1 very nearly complete.

So now if I want the pixels to light up in pairs instead of one after the other, the 'int section#[ ]' just above 'void setup' will need to be replaced (I presume).

This is the first few leds in the sequence I want for section 1.
The animation is still the same but this should make the sections light up better, more like a wave.

const uint8_t segGroups[24][2] PROGMEM = {

{ 44, 44},
{ 0, 43},
{ 1, 42},
{ 2, 41},
{ 3, 40},
{ 4, 39},
{ 5, 38},
{ 6, 37},
{ 7, 36},

Does this also require more code and can it be done easily ?

I have learnt more today than I have in the last 3 days.

Regards and thanx,
Xant247

Good. Now, tell yourself (learn) why these two methods work. Go through the loops.

44 = 44 + 0 (an exception to the following loop)

43 = 43 + 0
43 = 42 + 1
43 = 41 + 2
.
.
.
One column decreases (in a loop) from 43 to ??. The other column increases from 43 minus 43 to ??

Rather than atrying to solve both loops at one time, solve the outer loop first (43 to 0), then the inner (x minus y)

the name we chose for the varaibale that only exists in the context of the for loop.

'i' isn't the best name, better woukd be ledIndex. Or something like ii, so it is clear. I was just lazy, plus the scope is only a few lines of code, all within view.

But the point is that you could have named it any legal variable name like myBeachBuddyIsLate

  for (int myBeachBuddyIsLate = 0; myBeachBuddyIsLate < 45; myBeachBuddyIsLate++) {

// and use, as appropriate
    section3[myBeachBuddyIsLate]

The irony is she gets so mad when I keep her waiting…

a7

@xfpd
I should have posted the full list of section1 numbers. The whole list does not count up on 1 side and down on the other.

{ 44, 44},
{ 0, 43},
{ 1, 42},
{ 2, 41},
{ 3, 40},
{ 4, 39},
{ 5, 38},
{ 6, 37},
{ 7, 36},
{ 35, 35},
{ 8, 34},
{ 33, 33},
{ 9, 32},
{ 10, 31},
{ 11, 30},
{ 12, 29},
{ 13, 28},
{ 14, 27},
{ 15, 26},
{ 16, 25},
{ 17, 24},
{ 18, 23},
{ 19, 22},
{ 20, 21},

This is due to the way the strips are wired.
Does this make a difference to doing it your way ?

A "brute force" method for making this list of pixel pairs show() as pairs is:

  1. put all your data in one array (as you did before)
  2. read a value
  3. if your counter is a divisible by two
  • either have a counter (count = count + 1) or
  • use modulus 2 (two) that is to say if "i" divided by 2 has zero remainder (if (i%2), delay() before next pair-read
  1. "show()" the pixels (44,44 will just be seen as 44 (one pixel)).
  2. repeat

Regardless of how you define the patterns, one thing that might make your life easier is to use FastLED's, CPixelView class. It allows you treat different sections of the single, large LED strip as multiple virtual strips each with their own size and indexing that starts at zero. I would define three virtual strips for your thee different sections and put them in an array:

#include <FastLED.h>

const size_t numSections = 3;
const size_t ledsPerSection = 45;
const size_t ledCount = numSections * ledsPerSection;
const uint8_t ledPin = 7;

CRGB leds[ledCount];
CPixelView<CRGB> sections[numSections] = {
  CPixelView<CRGB>(leds, 0, ledsPerSection),
  CPixelView<CRGB>(leds, ledsPerSection, ledsPerSection),
  CPixelView<CRGB>(leds, 2 * ledsPerSection, ledsPerSection)
};

void setup() {
  FastLED.addLeds<WS2812, ledPin, RGB>(leds, ledCount);

}

void loop() {
}

With this all three virtual strips will be indexed 0-44 and you won't need custom offsets for each one … the CPixelView class takes care of that for you. So you'd index the sections as:

Section 0: sections[0][0] through sections[0][44]
Section 1: sections[1][0] through sections[1][44]
Section 2: sections[2][0] through sections[2][44]

Again, the CPixelView class will take these indexes and properly offset them into the "real" leds array.

1 Like

Sorry for the late reply guys, had a medical emergency at home with my brother.

@xpfd
Thanx for your PM, I will definitely take a look at WOKWI.com, not having to upload code every time I make a change will speed things up a bit.
I did try Tinkercad and Codeblocks, but that doesn't have FastLED library.
I have also managed to make my display reverse the animation after 1 second using your loop by changing all colours to black and using ' i-- '

@gfvalvo
All my sections are the same, they all contain the same size strip pieces but have slightly different data routes.

Apart from a few Strandtest animations (to run as a full strip), all I want to do is to get all 3 sections to display the same animation at the same time but using their own colour palette and pixel order.
I think the loop example from xfpd will make this easier for me.

Ideally I would like the pixels to light in pairs (like the list in post#14), but if that proves to be beyond me for now I will settle for how they light now.

After getting the pixel order and colour palettes in order, my final objective will be to make the pixels in my own patterns fade rather than on / off.

The progress I / we have made so far is amazing and I have learnt so much already.

Don't think I could have done this myself, Thanx again and...

Keep the help coming, please. :+1:

Xant247

I understand that. It was also my impression that those sections are wired electrically in series as one long strip. That's why I showed you code that used the CPixelView class to treat the one long strip as three virtual strips. Each of these virtual strips is indexed 0 - 44. That way you can concentrate on developing your animations to work just over that range without having to worry about offsets to index 0-44 for one section, 45-89 for the next section and 90-134 for the last section.

@gfvalvo
Post#18 makes things a lot clearer for me now and your last answer (post#16) makes more sense now.
Make 1 animation then run that on all 3 sections.

I still don't understand where and how to define the pixel lighting order to make pairs light up (instead of singles) for my own animations. My animations won't be much more than what is in my posted code (fill with a colour then drain or overlay with another colour).

I know how to put animations from the example files together and run as a full strip, so defining pixel order is my biggest problem now.

Regards,
Xant247

@xfpd
@alto777
@gfvalvo

I think I can now call step 1 complete thanx to you amazing people.

I have used WOKWI to recreate my full display and the basic code I have now, am I doing OK so far ?

diagram.json.txt (44.3 KB)
Triple7.ino (2.5 KB)

All wiring is the same as my sections, it's due to the way they will be positioned when finished.

Am I right in thinking that I can add my own animations to the main loop and have them play a certain number of times along with the demo's I want to use ?

Step 2 now is to stitch a few demos together with my basic animation and play them is sequence.
I will work on my animations when I have learnt a bit more.

Thanx again guys

Xant247