Gave up on millis and using delay instead for two separate things

I'm using Adafruit to program one addressable LED strip that's 12 lights long, and four "circles" of LEDs which is one light surrounded by six lights, and they're all addressable. On the strip, I'm trying to get blue lights to climb up, stay lit for a bit, then all turn off for a bit. On the circles, I'm trying to get one circle to light up all in red, then turn off and another circle lights up all in red, and so on in a cycle. (It's a Ghostbusters proton pack, the strip is the power bar and the four circles are the lights on the cyclotron.)

Using delay, I was able to get one code to get the power bar to work, and a separate code to get the cyclotron to work. But after struggling with millis() forever to try to combine the two, I gave up. I thought I'd try to fake running both at the same time using delay.

So what I'm trying to do is have the first circle of light to turn on, then turn on the first five lights on the power bar turn on in sequence. Then the first circle of light turns off, and the second circle of lights turns on, and then lights 6 through 10 on the power bar turns on in sequence. Then the third circle turns on, lights 11 then 12 turns on and remains on. The fourth circle turns on, and after a wait, the power bar turns off, and after a wait, the loop should start again.

When I try to run the code, the power bar runs correctly for three cycles and then remains on. The first circle of lights will turn on, but the rest won't. Anyone know what the issue is?

#include <Adafruit_NeoPixel.h>

// Pin of LED strip
uint8_t stripPin = 5;

//Pin for each circle of LEDS
uint8_t circlePin[] = {10,11,12,13};

// Number of lights in LED strip
#define numberOfPixels 12

//Size of each LED circle
#define circleNumberOfPixels 7

//Color of LED circles based on RGB values
uint8_t circleLightColor[] = {255, 0, 0};

//Color of lights based on RGB values
uint8_t stripLightColor[] = {0, 0, 255};

//Brightness of LED Circles
#define circleBrightness 127

//Brightness of LED strip
#define stripBrightness 127

//Create an LED object for each pin

Adafruit_NeoPixel ledStrip = Adafruit_NeoPixel(numberOfPixels, stripPin);

Adafruit_NeoPixel ledCircle0 = Adafruit_NeoPixel(circleNumberOfPixels,circlePin[0]);
Adafruit_NeoPixel ledCircle1 = Adafruit_NeoPixel(circleNumberOfPixels,circlePin[1]);
Adafruit_NeoPixel ledCircle2 = Adafruit_NeoPixel(circleNumberOfPixels,circlePin[2]);
Adafruit_NeoPixel ledCircle3 = Adafruit_NeoPixel(circleNumberOfPixels,circlePin[3]);

Adafruit_NeoPixel circleArray[] = {ledCircle0,ledCircle1,ledCircle2,ledCircle3};

enum CircCycle {CIRCLE1,CIRCLE2,CIRCLE3,CIRCLE4};

CircCycle currentCycle = CIRCLE1;

void setup() {
  ledStrip.begin();
  ledStrip.setBrightness(stripBrightness);
  ledStrip.clear();
  ledStrip.show();
  for (uint8_t n=0;n<=sizeof(circlePin);n++){
    circleArray[n].begin();
    circleArray[n].clear();
    circleArray[n].show();
    circleArray[n].setBrightness(circleBrightness);
  }
}


void loop() {
  switch (currentCycle) {
    case CIRCLE1:
    ledCircle3.clear();
    ledCircle3.show();
    circleLightsOn (ledCircle0, circleLightColor[0], circleLightColor[1], circleLightColor[2]);
    stripLightRegular (0,100);
    stripLightRegular (1,100);
    stripLightRegular (2,100);
    stripLightRegular (3,100);
    stripLightRegular (4,63);
    currentCycle=CIRCLE2;
    break;
    
    case CIRCLE2:
    ledCircle0.clear();
    ledCircle0.show();
    circleLightsOn (ledCircle1, circleLightColor[0], circleLightColor[1], circleLightColor[2]);
    delay(37);
    stripLightRegular (5,100);
    stripLightRegular (6,100);
    stripLightRegular (7,100);
    stripLightRegular (8,100);
    stripLightRegular (9,26);
    currentCycle=CIRCLE3;
    break;

    case CIRCLE3:
    ledCircle1.clear();
    ledCircle1.show();
    circleLightsOn (ledCircle2, circleLightColor[0], circleLightColor[1], circleLightColor[2]);
    delay(74);
    stripLightRegular (10,100);
    stripLightRegular (11, 289);
    currentCycle=CIRCLE4;
    break;

    case CIRCLE4:
    ledCircle2.clear();
    ledCircle2.show();
    circleLightsOn (ledCircle2, circleLightColor[0], circleLightColor[1], circleLightColor[2]);
    delay(113);
    ledStrip.clear();
    ledStrip.show();
    delay(350);
    currentCycle=CIRCLE1;
    break;
  }
}



void stripLightRegular (uint8_t offset, uint16_t delayVal) {
  ledStrip.setPixelColor(offset, ledStrip.Color(stripLightColor[0], stripLightColor[1], stripLightColor[2]));
  ledStrip.show();
  delay(delayVal);
}


void circleLightsOn (Adafruit_NeoPixel circle, uint8_t red,uint8_t green,uint8_t blue){
   for (uint8_t k=0; k<=circleNumberOfPixels;k++) {
    circle.setPixelColor(k,red, green, blue);
   }
   circle.show();
}

have you looked at

you might benefit from studying state machines. Here is a small introduction to the topic: Yet another Finite State Machine introduction

3 Likes

Please share your millis() code with us and let us know what part you struggled.

I agree with @J-M-L on using the state machine for this project.

1 Like

side notes:

you are overflowing here. should be < not <=


when you do this

In C++, when you initialize an array of objects like circleArray using the initializer list as you did, each element in the array is copy-initialized from the corresponding initializer expression.

So, in your case, circleArray elements are copies of ledCircle0, ledCircle1, ledCircle2, and ledCircle3, not references to them. Any changes made to the elements of circleArray will not affect the original objects ledCircle0, ledCircle1, ledCircle2, and ledCircle3, and vice versa.

To build the array you should do

Adafruit_NeoPixel circleArray[] = {
  {circleNumberOfPixels,circlePin[0]}, 
  {circleNumberOfPixels,circlePin[1]}, 
  {circleNumberOfPixels,circlePin[2]}, 
  {circleNumberOfPixels,circlePin[3]}, 
};

and not define ledCircle0, ledCircle1, ledCircle2, and ledCircle3.

2 Likes

Can you post the picure of your setup to show the relative positions of the ledstrip and ledcircles?

Are your four ledcircles are like this (Fig-1)?
circlesleds
Figure-1:

1 Like

not sure why this matters for the code :slight_smile:

I have few of these addressable LEDs and wish to duplicate OP's setup so that I can execute OP's sketch and suggestions of other posters.

it's probably more like this (just a guess)

That is a real one!

OP is saying that he has four circles with 7 LEDS having one in the center and there are four driving DPins; accordingly, I have chalked out the diagram of Fig-1 of post #5.

I think it's four times one like this

That one of post #10 contains cascaded LEDs in two circles and one DPin is enough to drive it. OP is saying that he has four driving DPins.

he has 4 independent Neopixels rings, each being their own strip rather than being cascaded

Sometimes, it is difficult to convert text into pictures that really exist; that's why I have wanted to see OP's setup.

here is a picture that represent the text as I understood it

each strip is independent, as seen in OP's code.

This makes sense to me.

Thanks a lot for the patience to understand what I have been looking for. I don't have
pre-fabricated rings like these; I have to make them from single pieces and joining them together.

they are quite frequent and come in multiple sizes and you can indeed build some kinds of disk if you buy units of different sizes

1 Like

Ach, I’m new to this forum so I’m not so familiar with all the interface. Anyway, J-M-L’s diagram is my exact setup. I got rather ambitious in upgrading my Proton Pack and got those circle LED lights because they’d be brighter. I didn’t realize that there’s no simple “turn all the lights on in this strip” function which would let me treat them like single LEDs.

what about the fill() function ?

1 Like

Would making those copies, passing the objects by value, and overflowing the arrays make it easy to mess up memory and cause a hang?

Edit: Changing to the arrays and array access by index seems to work without hangs, vs the #1 code hanging.

#include <Adafruit_NeoPixel.h>

// Pin of LED strip
uint8_t stripPin = 5;

//Pin for each circle of LEDS
uint8_t circlePin[] = {10,11,12,13};

// Number of lights in LED strip
#define numberOfPixels 12

//Size of each LED circle
#define circleNumberOfPixels 7

//Color of LED circles based on RGB values
uint8_t circleLightColor[] = {255, 0, 0};

//Color of lights based on RGB values
uint8_t stripLightColor[] = {0, 0, 255};

//Brightness of LED Circles
#define circleBrightness 127

//Brightness of LED strip
#define stripBrightness 255

//Create an LED object for each pin

Adafruit_NeoPixel ledStrip = Adafruit_NeoPixel(numberOfPixels, stripPin);

Adafruit_NeoPixel circleArray[] = {
  {circleNumberOfPixels,circlePin[0]}, 
  {circleNumberOfPixels,circlePin[1]}, 
  {circleNumberOfPixels,circlePin[2]}, 
  {circleNumberOfPixels,circlePin[3]}, 
};

enum CircCycle {CIRCLE1,CIRCLE2,CIRCLE3,CIRCLE4};
byte circleIndex =0;

CircCycle currentCycle = CIRCLE1;

void setup() {
  Serial.begin(115200);
  ledStrip.begin();
  ledStrip.setBrightness(stripBrightness);
  ledStrip.clear();
  ledStrip.show();
  for (uint8_t n=0;n<sizeof(circlePin);n++){
    circleArray[n].begin();
    circleArray[n].clear();
    circleArray[n].show();
    circleArray[n].setBrightness(circleBrightness);
  }
}


void loop() {
  switch (currentCycle) {
    case CIRCLE1:
    circleArray[3].clear();
    circleArray[3].show();
    circleIndex = 0;
    circleLightsOn (circleIndex, circleLightColor[0], circleLightColor[1], circleLightColor[2]);
    stripLightRegular (0,100);
    stripLightRegular (1,100);
    stripLightRegular (2,100);
    stripLightRegular (3,100);
    stripLightRegular (4,63);
    currentCycle=CIRCLE2;
    break;
    
    case CIRCLE2:
    circleArray[0].clear();
    circleArray[0].show();
    circleIndex = 1;
    circleLightsOn (circleIndex, circleLightColor[0], circleLightColor[1], circleLightColor[2]);
    delay(37);
    stripLightRegular (5,100);
    stripLightRegular (6,100);
    stripLightRegular (7,100);
    stripLightRegular (8,100);
    stripLightRegular (9,26);
    currentCycle=CIRCLE3;
    break;

    case CIRCLE3:
    circleArray[1].clear();
    circleArray[1].show();
    circleIndex = 2;
    circleLightsOn (circleIndex, circleLightColor[0], circleLightColor[1], circleLightColor[2]);
    delay(74);
    stripLightRegular (10,100);
    stripLightRegular (11, 289);
    currentCycle=CIRCLE4;
    break;

    case CIRCLE4:
    circleArray[2].clear();
    circleArray[2].show();
    circleIndex = 3;
    circleLightsOn (circleIndex, circleLightColor[0], circleLightColor[1], circleLightColor[2]);
    delay(113);
    ledStrip.clear();
    ledStrip.show();
    delay(350);
    currentCycle=CIRCLE1;
    break;
  }
  report();
}



void stripLightRegular (uint8_t offset, uint16_t delayVal) {
  ledStrip.setPixelColor(offset, ledStrip.Color(stripLightColor[0], stripLightColor[1], stripLightColor[2]));
  ledStrip.show();
  delay(delayVal);
}


void circleLightsOn (uint8_t circleIndex, uint8_t red,uint8_t green,uint8_t blue){
   for (uint8_t k=0; k<circleNumberOfPixels;k++) {
    circleArray[circleIndex].setPixelColor(k,red, green, blue);
   }
   circleArray[circleIndex].show();
}


void report(void){
  static uint32_t last = 0;
  if(millis() - last < 500) return;
  Serial.print(".");
   Serial.print(currentCycle);
}

with this .json file on Wokwi:

{
  "version": 1,
  "author": "David Forrest",
  "editor": "wokwi",
  "parts": [
    { "type": "wokwi-arduino-mega", "id": "mega", "top": 0, "left": 0, "attrs": {} },
    {
      "type": "wokwi-led-ring",
      "id": "ring1",
      "top": -239.36,
      "left": 202.79,
      "attrs": { "pixels": "12" }
    },
    {
      "type": "wokwi-led-ring",
      "id": "ring2",
      "top": -210.56,
      "left": -46.81,
      "attrs": { "pixels": "7" }
    },
    {
      "type": "wokwi-led-ring",
      "id": "ring3",
      "top": -310.01,
      "left": 47.47,
      "attrs": { "pixels": "7" }
    },
    {
      "type": "wokwi-led-ring",
      "id": "ring4",
      "top": -214.01,
      "left": 47.47,
      "attrs": { "pixels": "7" }
    },
    {
      "type": "wokwi-led-ring",
      "id": "ring5",
      "top": -310.01,
      "left": -48.53,
      "attrs": { "pixels": "7" }
    }
  ],
  "connections": [
    [ "ring1:DIN", "mega:5", "green", [ "v57.6", "h-9.6" ] ],
    [ "ring4:DIN", "mega:10", "green", [ "v28.8", "h-19.2", "v38.4" ] ],
    [ "ring3:DIN", "mega:11", "green", [ "v9.6", "h28.8" ] ],
    [ "ring2:DIN", "mega:12", "green", [ "v19.2", "h57.6" ] ],
    [ "ring5:DIN", "mega:13", "green", [ "v-19.2", "h249.6" ] ]
  ],
  "dependencies": {}
}

Adafruit's library does bounds checking, so you can get lazy and write to any pixel.

FastLED has us write directly into pixel buffers we were responsible for creating, and we do our own bounds checking or as I prefer to call it live dangerously as in we don't need no stinkin' bounds checking.

a7

1 Like