Command to run 2 or more LED strips simultaneously

Hello,

I am part of a team, we are currently working on a rather big project. I've attached some photos as wall as circuit diagramms so you can understand it better. We are building a LED "sky" out of 50 LED strips, 750 single LEDs. There are two options for wiring the data cable:

a)We are planning to have a single data wire to each of the LED strips.

1.As you can see in the skecht below, we want to run for example a color Wipe on all the strips the same time. So I need a comman/way to say: colorWipe(strip1 to 50.Color(255, 0, 0), 50); instead of as seen in the sketch.
And can I use this command also here: Adafruit_NeoPixel strip1 = Adafruit_NeoPixel(15, PIN1, NEO_GRB + NEO_KHZ800);

b)Or if this is a better option we want to connect one bar of LED strips(would be 12 strips) with one wire. But I dont really know if the commands would still work as the programm see would see the 12 strips as on strip.

2.So is there are way to run a effect like colorWipe on 12 strips simultaneously, if the sketch thinks its just one big strip?

Here is the sketch:

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif

#define PIN1 7

#define PIN2 6
//and so on until 50

Adafruit_NeoPixel strip1 = Adafruit_NeoPixel(15, PIN1, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip2 = Adafruit_NeoPixel(15, PIN2, NEO_GRB + NEO_KHZ800);
//and so on until 50



void setup() {

#if defined (__AVR_ATtiny85__)
  if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
#endif


  strip1.begin();
  strip1.setBrightness(200);
  strip1.show();

  strip2.begin();
  strip2.setBrightness(200);
  strip2.show();
  //and so on until 50?


}

void loop() {

  colorWipe(strip1.Color(255, 0, 0), 50); // Red
  colorWipe(strip1.Color(0, 255, 0), 50); // Green
  colorWipe(strip1.Color(0, 0, 255), 50); // Blue
  strip1.show();


  theaterChase(strip2.Color(127, 127, 127), 50); // White
  theaterChase(strip2.Color(127, 0, 0), 50); // Red
  theaterChase(strip2.Color(0, 0, 127), 50); // Blue
  strip2.show();



}

void colorWipe(uint32_t c, uint8_t wait) {
  for (uint16_t i = 0; i < strip1.numPixels(); i++) {
    strip1.setPixelColor(i, c);
    strip1.show();
    delay(wait);
  }
}



void theaterChase(uint32_t c, uint8_t wait) {
  for (int j = 0; j < 10; j++) { //do 10 cycles of chasing
    for (int q = 0; q < 3; q++) {
      for (uint16_t i = 0; i < strip2.numPixels(); i = i + 3) {
        strip2.setPixelColor(i + q, c);  //turn every third pixel on
      }
      strip2.show();

      delay(wait);

      for (uint16_t i = 0; i < strip2.numPixels(); i = i + 3) {
        strip2.setPixelColor(i + q, 0);      //turn every third pixel off
      }
    }
  }
}

//Theatre-style crawling lights with rainbow effect




uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if (WheelPos < 85) {
    return strip2.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if (WheelPos < 170) {
    WheelPos -= 85;
    return strip2.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip2.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

I hope some of you have got some answers, thank you for your help!

Andi

If you switch to the FastLED library, they have examples of how to control multiple strips simultaneously. Neopixels work just fine with that library.

If you wire multiple strips together, you have to take care in the code to know which pixel is the first of each row, which is the 2nd, etc. but it totally doable. You could also wire them up as one huge strip and color in different sections to make them appear as you want.

You better have a large power supply :slight_smile:

What board are you using ? this is the first question to ask, 750 LED's at 3 bytes (or 4 bytes if they are RGBW) each is 2250 bytes, so a small sized board will run out of RAM.
The point about the Power-supply is valid !
The method you suggested using Adafruit_neopixel will work just fine, but no built-in function for doing a swipe on multiple strips is available, though if you are doing a project like this with a few people, someone should have enough time to look and see how this function is created within the library and set that up so that it can.
There is no real benefit for using multiple pins other than 'if you chain breaks you lose less of the whole' and 'like that i can run shorter wires'
The second argument is something to consider, the length of a data-wire is limited as a result of the capacitance of the cable causing the signal to be disturbed (thinner wire is better !, solid is better than multi-strand)
Switching to FastLED, i can't help you any further (i just don't want to support the library) but other probably still will. Either way, if you are on an UNO, Nano or Pro-Mini, you'll need a different board (MEGA or ESP-based) and for ESP-based boards using Makuna-Neopixelbus will be a great solution, though you then probably want to use just 1 pin.

Some things that may help;

1st get rid of the delay() calls. You are trying to manipulate 50 addressable led strings as fast as possible, no?

I would say yes, fast as possible. I look at your code with calls to delay salted throughout and see that the code between those calls will run in less than 1000 cycles and then it hits the next delay(wait) with typical wait == 50ms.

Do you know how many clock cycles every millisecond of delay() WASTES? Yes, nothing else runs during delay(), 16000 cycles that could be changing leds is thrown away for every 1 ms of delay, 50ms is 800,000 cycles.

But perhaps you don't know there is a way around this that will boost the skill of anyone who learns it, and it is a lesson that is not so big but does require thinking about what code should be doing, a different approach. One or more of your team could check this out and bring the rest up. Here is a tutorial with good explanation and code to mess with (how to learn best, mess with the code!),

Also I don't know if you are familiar with arrays of variables (if not, learn just to save your fingers and hair and sanity!) but instead of

Adafruit_NeoPixel strip1 = Adafruit_NeoPixel(15, PIN1, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip2 = Adafruit_NeoPixel(15, PIN2, NEO_GRB + NEO_KHZ800);
//and so on until 50

that requires source code with 50 different names in every part that addresses a strip, oh poor fingers! Oh poor free time!

Instead:

const byte ledStrips = 10; // because 50 pins is a bit much eh?
const byte pixelPin[ ledStrips ] = { 2,3,4,5,6,7,8,9,10,11 };
byte doStrip = 0;

Adafruit_NeoPixel strip[ ledStrips ];  // I only bet this is possible knowing how C++ works, try it with just 2 strips to test.

......

void setup() 
{
  // other setup code

  for ( byte i = 0; i < ledStrips; i++ )
  {
    strip[ i ]= Adafruit_NeoPixel(15, pixelPin[ i ], NEO_GRB + NEO_KHZ800);
  }
}

void loop()
{
  // inside of loop you only process strip[ doStrip ] using one code. 
  // at the end you put

  if ( doStrip >= ledStrips )  doStrip = 0; // so it runs through all the strips over and over.
}

And last, you can store patterns in the chip flash that has plenty of room and not waste RAM. You can connect SD to Arduino and read stored patterns off that. You can generate patterns once your code is faster than human eye (about 40ms between changes looks like movement, it is 25 FPS) and you have cycles for it.

Deva_Rishi:
Switching to FastLED, i can't help you any further (i just don't want to support the library)

You really do seem to have a bug up your a** about that library. Any particular reason?

I can see why most anyone would prefer to use a library, the data timing is awfully close.

I for one would like to see RGB led strips that can run off SPI MOSI and CLK for data. You'd be able to pause......

GoForSmoke:
I for one would like to see RGB led strips that can run off SPI MOSI and CLK for data. You'd be able to pause......

You mean like APA102, aka DotStar?

blh64:
If you switch to the FastLED library, they have examples of how to control multiple strips simultaneously. Neopixels work just fine with that library.

If you wire multiple strips together, you have to take care in the code to know which pixel is the first of each row, which is the 2nd, etc. but it totally doable. You could also wire them up as one huge strip and color in different sections to make them appear as you want.

You better have a large power supply :slight_smile:

I haven't heard about that library but if FastLED has got such a function it would make it a lot easier.

I guess wiring them up in one huge strip makes the most sense, considiring it works in the code.

Yes we have got some big PSU :), thank you!

Deva_Rishi:
What board are you using ? this is the first question to ask, 750 LED's at 3 bytes (or 4 bytes if they are RGBW) each is 2250 bytes, so a small sized board will run out of RAM.
The point about the Power-supply is valid !
The method you suggested using Adafruit_neopixel will work just fine, but no built-in function for doing a swipe on multiple strips is available, though if you are doing a project like this with a few people, someone should have enough time to look and see how this function is created within the library and set that up so that it can.
There is no real benefit for using multiple pins other than 'if you chain breaks you lose less of the whole' and 'like that i can run shorter wires'
The second argument is something to consider, the length of a data-wire is limited as a result of the capacitance of the cable causing the signal to be disturbed (thinner wire is better !, solid is better than multi-strand)
Switching to FastLED, i can't help you any further (i just don't want to support the library) but other probably still will. Either way, if you are on an UNO, Nano or Pro-Mini, you'll need a different board (MEGA or ESP-based) and for ESP-based boards using Makuna-Neopixelbus will be a great solution, though you then probably want to use just 1 pin.

We are using a MEGA 2560 so RAM shouldn't be a problem. We are will connect it to a wifi shield, but thats another story.

Yes this would be me, but I don't think I understand programming enough to find how this function is creasted.

We have planned to use cables, with a cross-section of 1.5mm², solid ones. I don't think thats to tough?

Yes, we are probably using 4 PINs as we have got 4 rows out of 12 to 13 LED strips.

GoForSmoke:
Some things that may help;

1st get rid of the delay() calls. You are trying to manipulate 50 addressable led strings as fast as possible, no?

I would say yes, fast as possible. I look at your code with calls to delay salted throughout and see that the code between those calls will run in less than 1000 cycles and then it hits the next delay(wait) with typical wait == 50ms.

Do you know how many clock cycles every millisecond of delay() WASTES? Yes, nothing else runs during delay(), 16000 cycles that could be changing leds is thrown away for every 1 ms of delay, 50ms is 800,000 cycles.

But perhaps you don't know there is a way around this that will boost the skill of anyone who learns it, and it is a lesson that is not so big but does require thinking about what code should be doing, a different approach. One or more of your team could check this out and bring the rest up. Here is a tutorial with good explanation and code to mess with (how to learn best, mess with the code!),

Gammon Forum : Electronics : Microprocessors : How to do multiple things at once ... like cook bacon and eggs

Also I don't know if you are familiar with arrays of variables (if not, learn just to save your fingers and hair and sanity!) but instead of

Adafruit_NeoPixel strip1 = Adafruit_NeoPixel(15, PIN1, NEO_GRB + NEO_KHZ800);

Adafruit_NeoPixel strip2 = Adafruit_NeoPixel(15, PIN2, NEO_GRB + NEO_KHZ800);
//and so on until 50




that requires source code with 50 different names in every part that addresses a strip, oh poor fingers! Oh poor free time!

Instead:



const byte ledStrips = 10; // because 50 pins is a bit much eh?
const byte pixelPin[ ledStrips ] = { 2,3,4,5,6,7,8,9,10,11 };
byte doStrip = 0;

Adafruit_NeoPixel strip[ ledStrips ];  // I only bet this is possible knowing how C++ works, try it with just 2 strips to test.

......

void setup()
{
  // other setup code

for ( byte i = 0; i < ledStrips; i++ )
  {
    strip[ i ]= Adafruit_NeoPixel(15, pixelPin[ i ], NEO_GRB + NEO_KHZ800);
  }
}

void loop()
{
  // inside of loop you only process strip[ doStrip ] using one code.
  // at the end you put

if ( doStrip >= ledStrips )  doStrip = 0; // so it runs through all the strips over and over.
}




And last, you can store patterns in the chip flash that has plenty of room and not waste RAM. You can connect SD to Arduino and read stored patterns off that. You can generate patterns once your code is faster than human eye (about 40ms between changes looks like movement, it is 25 FPS) and you have cycles for it.

Good ponint I should get rid of them. In some parts of the programm I will need to use them for the effects but if they have no sense, as you pointed out I will delete them.

Thank you, I will have a look through that guide!

And thank you again, the variables is exactly what I looked for.

The thing with the chip flash would make sense, but is it necessary if we using a MEGA?

HA21:
Good ponint I should get rid of them. In some parts of the programm I will need to use them for the effects but if they have no sense, as you pointed out I will delete them.

No, get rid of all delay() calls. Use proper State Machine, millis()-based timing techniques instead to make your code totally non-blocking.

gfvalvo:
You really do seem to have a bug up your a** about that library. Any particular reason?

Very simple, it has caused a lot of extra work with people writing beyond the size of the array and coming for help, without any warning given in the examples, 2nd, i can not support people that write their own delay function and make it that F^%$^% Stupid that it does something pointless, usually turns of interrupts (actually last time we came to the conclusion it even momentarily does for strips with clock pin) and then messes up the timing. And it is Not Faster than any of the others. But i thought i made that clear before so let's leave it at that. I do not support it, if you want to, go for it, but don't write beyond the size of the array, and please remove FastLED.delay() from any code you find !

Deva_Rishi:
Very simple, it has caused a lot of extra work with people writing beyond the size of the array and coming for help

...usually turns of interrupts (actually last time we came to the conclusion it even momentarily does for strips with clock pin)

Funny, I've never had any problem with it. Including using it on an interrupt-intensive POV project (more than 10,000 interrupts / second).

Newbies overwrite arrays all the time. That's what they do. Are you proposing that they be discouraged from using integer and character arrays also?

And from my own update speed experiments, it compares well against simply writing to the APA102 LEDs from a buffer over Hardware SPI using Hardware DMA on a Teensy 3.2. That's smoke'in fast.

gfvalvo:
You mean like APA102, aka DotStar?

Possibly, do the bits shift out as data via hardware or software? Port or bang?
The difference is CPU load and I do have a long personal love of stealing cycles that would otherwise be wasted.

  • Extremely fast data1 and PWM2 rates, suitable for persistence-of-vision displays.

  • Easier to interface to a broader range of devices; no strict signal timing requirements.

  • Works with Servo library, tone() function, interrupts, etc.

– Slightly more expensive.

– Fewer available form factors.

– Needs two pins for control.

It does look like fun. Easier fun at that. Think of the cost and work of wiring up RBG-led-driver chips and 60 RGB leds, the strips should be a bargain.

But you know, I think I have one thing about WS2812 wrong. When you give it LOW for 50+us it loads the data to the leds... a 30us LOW would leave the leds lit that long not needing continuous reload? Just with the close timing during writes that has to write slower.

HA21:
Good ponint I should get rid of them. In some parts of the programm I will need to use them for the effects but if they have no sense, as you pointed out I will delete them.

Thank you, I will have a look through that guide!

Yes, that tutorial teaches using time in code as well as about not blocking execution. It is the first tool of a simple kind of automation without the overhead of a multi-tasking OS.
Next tool is the finite state machine that sounds more complicated than it is. State machine allows the code to run differently depending on what it's supposed to be doing. They also take a lot less structure than using massive logic trees, usually half the lines or less.
With those two alone you can write very effective automation. Interrupts is the last but save them for special cases as every interrupt has over 80 cycles overhead.

And thank you again, the variables is exactly what I looked for.

The array? In C, all data structures should be arrayable. Arrays of class objects are meat and veg in C++.

The thing with the chip flash would make sense, but is it necessary if we using a MEGA?

The Mega2560 has 256KB flash and 8KB RAM. You could store a whole LOT of patterns in flash. Even in RAM you only read and operate on 1 byte at a time (8 bit CPU), you can do the same with flash. Difference is 2 cycle RAM fetch vs 3 cycle flash fetch vs difference in RAM and flash size. Some would choose to keep an array in RAM that they can change from data in flash.

I have a Rugged Circuits 512K Quadram card for my Mega. It gives 8 banks of 56K heap while the internal 8K is dedicated to stack space. The card ran me less than $30 shipped.

GoForSmoke:
Possibly, do the bits shift out as data via hardware or software? Port or bang?

That totally depends on the processor hardware and software you use to drive the APA102 LED strip.

Also, regarding WS2812, there are libraries that use hardware DMA to shove the required waveforms out of hardware ports with basically nil CPU involvement. The tradeoff is memory efficiency. Examples are:
https://www.pjrc.com/teensy/td_libs_OctoWS2811.html

Of course these techniques won't work on little AVR processors with no DMA and tiny memory.

AVR's are more challenging. (sniff) Their pins are more hobbyist-friendly too.

GoForSmoke:
AVR's are more challenging. (sniff) Their pins are more hobbyist-friendly too.

Not sure I understand your point. AVR processors have neither the DMA hardware nor sufficient memory required to use the technique. That's simply a fact.

That was a joke. The (sniff) didn't give the Poe away?

Adafruit_NeoPixel strip[ ledStrips ];  // I only bet this is possible knowing how C++ works, try it with just 2 strips to test. but what about the other arguments to the object ?

Adafruit_NeoPixel strip1 = Adafruit_NeoPixel(15, PIN1, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip2 = Adafruit_NeoPixel(15, PIN2, NEO_GRB + NEO_KHZ800);

the pin number & the amount of leds don't have a default value.
and to get back to the title of this thread

Command to run 2 or more LED strips simultaneously

you can update them 1 at a time but very quickly after each other, totally simultaneously although theoretically possible, will probably be a bit much for the CPU.
The MEGA should be fine for what you want to do and the well, use thick cables for power & Ground and a thinner one for data.

Yes this would be me, but I don't think I understand programming enough to find how this function is creasted.

Don't underestimate yourself, use an editor like notepad++ to have a look in the library's .cpp file and see if you can work it out, start with the easy ones like fillSolid(), go through a loop in your mind and figure out what is different next time around and how the parameters (arguments) to a function are used to change things.