Go Down

Topic: [tuto] WS2812 independent patterns on a single strip (Read 1 time) previous topic - next topic

Hi!  :)

I'm opening this topic to share what I have found on this subject, share my work in progress and get some help if needed  :smiley-wink:

► I would like to display independent patterns on one single strip: the project is to light a pinball.

chasing effect below the ramp
blink target to get bonus
rainbow effect when success
fading effects to illuminate backglass





► list of components:
About LED technologies comparison:
https://www.tweaking4all.com/hardware/arduino/arduino-ws2812-led/

I've bought a WS2812/WS2811 strip of 50 RGB leds


https://fr.aliexpress.com/item/50pcs-Pre-wired-WS2812B-led-Chip-with-Heatsink-DC5V-WS2811-control-individually-Addressable-led-pixel-strip/32582314997.html
9€


I'm using a Arduino Nano 328
https://store.arduino.cc/arduino-nano 20€


and a power supply 5V
50 LEDs: 15 Watts (about 3 Amps at 5 Volts)

https://fr.aliexpress.com/item/1PCS-5V3A-AC-100V-240V-Converter-Adapter-DC-5V-3A-3000mA-Power-Supply-EU-Plug-5/32700939534.html 2€


In order to get independence in the tasks, I followed the hint of "blink without delay"
https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay

a johnwasser code example "DaftPunkLights"
https://forum.arduino.cc/index.php?topic=105210.msg789378#msg789378

another code example
https://arduino.stackexchange.com/questions/3248/multiple-independent-led-patterns

► libraries
and I found some dedicated libraries
neopixel adafruit https://github.com/adafruit/Adafruit_NeoPixel
and tutorial https://learn.adafruit.com/multi-tasking-the-arduino-part-3/deconstructing-the-loop


FastLEd
https://github.com/FastLED/FastLED/wiki/Multiple-Controller-Examples

Arduino Light Animation (ALA)
http://yaab-arduino.blogspot.fr/p/ala.html

Grumpy_Mike


This tutorial https://learn.adafruit.com/multi-tasking-the-arduino-part-3/deconstructing-the-loop
explains in detail how to drive several strips, each strip with its own pattern

But I would like to spare some pins and drive only a single strip!

I'll try to adapt the code to my use. Or I will rethink cutting the strip in multiple strips...

Thanks Grumpy_Mike, I will look at your code right now!

Grumpy_Mike

Quote
But I would like to spare some pins and drive only a single strip!
Then that is even simpler. Just use a restricted range of LED numbers for each pattern you want to work on.

I did it on a matrix and had each line of the matrix do a different pattern. However the code was in Python so not much point in posting it here.

I did that (but I didn't find it simplier  ::) ... I had to pass sub strips instead of patterns to the functions.

I created a structure to store informations on the sub strips and its associated pattern.

This draft is compiling OK (but untested yet, my hardware is at home)



Code: [Select]

// StrandTest from AdaFruit implemented as a state machine
// pattern change by push button
// By Mike Cook Jan 2016

#define PINforControl   7 // pin connected to 1 single NeoPixels strip
#define NUMPIXELS1      20 // number of LEDs on strip

#include <Adafruit_NeoPixel.h>

Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS1, PINforControl, NEO_GRB + NEO_KHZ800);
// Pattern types supported:
enum  pattern_type { NONE, BLINK, RAINBOW, RAINBOW_CYCLE, THEATER_CHASE_RAINBOW, COLOR_WIPE, FADING };

[b]struct subStrips {
  uint16_t startIndex;
  uint16_t nb_LED;
  pattern_type  activePattern;
  unsigned long patternInterval;
  unsigned long lastUpdate;
};[/b]

[b]// declare substrips
// the 20 LED are grouped by 7, 1, 1, 1, 1, 1, 7 (see image in the post)

subStrips stripRamp = {0, 7, THEATER_CHASE_RAINBOW, 20, 0 };
subStrips stripSingle1 = {7, 1, NONE, 20, 0 };
subStrips stripSingle2 = {8, 1, FADING, 20, 0 };
subStrips stripSingle3 = {9, 1, RAINBOW, 20, 0 };
subStrips stripSingle4 = {10, 1, BLINK, 20, 0 };
subStrips stripSingle5 = {11, 1, RAINBOW, 20, 0 };
subStrips stripAmbilight = {12, 7, RAINBOW_CYCLE, 20, 0 };[/b]

unsigned long patternInterval = 20 ; // time between steps in the pattern
unsigned long lastUpdate = 0 ; // for millis() when last update occoured
unsigned long intervals [] = { 20, 20, 50, 100 } ; // speed for each pattern
const byte button = 2; // pin to connect button switch to between pin and ground

void setup() {
  strip.begin(); // This initializes the NeoPixel library.
  wipe(); // wipes the LED buffers
  pinMode(button, INPUT_PULLUP); // change pattern
}

void loop() {
  // subStrip Ramp
  if(millis() - stripRamp.lastUpdate > stripRamp.patternInterval) updateSubStripPattern(stripRamp);
  // subStrip Single1
  if(millis() - stripSingle1.lastUpdate > stripSingle1.patternInterval) updateSubStripPattern(stripSingle1);
  //...
}

void  updateSubStripPattern(subStrips &substripOut){ // out parameter
  switch(substripOut.activePattern) {
    case NONE :
    wipeSubStrip(substripOut);
        break;
    case RAINBOW :
        rainbow(substripOut);
        break;
    case RAINBOW_CYCLE:
        rainbowCycle(substripOut);
        break;
    case THEATER_CHASE_RAINBOW:
        theaterChaseRainbow(substripOut);
        break;
    case COLOR_WIPE:
         colorWipe(substripOut, strip.Color(255, 0, 0)); // red
         break;    
    case BLINK:
        blinkEffect(substripOut, 111);
        break;
  }
}

void blinkEffect(subStrips &substrip, uint32_t color) {
    for(int i=substrip.startIndex; i<(substrip.startIndex+substrip.nb_LED) ; i++) {
      if (strip.getPixelColor(i) == 0) { strip.setPixelColor(i, color); }
      else { strip.setPixelColor(i, 0); }
    }
    strip.show();
    substrip.lastUpdate = millis(); // time for next change to the display
}


void rainbow(subStrips &substrip) { // modified from Adafruit example to make it a state machine
  static uint16_t j=0;
    for(int i=substrip.startIndex; i<(substrip.startIndex+substrip.nb_LED) ; i++) {
      strip.setPixelColor(i, Wheel((i+j) & 255));
    }
    strip.show();
     j++;
  if(j >= 256) j=0;
  substrip.lastUpdate = millis(); // time for next change to the display
}

void rainbowCycle(subStrips &substrip) { // modified from Adafruit example to make it a state machine
//
}

void theaterChaseRainbow(subStrips &substrip) { // modified from Adafruit example to make it a state machine
//  
}

void colorWipe(subStrips &substrip, uint32_t c) { // modified from Adafruit example to make it a state machine
//
}


void wipeSubStrip(subStrips &substrip){ // clear all LEDs
    for(int i=substrip.startIndex; i<(substrip.startIndex+substrip.nb_LED) ; i++) {
       strip.setPixelColor(i, strip.Color(0,0,0));
    }
    strip.show();
    // substrip.lastUpdate = millis(); // no need to refresh LED off
 substrip.patternInterval = 10000000; // no need to refresh LED off
}
 
 
void wipe(){ // clear all LEDs
     for(int i=0;i<strip.numPixels();i++){
       strip.setPixelColor(i, strip.Color(0,0,0));
       }
}

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




Grumpy_Mike

Quote
I had to pass sub strips instead of patterns to the functions.
That seems an odd and complex way of doing things.

- I'm glad to say it works fine! : multiple simultaneous patterns on my single LED strip!

(just corrected my draft Blink function which didn't blink  :D  i'll edit the previous post)
Code: [Select]
void blinkEffect(subStrips &substrip, uint32_t color) {
    for(int i=substrip.startIndex; i<(substrip.startIndex+substrip.nb_LED) ; i++) {
      if (strip.getPixelColor(i) == 0) { strip.setPixelColor(i, color); }
      else { strip.setPixelColor(i, 0); }
    }
    strip.show();
    substrip.lastUpdate = millis(); // time for next change to the display
}


- Thanks Grumpy_Mike!
In my grand scheme  :-[  it seemed interesting to address orders to sub strip passing pattern as an argument.
Please advice me another way to follow!

Pandora114118

#8
Aug 08, 2018, 01:52 pm Last Edit: Aug 08, 2018, 06:43 pm by Pandora114118
Hi Mat

Did you ever finish this program by adding the extra Modes in?


Thanks for help

P.

Hi! I added few effects but not many... as I'm busy on other parts of my pinball code.

I needed a proof of concept to validate my choice for lightning. I'll come back later and dig deeper ;)

What's your project @Pandora114118?

gegg

I did that (but I didn't find it simplier  ::) ... I had to pass sub strips instead of patterns to the functions.

I created a structure to store informations on the sub strips and its associated pattern.

This draft is compiling OK (but untested yet, my hardware is at home)




Maybe you can create another pixel strip object for different segment of the same strip and put them running into the same State Machine timing control.

OR , try this library

https://github.com/kitesurfer1404/WS2812FX

Go Up