Multiple String Array Noobish Question  I've got 8 LED strings defined on different pins

Multiple String Array Noobish Question

I’ve got 8 LED strings defined on different pins (using teensy/octo adapter)

FastLED.addLeds<WS2812B, 2, GRB>(leds[0], NUM_LEDSPERROW);
FastLED.addLeds<WS2812B, 14, GRB>(leds[1], NUM_LEDSPERROW);
FastLED.addLeds<WS2812B, 7, GRB>(leds[2], NUM_LEDSPERROW);
FastLED.addLeds<WS2812B, 20, GRB>(leds[3], NUM_LEDSPERROW);
FastLED.addLeds<WS2812B, 6, GRB>(leds[4], NUM_LEDSPERROW);
FastLED.addLeds<WS2812B, 9, GRB>(leds[5], NUM_LEDSPERROW);
FastLED.addLeds<WS2812B, 21, GRB>(leds[6], NUM_LEDSPERROW);
FastLED.addLeds<WS2812B, 5, GRB>(leds[7], NUM_LEDSPERROW);

Variables:
#define NUM_LEDS 160
#define NUM_ROWS 8
#define NUM_LEDSPERROW 20
CRGB leds[NUM_ROWS][NUM_LEDSPERROW];

Using a simple colorwipe type function:
for(int i = 0; i < TotalSteps; i++ )
{
leds[Row][i] = CRGB::Red;
}

Now if TotalSteps is equal to the row length (number of LEDs) works as expected.

However, if for some reason TotalSteps is larger than the string length (number of leds), then the extra updates are bleeding into the next array.

Apart from being careful or adding checks on my number of leds per row, are there other ways to avoid this?

I suppose if I wanted to run code on all of the 8 strings as one array, I could essentially just use leds[0][NUM_LEDS]? my gut says no though.

current code:

really trying to get a good understanding on how to run multiple strips simultaneously with simple effects, but not quite clicking yet. May just defer back to the same effect on all the strings instead.

you can use the constrain function to stay in the range of numbers you want : http://www.arduino.cc/en/Reference/Constrain

You can use constrain, but especially in C/C++, running off the end of an array is (1) usually the sign that you’ve made a mistake earlier in your program, and (2) likely to cause crashes, freezes, or other errors.
(In the outside world, I’d also warn about the security implications, too.)

I recommend finding out why your program is overrunning it’s buffers, and fix it.

And yes: you CAN access the whole array as one big piece! Try it!

The error was on purpose, i was seeing how thing would react. I’m a hands on learning kind of guy.
It should be an easy fix, I’ll look into constraints… i think that could save me some headache down the road!

If its possible to access the whole array as one big piece, how would like look?

Wouldnt leds[0][NUM_LEDS] cause crashes as mentioned? since it is overflowing the first array?

Q: Wouldnt leds[0][NUM_LEDS] cause crashes as mentioned? since it is overflowing the first array?

I guess it depends how the… CRGB leds[NUM_ROWS][NUM_LEDSPERROW];

gets allocated in memory.

If they are all sequentially allocated (as would normally be expected) it would work!!

However, if you try to access and modify further than leds[7][numledsperrow-1] you simply do not know what you are modifying!

As Mark suggested and since you say your hands-on… just try it!

I guess you could make constraints work but in my opinion, you need to somehow specify the actual length of that array when you execute that for loop !

Here’s a cut and paste from the Arduino reference for arrays…

"For this reason you should be careful in accessing arrays. Accessing past the end of an array (using an index number greater than your declared array size - 1) is reading from memory that is in use for other purposes.

Reading from these locations is probably not going to do much except yield invalid data. Writing to random memory locations is definitely a bad idea and can often lead to unhappy results such as crashes or program malfunction. This can also be a difficult bug to track down.

Unlike BASIC or JAVA, the C compiler does no checking to see if array access is within legal bounds of the array size that you have declared."

Thanks @JP_Roy
I’m currently at the office, but Im trying to read and learn more before I get a chance to try it at home in 10 hours. Sounds promising for some ideas floating around my head now.

You define an array of led arrays…

CRGB leds[NUM_ROWS][NUM_LEDSPERROW];

But are all your strips actually the same length ?

If not, you could instead specify your array like…

CRGB leds[NUM_LEDS];

and then use the following…

FastLED.addLeds<WS2812B, 2, GRB>(leds, FIRST_LED_0, NUM_LEDS_0);
FastLED.addLeds<WS2812B, 14, GRB>(leds, FIRST_LED_1, NUM_LEDS_1);
FastLED.addLeds<WS2812B, 7, GRB>(leds, FIRST_LED_2, NUM_LEDS_2);
FastLED.addLeds<WS2812B, 20, GRB>(leds, FIRST_LED_3, NUM_LEDS_3);
FastLED.addLeds<WS2812B, 6, GRB>(leds, FIRST_LED_4, NUM_LEDS_4);
FastLED.addLeds<WS2812B, 9, GRB>(leds, FIRST_LED_5, NUM_LEDS_5);
FastLED.addLeds<WS2812B, 21, GRB>(leds, FIRST_LED_6, NUM_LEDS_6);
FastLED.addLeds<WS2812B, 5, GRB>(leds, FIRST_LED_7, NUM_LEDS_7);

with this, each string length may be totally different and you could use FIRST_LED_x and NUM_LEDS_x in your For loop

That’s the method I’ve used before (my last years model). It worked great for running the same effect on the whole array.

The problem I face with that method is the math I would need to do in order to update a specific row on its own.

but as I write this, it may not be as difficult as i once thought. I could write a function to find/define the first and last led of a given row before running my effects, so I wouldn’t have do change my effects.

something like (logical wording, not actual code):
if row = 2 then
i = 10 & TotalSteps = 20
if row 3 then
i = 30 & TotalSteps = 10
if row 4 then
i = 40

then when I run my effect updates, they can stay untouched since i and TotalSteps would be defined before it runs.
for(int i = 0; i < TotalSteps; i++ )
{
leds[i] = CRGB::Red;
}
thanks for the guidance @JP_Roy

There are so many different ways to skin a cat!

I have no doubts your cat will lose it’s skin soon… :wink:

Also, if you’re using the teensy/octo adapter, and are running FastLED3.1 (which you should be) - then replace these lines:

FastLED.addLeds<WS2812B, 2, GRB>(leds[0], NUM_LEDSPERROW);
FastLED.addLeds<WS2812B, 14, GRB>(leds[1], NUM_LEDSPERROW);
FastLED.addLeds<WS2812B, 7, GRB>(leds[2], NUM_LEDSPERROW);
FastLED.addLeds<WS2812B, 20, GRB>(leds[3], NUM_LEDSPERROW);
FastLED.addLeds<WS2812B, 6, GRB>(leds[4], NUM_LEDSPERROW);
FastLED.addLeds<WS2812B, 9, GRB>(leds[5], NUM_LEDSPERROW);
FastLED.addLeds<WS2812B, 21, GRB>(leds[6], NUM_LEDSPERROW);
FastLED.addLeds<WS2812B, 5, GRB>(leds[7], NUM_LEDSPERROW);

with this line:

FastLED.addLeds<WS2811_PORTD,8,GRB>(leds[0], NUM_LEDSPERROW)

(See also https://github.com/FastLED/FastLED/wiki/Parallel-Output )

@Daniel_Garcia This will be great for my led panels!

For my new project the rows will end up being different sizes eventually.

If I declare NUM_LEDSPERROW to the largest strip length, would that still benefit in the end if some of the strips were say half the size?

example:
Strip a = 5 leds
Strip b = 10 leds
Strip c = 15 leds
Strip d = 5 leds
Strip e = 10 leds
Strip f = 15 leds
Strip g = 15 leds
Strip h = 5 leds
Total_LEDS = 80

In that:
FastLED.addLeds<WS2811_PORTD,8,GRB>(leds[0], 15)

With:
CRGB = leds[120] //total number of leds

The array would essentially have unused spaces for some strips that are not 15 in length.
[a1][a2][a3][a4][a5][x][x][x][x][x][x][x][x][x][x]
[b1[b2][b3]…[b10][x][x][x][x][x]
[c1]…[c15]
etc.

It absolutely would benefit.

If you did the 8 set of addLed calls, it would take 2.4ms (80 rgb leds time 30µs per led) to write out a frame of led data.

If you’re running the 8 way parallel, then it would only take 0.45ms - so still almost 5 times faster.

Hi @Daniel_Garcia , when using the Teensy3.1 with OCTOWS2811 adaptor with FastLED3.1 with this line:

FastLED.addLeds<WS2811_PORTD,8,GRB>(leds[0], NUM_LEDSPERROW)

Does that use DMA to create the WS2811 waveforms with near zero CPU usage ?

No, you have to specifically ask it to use the octows2811 - the wiki page points at the example for it.

Also, while octows2811 has 0 cpu overhead while writing out data it turns out that the cost of the bit rotation almost completely undid the cpu savings of using dma (which is why octows2811 is great when using it as a buffer when you’re doing the expensive bit rotation on a host machine and pushing pre-rotated data to the teensy).

Sorry @Daniel_Garcia , I read the wiki a few times and toyed a bit with the OCTOWS2811DEMO… still got some questions…

As per wiki…

… call into OctoWS2811’s setpixel functions, for a 64x8 array of leds this would end up taking nearly 2µs worth of calls to setPixel -

That is not much of an overhead unless you meant 2ms, the time to write to 64 WS2812?

I definitely want the full features offered by FastLED AND of course, have as much available CPU time as possible to create complex animations within the Teensy (no outside data preparation and transfer)

What setup would you recommend?

Sorry that should be 2ms - setPixel is really really expensive. Best is fastled with the octows2811 controller, which comes out to about 1us of overhead per pixel (vs 4 w/setPixel)

@Daniel_Garcia WOW the parallel output is AWESOME!

night and day difference. looks amazing now.