neopixel WS2812 split strip into groups

Greetings,

I have a strip of 10 WS2812 RGB LEDs and I am trying to do the following:

  1. Make the first 7 LEDs (0-6) flicker using the Adafruit Neopixel Fire function
  2. Make LEDs 7 and 8 a constant colour (BLUE) or flash, etc.
  3. The last LED (9) I want to flash (RED 1Hz) or remain a constant colour, etc.

I think my issue is understanding the Adafruit library because without using the fire function I can handle the LEDs separately no issue. Or I can use only the fire function and handle all the LEDS but my knowledge breaks down when I try to mix the two.

  • I have implemented an interrupt to handle the flash currently it is only blinking the on-board LED.

Any help splitting my strip would be really appreciated.

Here is the code i am trying to use but I'm not sure how to start handling the last 3 LEDs :

 /**
 * Arduino Uno - NeoPixel Fire
 * v. 1.0
 * Copyright (C) 2015 Robert Ulbricht
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <Adafruit_NeoPixel.h>

#define ledPin 13

// data pin
#define PIN 5
// led count
#define CNT 9

//first 7 lEDS are engine 
#define engine1_cnt 6

//two interior lights 
#define interior2 7 
#define interior1 8

// front Navation light 
#define NAV_light 9

boolean timer =false; 


// Parameter 1 = number of pixels in strip
// Parameter 2 = pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_RGB     Pixels are wired for RGB bitstream
//   NEO_GRB     Pixels are wired for GRB bitstream
//   NEO_KHZ400  400 KHz bitstream (e.g. FLORA pixels)
//   NEO_KHZ800  800 KHz bitstream (e.g. High Density LED strip)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(CNT, PIN, NEO_GRB + NEO_KHZ800);


//uint32_t fire_color   = strip.Color ( 0,  0, 255);    //( 200,  35,  0);
uint32_t fire_color   = strip.Color ( 200,  50,  10);    //( 200,  35,  0);
uint32_t off_color    = strip.Color (  0,  0,  0);
uint32_t white_color   = strip.Color (  255,  255,  255);

///
/// Fire simulator
///

class NeoFire
{
  Adafruit_NeoPixel &strip;
  public:

  NeoFire(Adafruit_NeoPixel&);
  void Draw();
  void Clear();
  void ClearALL();
  void AddColor(uint8_t position, uint32_t color);
  void SubstractColor(uint8_t position, uint32_t color);
  uint32_t Blend(uint32_t color1, uint32_t color2);
  uint32_t Substract(uint32_t color1, uint32_t color2);
};

///
/// Constructor
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
NeoFire::NeoFire(Adafruit_NeoPixel& n_strip)
: strip (n_strip)
{
}

///
/// Set all colors
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void NeoFire::Draw()
{
Clear();

for(int i=0;i<CNT;i++)  //for(int i=0;i<CNT;i++)
  {
  AddColor(i, fire_color);
  int r = random(80);
  uint32_t diff_color = strip.Color ( r, r/2, r/2);
  SubstractColor(i, diff_color);
  }
  
strip.show();
}



///
/// Set color of LED
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void NeoFire::AddColor(uint8_t position, uint32_t color)
{
uint32_t blended_color = Blend(strip.getPixelColor(position), color);
strip.setPixelColor(position, blended_color);
}

///
/// Set color of LED
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void NeoFire::SubstractColor(uint8_t position, uint32_t color)
{
uint32_t blended_color = Substract(strip.getPixelColor(position), color);
strip.setPixelColor(position, blended_color);
}

///
/// Color blending
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
uint32_t NeoFire::Blend(uint32_t color1, uint32_t color2)
{
uint8_t r1,g1,b1;
uint8_t r2,g2,b2;
uint8_t r3,g3,b3;

r1 = (uint8_t)(color1 >> 16),
g1 = (uint8_t)(color1 >>  8),
b1 = (uint8_t)(color1 >>  0);

r2 = (uint8_t)(color2 >> 16),
g2 = (uint8_t)(color2 >>  8),
b2 = (uint8_t)(color2 >>  0);

return strip.Color(constrain(r1+r2, 0, 255), constrain(g1+g2, 0, 255), constrain(b1+b2, 0, 255));
}

///
/// Color blending
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
uint32_t NeoFire::Substract(uint32_t color1, uint32_t color2)
{
uint8_t r1,g1,b1;
uint8_t r2,g2,b2;
uint8_t r3,g3,b3;
int16_t r,g,b;

r1 = (uint8_t)(color1 >> 16),
g1 = (uint8_t)(color1 >>  8),
b1 = (uint8_t)(color1 >>  0);

r2 = (uint8_t)(color2 >> 16),
g2 = (uint8_t)(color2 >>  8),
b2 = (uint8_t)(color2 >>  0);

r=(int16_t)r1-(int16_t)r2;
g=(int16_t)g1-(int16_t)g2;
b=(int16_t)b1-(int16_t)b2;
if(r<0) r=0;
if(g<0) g=0;
if(b<0) b=0;

return strip.Color(r, g, b);
}

///
/// Every LED to black
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void NeoFire::Clear()
{
for(uint16_t i=0; i<strip.numPixels(); i++)          //for(uint16_t i=0; i<strip.numPixels (); i++)
  strip.setPixelColor(i, off_color);
}

NeoFire fire(strip);



/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Setup
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void setup()
{

pinMode(ledPin, OUTPUT);

  // initialize timer1 
  noInterrupts();           // disable all interrupts
  TCCR1A = 0;
  TCCR1B = 0;

  TCNT1 = 34286;            // preload timer 65536-16MHz/256/2Hz
  TCCR1B |= (1 << CS12);    // 256 prescaler 
  TIMSK1 |= (1 << TOIE1);   // enable timer overflow interrupt
  interrupts();             // enable all interrupts
  strip.begin();
  strip.show();               // Initialize all pixels to 'off'



}


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// ISR
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ISR(TIMER1_OVF_vect)                                // interrupt service routine that wraps a user defined function supplied by attachInterrupt
{
  TCNT1 = 34286;                                    // preload timer
  timer = !timer;          

  digitalWrite(ledPin, digitalRead(ledPin) ^ 1);    // flast onboard LED to indicate interrupt 
}


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Main loop
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void loop()
{

fire.Draw();
delay(random(2,20));
}

Drawing1.jpg

You have

#define CNT 9

And then in the fire code you have

for(int i=0;i<CNT;i++)

Which tells the fire code to use all 9 LEDs.

If you want to stop the fire code from stamping over the other LEDs then restrict the for loop to just use the first 7 LEDs.

You will also need to restrict the pixels that are cleared in the fire code so it doesn't clear all the pixels.

void NeoFire::Clear(){
  for(uint16_t i=0; i<strip.numPixels(); i++)         
    strip.setPixelColor(i, off_color);
}

Thanks Mike,

I have tried that already but it doesn't work as i would expect...

Actually I changed the variable CNT to 6 in two locations for the Draw and Clear functions and tried a combination of both. The best result I have managed is that I can change the colour of the last 3 leds but they still flicker with the fire effect.

leave cnt as it is and use your engine1_cnt

I removed also the interrupt code as it can be done with millis only.
Here's a code with 6 flickering pixels, one blinking pixel:

/**
  Arduino Uno - NeoPixel Fire
  v. 1.0
  Copyright (C) 2015 Robert Ulbricht

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <Adafruit_NeoPixel.h>

#define ledPin 13

// data pin
#define PIN 5
// led count
#define CNT 9

//first 7 lEDS are engine
#define engine1_cnt 6

//two interior lights
#define interior2 7
#define interior1 8

// front Navation light
#define NAV_light 9

boolean timer = false;

unsigned long lastMillisFire = 0;
unsigned long lastMillisBlink = 0;



// Parameter 1 = number of pixels in strip
// Parameter 2 = pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_RGB     Pixels are wired for RGB bitstream
//   NEO_GRB     Pixels are wired for GRB bitstream
//   NEO_KHZ400  400 KHz bitstream (e.g. FLORA pixels)
//   NEO_KHZ800  800 KHz bitstream (e.g. High Density LED strip)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(CNT, PIN, NEO_GRB + NEO_KHZ800);


//uint32_t fire_color   = strip.Color ( 0,  0, 255);    //( 200,  35,  0);
uint32_t fire_color   = strip.Color ( 200,  50,  10);    //( 200,  35,  0);
uint32_t off_color    = strip.Color (  0,  0,  0);
uint32_t white_color   = strip.Color (  255,  255,  255);

///
/// Fire simulator
///

class NeoFire
{
    Adafruit_NeoPixel &strip;
  public:

    NeoFire(Adafruit_NeoPixel&);
    void Draw();
    void Clear();
    void ClearALL();
    void AddColor(uint8_t position, uint32_t color);
    void SubstractColor(uint8_t position, uint32_t color);
    uint32_t Blend(uint32_t color1, uint32_t color2);
    uint32_t Substract(uint32_t color1, uint32_t color2);
};

///
/// Constructor
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
NeoFire::NeoFire(Adafruit_NeoPixel& n_strip)
  : strip (n_strip)
{
}

///
/// Set all colors
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void NeoFire::Draw()
{
  Clear();

  for (int i = 0; i < engine1_cnt; i++) //for(int i=0;i<CNT;i++)
  {
    AddColor(i, fire_color);
    int r = random(80);
    uint32_t diff_color = strip.Color ( r, r / 2, r / 2);
    SubstractColor(i, diff_color);
  }

  strip.show();
}



///
/// Set color of LED
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void NeoFire::AddColor(uint8_t position, uint32_t color)
{
  uint32_t blended_color = Blend(strip.getPixelColor(position), color);
  strip.setPixelColor(position, blended_color);
}

///
/// Set color of LED
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void NeoFire::SubstractColor(uint8_t position, uint32_t color)
{
  uint32_t blended_color = Substract(strip.getPixelColor(position), color);
  strip.setPixelColor(position, blended_color);
}

///
/// Color blending
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
uint32_t NeoFire::Blend(uint32_t color1, uint32_t color2)
{
  uint8_t r1, g1, b1;
  uint8_t r2, g2, b2;
  uint8_t r3, g3, b3;

  r1 = (uint8_t)(color1 >> 16),
  g1 = (uint8_t)(color1 >>  8),
  b1 = (uint8_t)(color1 >>  0);

  r2 = (uint8_t)(color2 >> 16),
  g2 = (uint8_t)(color2 >>  8),
  b2 = (uint8_t)(color2 >>  0);

  return strip.Color(constrain(r1 + r2, 0, 255), constrain(g1 + g2, 0, 255), constrain(b1 + b2, 0, 255));
}

///
/// Color blending
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
uint32_t NeoFire::Substract(uint32_t color1, uint32_t color2)
{
  uint8_t r1, g1, b1;
  uint8_t r2, g2, b2;
  uint8_t r3, g3, b3;
  int16_t r, g, b;

  r1 = (uint8_t)(color1 >> 16),
  g1 = (uint8_t)(color1 >>  8),
  b1 = (uint8_t)(color1 >>  0);

  r2 = (uint8_t)(color2 >> 16),
  g2 = (uint8_t)(color2 >>  8),
  b2 = (uint8_t)(color2 >>  0);

  r = (int16_t)r1 - (int16_t)r2;
  g = (int16_t)g1 - (int16_t)g2;
  b = (int16_t)b1 - (int16_t)b2;
  if (r < 0) r = 0;
  if (g < 0) g = 0;
  if (b < 0) b = 0;

  return strip.Color(r, g, b);
}

///
/// Every LED to black
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void NeoFire::Clear()
{
  for (uint16_t i = 0; i < engine1_cnt; i++)     //for(uint16_t i=0; i<strip.numPixels (); i++)
    strip.setPixelColor(i, off_color);
}

NeoFire fire(strip);

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Setup
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void setup()
{
  pinMode(ledPin, OUTPUT);
  strip.begin();
  strip.show();               // Initialize all pixels to 'off'
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Main loop
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void loop()
{
  if (millis() - lastMillisFire > random(2, 20))
  {
    fire.Draw();
    lastMillisFire = millis();
  }

  if (millis() - lastMillisBlink > 500)
  {
    static bool isOn = false;
    if (isOn) 
    {
      strip.setPixelColor(interior2, 0);
      isOn = false;
    }
    else
    {
      strip.setPixelColor(interior2, 128);
      isOn = true;
    }
    strip.show();
    lastMillisBlink = millis();
  }
}

Didn't want to keep the timers also, therefore it could be that you need to adopt the random intervall also. e.g. to random(50, 200))
test and let me know if it is not what you would expect ...

Wow thank you noiasca! that works perfectly.

I managed to get it working using the interrupt because I want it for other things

I am still working on the finishing touches but I have added a video to say thanks to everyone for the help!

Coming soon:

  • Finalise the Lego housing for the front NAV light
  • Correct the colour for the internal illumination and add some blinking red and green dials
    *Add red blinking recording LED to external camera and white floodlight
  • Add pinhole arduino camera to "broadcast" the LEM external camera view to a small OLED display.

Note: its all build using magnetic connectors so you can still take it to pieces without pulling wires.

Cheers!

try again

I doubt the real need of interupts in a shiny-blink-blink-code with delays ... :wink: