If I have 20 pixels on a ws2812b led strip, can I program something for the first, say, 6 pixels (I'm calling the LEDs pixels for now) , and something else on the rest of the strip, to run independently? Or am I a dreamer and should have put a second data line in my model?
Yes
You can also have more than 1 (one) strip.
Sure, the pixels are numbered 0…n, so you can set up any pattern or animation in your array, then refresh as often as you need.
Limitations are memory, power to the LESs, and the maximum refresh allowed by the WS28xx chips.
Too late, it is already installed into the model. If wore comes to worst, I can add another data line. I think
Jim Smagata
647-890-4397
Freelance Tech Theatre Services
That’s reasonable.
Cut the trace on the strip and use 28AWG (16 strand) silicone insulated wire to the data input side.
What's the problem with doing what you first proposed?
Yeah, that is all in software. You can do absolutely anything with any pixel, they are completely independently programmable. Since they are indexed by number in software, that is the key to partitioning them. Usually that is done with "offsets". So if you had some routine that ran on LEDS 0-5, you can just add 5 and it will do the same pattern on LEDs 5-12.
BTW, Jim, hi neighbor in GTA!
The problem is, I was trying different ways of addressing the pixels I wanted, but I just couldn't seem to get them to work separately- one usually joined the other. I'm just not experienced enough. I just wanted to have some reassurance that it can be done. Pictured: Here's the thing. 0 to 4-breathing red (maybe, if I can figure it out, a little amber mixing action). 5-static white. 6-24 - programmed for a few things that go with a button press. Light up, flash, light off. This last part I got, I just need to figure how to tell it to only address the last 19 pixels instead of NUM_LEDS.
Nacelle_lighting|690x179
Please upload pictures to the forum, don't post external links unnecessarily.
Please post your code, the version where you tried to achieve what you wanted but were unable to make it work. Describe what you wanted and what actually happened. Please auto-format the code and post it using code tags.
Yes it can be done but this is best done by using a state machine so that each animation can run at its own speed. This is a step up in programming for a beginner and is based on the Blink Without Delay example in the IDE.
Here is some code I wrote for doing just what you wanted
// Multiple patterns in a state machine format
// using the FastLED library
// by Mike Cook 2017
#include "FastLED.h"
// first set up the parameters to use in the pattern calling
unsigned long patternInterval [] = { 500, 40, 20, 200, 5 }; // how often each pattern updates
unsigned long lastUpdate [5] ; // for millis() when last update occurred
boolean patternEnabled [] = {true,true,false,true,true}; // should the pattern be called at all
byte patternState[5]; // state machine variable for patterns - this initialises them to zero
// now set up the LEDs to use
#define NUM_LEDS 64
#define DATA_PIN 3
#define CLOCK_PIN 13
CRGB leds[NUM_LEDS];
// Constants for patterns
// for Fire2012
#define COOLING 20
#define SPARKING 50
#define COLOR_ORDER BGR
// now set up the array of pointers to each pattern
void (*patternPtrs[5])(int index,byte state); //the array of pattern pointers
void setup() {
//initialises the array of pattern pointers
patternPtrs[0] = blinkOne;
patternPtrs[1] = cylon;
patternPtrs[2] = fire;
patternPtrs[3] = colorWipe;
patternPtrs[4] = rainbowCycle;
//initialises the FastLED driver you want
//FastLED.addLeds<APA102,leds, NUM_LEDS); // 13 clock and 11 data
FastLED.addLeds<APA102, DATA_PIN, CLOCK_PIN, BGR>(leds, NUM_LEDS); // 13 clock and 11 data
FastLED.setBrightness(8);
}
void loop() {
for(int i = 0; i<5; i++) { // go through all the patterns and see if it is time to call one
if(patternEnabled[i] && millis() - lastUpdate[i] > patternInterval[i]){
lastUpdate[i] = millis();
callPatterns(i, patternState[i]);
}
}
}
void callPatterns(int index, byte state) {
(*patternPtrs[index])(index,state); //calls the pattern at the index of `index` in the array
}
// These are the pattern functions written as a state machine
// this is the Blink program in FastLED's example folder
void blinkOne(int index,byte state) {
if(state == 0){
leds[3] = CRGB::Blue;
FastLED.show();
patternState[index] = 1; // move on the state machine for the next call
}
if(state == 1){
leds[3] = CRGB::Black;
FastLED.show();
patternState[index] = 0;
}
}
// this is the Cylon program in FastLED's example folder
// we will use LEDs 8 to 15 to show this
void cylon(int index,byte state) {
static int i = 8; // replaces the loop index
if(state == 0){
leds[i] = CRGB::Red;
FastLED.show();
patternState[index] = 1; // move on the state machine for the next call
}
if(state == 1){
// now that we've shown the leds, reset the i'th led to black
leds[i] = CRGB::Black;
i++; // increment what was the loop variable
if(i >= 16){ // we have finished one direction
patternState[index] = 2;
i--;
}
else {
patternState[index] = 0;
}
}
// Now go in the other direction only green
if(state == 2){
leds[i] = CRGB::Green;
FastLED.show();
patternState[index] = 3; // move on the state machine for the next call
}
if(state == 3){
// now that we've shown the leds, reset the i'th led to black
leds[i] = CRGB::Black;
i--; // decrement what was the loop variable
if(i < 8){ // we have finished the return, go back to the start
patternState[index] = 0;
i= 8; // ready to start again
}
else {
patternState[index] = 2;
}
// note that this could be better implemented but it has been written like this to keep it close to the original example
// so you can see what changes have been made
}
}
// this is the Fire2012 program in FastLED's example folder
void fire(int index,byte state) {
// using LEDs 16 to 32
// Array of temperature readings at each simulation cell
const byte startLED = 16; // first LED in section
const byte numLEDs = 16;
static byte heat[numLEDs];
random16_add_entropy( random());
// Step 1. Cool down every cell a little
for( int i = 0; i < numLEDs; i++) {
heat[i] = qsub8( heat[i], random8(0, ((COOLING * 10) / NUM_LEDS) + 2));
}
// Step 2. Heat from each cell drifts 'up' and diffuses a little
for( int k= numLEDs - 1; k >= 2; k--) {
heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3;
}
// Step 3. Randomly ignite new 'sparks' of heat near the bottom
if( random8() < SPARKING ) {
int y = random8(7);
heat[y] = qadd8( heat[y], random8(160,255) );
}
// Step 4. Map from heat cells to LED colors
for( int j = 0; j < numLEDs; j++) {
leds[j+startLED] = HeatColor( heat[j]); // transfer heat array to LEDs
}
FastLED.show(); // display this frame
}
//colorWipe modified from Adafruit example to make it a state machine
// uses LEDs 32 to 40
void colorWipe(int index,byte state) {
static int i =0; // used as state variable
static byte firstLED = 32;
static byte numLEDs = 8;
leds[i+firstLED] = CRGB::Yellow;
FastLED.show();
i++;
if(i >= numLEDs){
i = 0;
for(int j;j<numLEDs; j++) leds[j+firstLED] = CRGB::Black; // blank out strip
}
}
// rainbowCycle modified from Adafruit example to make it a state machine
// uses LEDs 48 to 64
void rainbowCycle(int index,byte state) {
static uint16_t j=0; // used as state variable
static byte firstLED = 48;
static byte numLEDs = 16;
for(int i=0; i< numLEDs; i++) {
leds[i+firstLED].setHSV( (((i * 256 / numLEDs) + j) & 255), 255, 255);
}
FastLED.show();
j++;
if(j >= 256*5) j=0;
}
Note this example is for the APA102 type addressable strip. If you are using another type then just call the correct initialiser for your type of LED in the setup function.
Thanks. I will.
That's a lot to take in, and thanks. I'll go over this carefully so I can try to understand it all, as I, admittedly, am still learning.
Yes it is I do appreciate this, but this is why I wrote the code in the first place. If there are any bits you don't understand what they are doing then please ask.
For a simplified view of a state machine
See my
http://www.thebox.myzen.co.uk/Tutorial/State_Machine.html
Or Robin2's several things at once
http://forum.arduino.cc/index.php?topic=223286.0
If this is all you want to do then post the code (in code tags) and we can probably tell you an easer way of doing it than a state machine.
Note read
how to get the best out of this forum to learn about posting code here in code tags.
Another trick is to use the CPixelView class from the FastLED library. It allows you to "break" a single physical LED strip into multiple logical strips. The library handles the index offsets for you.
Let say you have 25 LEDs total and want the first logical strip to access physical LEDs 0-5 and the second logical strip to access physical LEDs 6-24:
#include <Arduino.h>
#include <FastLED.h>
const uint8_t ledCount = 25;
const uint8_t startGroup0 = 0;
const uint8_t lengthGroup0 = 6;
const uint8_t startGroup1 = 6;
const uint8_t lengthGroup1 = 19;
const uint8_t ledPin = 3;
CRGB leds[ledCount];
CPixelView<CRGB> group0(leds, startGroup0, lengthGroup0);
CPixelView<CRGB> group1(leds, startGroup1, lengthGroup1);
void setup() {
FastLED.addLeds<WS2812, ledPin, RGB>(leds, ledCount);
}
So then, you'd update the first group using group0[0] - group0[5] and update the second group using group1[0] - group1[18]. Again, the library will take care of offsetting into the full 'leds' array for you.
After updating all your patterns, FastLED.show() actually writes the new data (i.e. colors) to the entire physical strip at one time.
WHATTHEHECK!! That sounds like just the thing.
I was going to upload the code I was trying to get to work, but because none did, I didn't save any. I can still upload the main sketch that I would have to modify for this. We'll see.
Thank you.
Are there any more documentation or examples I can use to see how to incorporate this?
Idealy, I want, at the push of a button, a fade in and effect on group 1, steady on group 2 ( a single pixel) and another effect (counting up to a fill of the rest of the pixels) in sequence. And then at the 4th push of the same button (using cases) the reverse happens.
I have them as separate elements, but I am not sure how to use this setup for my project.
Aside from the actual FastLED source code (where I found these constructs) I'm not aware of any, but I haven't really looked. You might try Googling around.
I just noticed a slight error in the example code I provided. The CPixelView objects should be created as:
CPixelView<CRGB> group0(leds + startGroup0, lengthGroup0);
CPixelView<CRGB> group1(leds + startGroup1, lengthGroup1);
Anyway, you can find the class definition Here.