Storing and referencing adafruit object in variable inside a struct

I have small problem on defining and referencing an adafruit_Neopixel object that i want to put in a variable inside a struct here is the defenition of the struct,

struct ledPanels {
  int GPIONO ;         // hold the pinNumber of each GPIO Used
  int NUMLEDS ;     // Number of leds per panel or strip
  long defColor ;    // defaulted color when loading
  bool panelEnabled ;  // tell if panel is enabled or not
  class strip ;          // reference to object created by adafruit constructor
};

The idea is to use as much as 4 gpio to control 4 different strip of panel or strip of led and use the methods for each object for each strip in use.
So far i'm unable to store and use the object of each Adafruit methods, since the initialisation method do not initialise the 4 element of an array that contains 4 structure each referencing a different object.
Here is how i define the initialisation of those array.




  // define the number of panels that we use
  int numberOfPanels = 2;

const int GPIO1=2 ;
const int GPIO2=4 ;
const int GPIO3=5 ;
const int GPIO4=16 ;
 // only serve as an example here
// Create 4 strip lights independently for each gpio port
  Adafruit_NeoPixel strip0 = Adafruit_NeoPixel(256,GPIO1, NEO_GRB + NEO_KHZ800);
  Adafruit_NeoPixel strip1 = Adafruit_NeoPixel(256,GPIO2, NEO_GRB + NEO_KHZ800);
  Adafruit_NeoPixel strip2 = Adafruit_NeoPixel(256,GPIO3, NEO_GRB + NEO_KHZ800);
  Adafruit_NeoPixel strip3 = Adafruit_NeoPixel(256,GPIO4, NEO_GRB + NEO_KHZ800);

    struct ledPanels numPanels[]= {
    {GPIO1,30,false,strip0},
    {GPIO2,30,false,strip1},
    {GPIO3,30,false,strip2},
    {GPIO4,30,false,strip3}
  };

  // store the object reference to the array of pads
  numPanels[0].strip = strip0 ; numPanels[1].strip = strip1 ; numPanels[2].strip = strip2; numPanels[3].strip = strip3 ;
  // define the default color of each panel
  numPanels[0].defcolor = numPanels[0].strip.Color(RED,NONE,NONE) ;
  numPanels[1].defcolor = numPanels[1].strip.Color(NONE,GREEN,NONE) ;
  numPanels[2].defcolor = numPanels[2].strip.Color(NONE,NONE,BLUE) ;
  numPanels[3].defcolor = numPanels[3].strip.Color(MIDDLE,MIDDLE,MIDDLE) ;


So basicly what happend id when i try to access numPanels[x].defcolor or other properties of the structure, the compiler return an error like
error: cannot convert 'Adafruit_NeoPixel' to 'bool' in initialization
63 | {GPIO1,30,false,strip0},

I think thatif i can resolve the problem i will be good for the rest of the project, what i don't understand is why i can't store the values in numPads[x] as it always return an error that numPads did not define a type. I try many different syntax and position inside the code to try to resolve this, i went on different sites showing how i should declare the array, but nowhere i found an example that work so the numPads[x] is defined and can be used to change it's properties inside the struct variables, it's like the numPads[x] is never created and can not be accessed.
So if anyone have an idea of how i should declare, initialise and use the methods of each different strips created, that wold be very helpfull.
NOTE: I am a long time programmer and i never used C++ syntax, i understand the programming and methodologies of the language but one thing i'm having a lot of difficulties id the syntax of the compiler in Adruino or c++ with the thing as reference by pointers or address of the variable in memory.
So please help me Thanks to you all.

Post your complete code.

may be use FastLED instead ?

(or use a pointer in the structure and create the instance in the setup)

Or a C++ Reference:

#include <Adafruit_NeoPixel.h>

const int GPIO1 = 2 ;
const int GPIO2 = 4 ;
const int GPIO3 = 5 ;
const int GPIO4 = 16 ;

struct ledPanels {
  int GPIONO ;         // hold the pinNumber of each GPIO Used
  int NUMLEDS ;     // Number of leds per panel or strip
  long defColor ;    // defaulted color when loading
  bool panelEnabled ;  // tell if panel is enabled or not
  Adafruit_NeoPixel &strip ;          // reference to object created by adafruit constructor
};

Adafruit_NeoPixel strip0 = Adafruit_NeoPixel(256, GPIO1, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip1 = Adafruit_NeoPixel(256, GPIO2, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip2 = Adafruit_NeoPixel(256, GPIO3, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip3 = Adafruit_NeoPixel(256, GPIO4, NEO_GRB + NEO_KHZ800);

struct ledPanels numPanels[] = {
  {GPIO1, 30, 0, false, strip0},
  {GPIO2, 30, 0, false, strip1},
  {GPIO3, 30, 0, false, strip2},
  {GPIO4, 30, 0, false, strip3}
};

void setup() {}

void loop() {}

his challenge is that he needs the GPIONO and NUMLEDS that are also defined in the struct to call the Adafruit_NeoPixel constructor.

Adafruit_NeoPixel strip(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

➜ you need to repeat the data that's in the struct to create the strip (256 was not what it's supposed to be), so it's not nice

struct ledPanels {
  int GPIONO ;         // hold the pinNumber of each GPIO Used
  int NUMLEDS ;     // Number of leds per panel or strip
  long defColor ;    // defaulted color when loading
  bool panelEnabled ;  // tell if panel is enabled or not
  Adafruit_NeoPixel * strip ;          // pointer  to object created by adafruit constructor
};


ledPanels panels[] = {
  {2,  30, 0, false, nullptr},
  {4,  30, 0, false, nullptr},
  {5,  30, 0, false, nullptr},
  {16, 30, 0, false, nullptr}
};

then in the setup you iterate over the panels entries and create dynamically the strip, reusing the GPIOs and number of leds from that entry

(or create constructor)

1 Like

Ahhhhh .... then I'd do it all in one shot:

#include <Adafruit_NeoPixel.h>

const int GPIO1 = 2 ;
const int GPIO2 = 4 ;
const int GPIO3 = 5 ;
const int GPIO4 = 16 ;

struct LedPanels {
  const uint8_t gpioNum ;         // hold the pinNumber of each GPIO Used
  const size_t numLeds ;     // Number of leds per panel or strip
  uint32_t defColor ;    // defaulted color when loading
  bool panelEnabled ;  // tell if panel is enabled or not
  Adafruit_NeoPixel strip ;          // reference to object created by adafruit constructor

  LedPanels(uint8_t pin, size_t num, uint32_t dColor, bool enabled) :
    gpioNum(pin), numLeds(num), defColor(dColor), panelEnabled(enabled), strip(numLeds, gpioNum, NEO_GRB + NEO_KHZ800) {
  }
};

LedPanels panels[] = {
  {GPIO1, 30, 0, false},
  {GPIO2, 30, 0, false},
  {GPIO3, 30, 0, false},
  {GPIO4, 30, 0, false}
};

void setup() {}

void loop() {}

yeah exactly my point

an example:

#include <Adafruit_NeoPixel.h>

class ledPanel {
    const byte gpio ;                        // hold the pinNumber of each GPIO Used
    const size_t numLeds ;                   // Number of leds per panel or strip
    uint32_t defColor ;                      // defaulted color when loading
    bool panelEnabled ;                      // tell if panel is enabled or not
    Adafruit_NeoPixel strip ;

  public:
    ledPanel(const byte pin, const size_t count, uint32_t col, bool en = true)
      : gpio(pin), numLeds(count), defColor(col), panelEnabled(en), strip(Adafruit_NeoPixel(numLeds, gpio, NEO_GRB + NEO_KHZ800))
    {}

    void begin() {
      strip.begin();
      strip.clear();
      if (panelEnabled) {
        for (size_t i = 0; i < numLeds; i++) {
          strip.setPixelColor(i, defColor);
          strip.show();
          delay(50);
        }
      }
    }
};


ledPanel panels[] = {
  {2,  5, 0xFF0000},    // pin 2, 5 pixels, red
  {4,  10, 0x00FF00},   // pin 4, 10 pixels, green
  {5,  15, 0x0000FF},   // pin 5, 15 pixels, blue
};


void setup() {
  Serial.begin(115200);
  for (auto& p : panels) p.begin();
}

void loop() {}

That is nice, but the reason i use an array [0]-[3] is that in the effects i will use this array to call some functions for each separate strip ex: numPads[0].strip.setPixelColor(numPads[0].strip.Color(128,255,40)) ;
or i can just call a function that use the index of the array ex:colorSwipe(int index,uint32_t color, int wait) so this will be.

colorSwipe(0,myColor,myWaitTime)
and in the function i will use something like this...
  numPads[index].strip.setPixelColor(myColor)
  delay(wait) ;

The index could be from a random number 0-3 that will be pass to the effect and use the right panel to display the effect.

So that's why i need the array and strip object contained in that array to affect only the panel concerned.

BTW: i use 16x16 led panels with vertical orientation in a layout of a 3 dimensional cube that count 5 surface including the top that will be inverted by hanging on the ceeling to display the top as the bottom panel. I already created a cude with 5 panels but they are setup as one big panel of 1280leds, it is nice but not the stuff that i want to display.

So from the code that you setup the strip in the structure will be referencing the object of each adafruit object independently, cause if that is the case then it will be nice.

One more thing can i define the adafruit constructor in the structure itself or i have to externaly define it.
All the parameters that is used for the adafruit constructor should be defined before the call to the constructor, ex:
Adafruit_NeoPixel strip0 = Adafruit_NeoPixel(numPads[0].NUMLEDS, numPads[0].GPIONO, NEO_GRB + NEO_KHZ800);

So i need to initialise the numpads[] before calling the adafruit constructor

struct ledPanels {
  int GPIONO ;         // hold the pinNumber of each GPIO Used
  int NUMLEDS ;     // Number of leds per panel or strip
  long defColor ;    // defaulted color when loading
  bool panelEnabled ;  // tell if panel is enabled or not
  Adafruit_NeoPixel &strip ;          // reference to object created by adafruit constructor
};
const int GPIO1=2 ;
const int GPIO2=4 ;
const int GPIO3=5 ;
const int GPIO4=16 ;

struct ledPanels numPanels[] = {
  {GPIO1, 30, 0, false, strip0},
  {GPIO2, 30, 0, false, strip1},
  {GPIO3, 30, 0, false, strip2},
  {GPIO4, 30, 0, false, strip3}
};

  Adafruit_NeoPixel strip0 = Adafruit_NeoPixel(numPads[0].NUMLEDS,numPads[0].GPIONO, NEO_GRB + NEO_KHZ800);

  Adafruit_NeoPixel strip0 = Adafruit_NeoPixel(numPads[1].NUMLEDS,numPads[1].GPIONO, NEO_GRB + NEO_KHZ800);

  Adafruit_NeoPixel strip0 = Adafruit_NeoPixel(numPads[2].NUMLEDS,numPads[3].GPIONO, NEO_GRB + NEO_KHZ800);

  Adafruit_NeoPixel strip0 = Adafruit_NeoPixel(numPads[3].NUMLEDS,numPads[3].GPIONO, NEO_GRB + NEO_KHZ800);

/* and can i do that */
numPads[0].strip = strip0 ;
numPads[1].strip = strip1 ;
numPads[2].strip = strip2 ;
numPads[3].strip = strip3 ;

So if you know that the compiler will not bug me with bunch of illegal syntax doind this then i think i will be in business to complete my code. It has been very much frustrated trying to accomplish this in c++ as i jnow a few more languages that this will not be an issue at all.

Thanks for the reply, i will try a few things if they works

My code example used an array just like you want.

That's wright i need to define the number of leds for each panels and the GPIO number for that panel before calling the adafruit constructor, so it means that numPads[] must be created before even calling the constructor, but after calling the constructor i need to store the strip object of each segment or panel that i define before assigning the strip object to the variable in the structure of each array concerned.

All the functions that will come in the loop section will be called using the values strored in the 4 elements of the array numPads[], so each strip has it's own functions and status stored in each object.

Here is what i want to try to store and retreive the values in numPads[x].

/* Define the numpads array before calling the constructor
   and later store each object in each array element and each strip
  for each element that represent a panel
*/

  ledPanels numPanels[]= {
    {GPIO1,30,false,NULL},
    {GPIO2,30,false,NULL},
    {GPIO3,30,false,NULL},
    {GPIO4,30,false,NULL}
  };


// Create 4 strip lights independently for each gpio port
  Adafruit_NeoPixel strip0 = Adafruit_NeoPixel(**numPanels[0].NUMLEDS**,**numPanels[0].GPIONO**, NEO_GRB + NEO_KHZ800);
  Adafruit_NeoPixel strip1 = Adafruit_NeoPixel(numPanels[1].NUMLEDS,numPanels[1].GPIONO, NEO_GRB + NEO_KHZ800);
  Adafruit_NeoPixel strip2 = Adafruit_NeoPixel(numPanels[2].NUMLEDS,numPanels[2].GPIONO, NEO_GRB + NEO_KHZ800);
  Adafruit_NeoPixel strip3 = Adafruit_NeoPixel(numPanels[3].NUMLEDS,numPanels[3].GPIONO, NEO_GRB + NEO_KHZ800);
 // each element has it's own adafruit object

  numPanels[0].strip = strip0 ;
  numPanels[1].strip = strip1 ;
  numPanels[2].strip = strip2 ;
  numPanels[3].strip = strip3 ;
  

There could be up to 5 panels depending of what i will decide later that will represent a 3D cube inverted with 4 sides and a top panel that will be representing the bottom panel that is inverted for viewing.

If there is a way that i can do that cause every time i try to compile the compiler complains
error: 'numPanels' does not name a type
65 | numPanels[3].strip = strip3 ;

So if you know a way to do this without the compiler complaining and acheive what i want a do please let me know or show me a way that i can acheive this without to complicated code.

Thanks all

You're not making an sense and I can't tell what you're really trying to do because you're just posting snippets. As I requested previously, please post a small but complete code showing what you want to do.

Did you understand the code that @J-M-L and I posted? How are they not doing exactly what you want?

WEll sorry but for now it is all the code i have i've has not pass this part yet cause i can't do nothing until this part compile.

LIke i said, i want to have 4 or 5 panels that i will mount as a cube front,read,left and right side as well as one top, each panel have 256 leds each, and each must be controled by a separate GPIO, so that i can address each panel separately and light up the leds for each panel independently using code that use the strip object of each element in the array separately, so when i want to turn on pixeld on panel1 i will use numPads[1].strip.setPixelColor(color) and if i want to setup leds in panel 4 i will use the strip in numPads[3].strip.setPixelColor(color) etc.. ect..

So i hope that you understand what i want to acheive with thsi way of storing values into array.

Thanks..

The codes @J-M-L and I provided do exactly that. Did you really look at them?

By the way, you keep talking about the array 'numPads'. But that array is not defined in any of the code you posted. It just used. And none of the code you posted even has as setup() or loop() function. So obviously such code won't compile.

The only array you actually define in your incomplete code is 'numPanels'.

BTW, @J-M-L and I both managed to post complete codes with variable definitions, setup(), loop(0), etc. Please do the same when you post again.

In my code the strip probably needs to be public so that it could be accessed directly

In a struct members are public by default

But it certainly meets the requirements that @jano161 stated (at least as I understand them).

So, I don't understand the insistence that it doesn't?

If OP tried to do this

with my code then he got stuck because of the private default. It’s just a matter of making the strip member public like this

Then with the definition

ledPanel panels[] = {
  {2,  5, 0xFF0000},    // pin 2, 5 pixels, red
  {4,  10, 0x00FF00},   // pin 4, 10 pixels, green
  {5,  15, 0x0000FF},   // pin 5, 15 pixels, blue
};

OP can have indeed direct access

panels[0].strip.setPixelColor(color);

Just for variety, a different way:

#include <Adafruit_NeoPixel.h>

class LedPanel : public Adafruit_NeoPixel {
  public:
    const uint8_t gpio;
    const size_t numLeds;
    uint32_t defColor;
    bool panelEnabled;

    LedPanel(uint8_t pin, size_t count, uint32_t col, bool en = true)
      : Adafruit_NeoPixel(count, pin, NEO_GRB + NEO_KHZ800), gpio(pin), numLeds(count), defColor(col),  panelEnabled(en)
    {}

    void begin() {
      Adafruit_NeoPixel::begin();
      clear();
      if (panelEnabled) {
        fill(defColor);
      }
      show();
      delay(50);
    }
};

LedPanel panels[] = {
  {2,  5, 0xFF0000},    // pin 2, 5 pixels, red
  {4,  10, 0x00FF00},   // pin 4, 10 pixels, green
  {5,  15, 0x0000FF},   // pin 5, 15 pixels, blue
};

void setup() {
  Serial.begin(115200);
  for (auto &p : panels) p.begin();
}

void loop() {
}

indeed - inheritance works to (probably the way to go)

Nice piece of code using class, but since i'm not very familiar with the syntax of C++ in Adruino, let me recap if i understand correctly.
The class ledPanel contains a section that i realy don't understand..

LedPanel(uint8_t pin, size_t count, uint32_t col, bool en = true)
      : Adafruit_NeoPixel(count, pin, NEO_GRB + NEO_KHZ800), gpio(pin), numLeds(count), defColor(col),  panelEnabled(en)
    {}

and you define a new begin() function to be called in the setup() to define and initialize the class and that is typical to the class object itself, so instead of calling Panels[x].strip.begin() you iterate through the array for each element and call the class function begin() for each class defined in the array panels[].
That's nice but my goal is to use the strip in the struct or class to be accessed by an index of the panels[] array like something like,
panels[0].strip.setPixelcolor(i,color) and maybe inside the function that will use another strip inside the same function like,
panels[3].strip.setPixelcolot(i,color)

I know how the class work cause i use class in almost all the language and different projects that i work on, either with Visual Studio, Javascript,Java, and other type of language that use class.
But like i said i don't know the syntax in C++ to create and access class in that language.

With the class defenition that you provide, can i access the class stored in panels[] by using an index or some other method to access it, here i'm in the dark, cause i don't know how to access class inside and array like that.
So if you can unlite me on how to access each class and methods contains in Adafruit for each different elements in the panels array, i'm shure that as soon as i understand the way to initialize, and access each array element containing the class and method of each strip i will certainly be able to do my stuff.
The complete code is not define yet cause i can pass the simple initialisation process so when that compile correctly i will work on my code to do the 3D effects on these panels.
Thanks for your time and comprehention, i'm not a newbie in programming, but i'm am a newbie in C++ since i never touch the c++ language.

Thanks.