using an array of array names

I am trying to condense a program I have running. Right now I use call a function and pass the name of the array to use as an argument. Here, I have the first two of several such statements:

if (millis() - loopMillis < delaytime)
  {
    display_pattern(pattern3);
  }
  else if ((millis() - loopMillis) >= 5010 && (millis() - loopMillis)  < 10000)
  {
    display_pattern(pattern4);

What I would like to do is use an array of array names like:

displays = {pattern3, pattern4… etc}

and then loop throught the array_name array to pass the name to the display_pattern function.

I have tried this and the error I get is

wave_array_compact:50:19: error: ‘pattern3’ was not declared in this scope
int displays = {pattern3, pattern4, pattern5, pattern6, pattern7,
^~~~~~~~

wave_array_compact:50:28: error: expected primary-expression before ‘]’ token
int displays = {pattern3, pattern4, pattern5, pattern6, pattern7,
^

exit status 1
‘pattern3’ was not declared in this scope

Any suggestions? Here is the full code, I have eliminated several arrays to keep teh code smaller in this post.

// Larson scanner with PWM

#define DEBUG_UART 0
int sensorpin = A0;    // select the input pin for the potentiometer
int sensorvalue = 0;  // variable to store the value coming from the sensor
bool dir = true;
const uint8_t leds[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};  // PWM pins 2 through 13
int totalnoleds = sizeof(leds);
static uint32_t loopMillis = 0;
int delaytime = 5000;

void display_pattern(const int *pattern, size_t rows, size_t cols)
{
  static uint32_t previousMillis = 0;
  const uint16_t myInterval = 50;
  static uint8_t indexI = 0;
  static uint8_t indexJ = 0;
  
  if  (dir == true)
  {
    for (indexI = 0; indexI < cols;  indexI++)
      analogWrite(leds[indexI], pattern[(indexJ * cols + indexI)]);
  }
  else
  {
    for (indexI = 0; indexI < cols;  indexI++)
      analogWrite(leds[ 11 - indexI], pattern[(indexJ * cols + indexI)]);  //  reversed
  }

#if DEBUG_UART
  //Serial.println(indexI);
  //Serial.println(indexJ * cols + indexI);
  Serial.println(dir);
  delay(10);
#endif

  if (millis() - previousMillis >= analogRead(sensorpin) / 5)
  {
    if ((indexJ * cols + indexI) < rows * cols)
    {
      indexJ++;
    }
    else
    {
      indexJ = 0;
    }
    previousMillis = millis();
  }
}
int displays[] = {pattern3[][], pattern4[][]};
  
  int pattern3[6][12] = {
  {0, 23, 105, 255, 105, 23, 0, 23, 105, 255, 105, 23},
  {23, 0, 23, 105, 255, 105, 23, 0, 23, 105, 255, 105},
  {105, 23, 0, 23, 105, 255, 105, 23, 0, 23, 105, 255},
  {255, 105, 23, 0, 23, 105, 255, 105, 23, 0, 23, 105},
  {105, 255, 105, 23, 0, 23, 105, 255, 105, 23, 0, 23},
  {23, 105, 255, 105, 23, 0, 23, 105, 255, 105, 23, 0},
};

int pattern4[8][12] = {
  {0, 12, 55, 135, 255, 135, 55, 12, 0, 12, 55, 135},
  {12, 0, 12, 55, 135, 255, 135, 55, 12, 0, 12, 55},
  {55, 12, 0, 12, 55, 135, 255, 135, 55, 12, 0, 12},
  {135, 55, 12, 0, 12, 55, 135, 255, 135, 55, 12, 0},
  {255, 135, 55, 12, 0, 12, 55, 135, 255, 135, 55, 12},
  {135, 255, 135, 55, 12, 0, 12, 55, 135, 255, 135, 55},
  {55, 135, 255, 135, 55, 12, 0, 12, 55, 135, 255, 135},
  {12, 55, 135, 255, 135, 55, 12, 0, 12, 55, 135, 255},
};


void setup()
{
  for (uint8_t i = 0; i < totalnoleds; i++)
  {
    pinMode(leds[i], OUTPUT);
  }
}

template <size_t rows, size_t cols> void display_pattern(const int (&pattern)[rows][cols])
{
  display_pattern(&pattern[0][0], rows, cols);
}

void loop()
{
  // read the value from the sensor:
  sensorvalue = analogRead(sensorpin);

  if (millis() - loopMillis < delaytime)
  {
    display_pattern(pattern3);
  }
  else if ((millis() - loopMillis) >= 5010 && (millis() - loopMillis)  < 10000)
  {
    display_pattern(pattern4);
  }
  
  else if (millis() - loopMillis > 10010)
  {
    loopMillis = millis();
    dir = !dir;
  }
}

For one thing, you can't use a variable before you have declared it. That's what the error is telling you. After that, you have other errors to fix. Please post error messages inside code tags.

rcayot:
What I would like to do is use an array of array names like:

I suspect what you have in mind won't work because the names of variables don't exist when the program is running. The ompiler converts names to addresses in memory.

Maybe you need an array of pointers - but that may be complicated if you are new to Arduino programming.

A simpler approach which may be suitable is to have a series of variables that index into an array - something like this

byte name0 = 0; // obviously use more a more meaningful name
byte name1 = 1;
byte name2 = 2;

int myArray[] = {20, 31, 42};

Then you can refer to an array element like this

Serial.println(myArray[name1]);

...R

You need to supply full code so we can see variable declarations and function signatures.

full code is posted at the end.

Original code references the array and works fine, the array of arrays does not.

[[code]
// Larson scanner with PWM

#define DEBUG_UART 0
int sensorpin = A0;    // select the input pin for the potentiometer
int sensorvalue = 0;  // variable to store the value coming from the sensor
bool dir = true;
const uint8_t leds[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};  // PWM pins 2 through 13
int totalnoleds = sizeof(leds);
static uint32_t loopMillis = 0;
int delaytime = 5000;

void display_pattern(const int *pattern, size_t rows, size_t cols)
{
  static uint32_t previousMillis = 0;
  const uint16_t myInterval = 50;
  static uint8_t indexI = 0;
  static uint8_t indexJ = 0;
  
  if  (dir == true)
  {
    for (indexI = 0; indexI < cols;  indexI++)
      analogWrite(leds[indexI], pattern[(indexJ * cols + indexI)]);
  }
  else
  {
    for (indexI = 0; indexI < cols;  indexI++)
      analogWrite(leds[ 11 - indexI], pattern[(indexJ * cols + indexI)]);  //  reversed
  }

#if DEBUG_UART
  //Serial.println(indexI);
  //Serial.println(indexJ * cols + indexI);
  Serial.println(dir);
  delay(10);
#endif

  if (millis() - previousMillis >= analogRead(sensorpin) / 5)
  {
    if ((indexJ * cols + indexI) < rows * cols)
    {
      indexJ++;
    }
    else
    {
      indexJ = 0;
    }
    previousMillis = millis();
  }
}

  
  int pattern3[6][12] = {
  {0, 23, 105, 255, 105, 23, 0, 23, 105, 255, 105, 23},
  {23, 0, 23, 105, 255, 105, 23, 0, 23, 105, 255, 105},
  {105, 23, 0, 23, 105, 255, 105, 23, 0, 23, 105, 255},
  {255, 105, 23, 0, 23, 105, 255, 105, 23, 0, 23, 105},
  {105, 255, 105, 23, 0, 23, 105, 255, 105, 23, 0, 23},
  {23, 105, 255, 105, 23, 0, 23, 105, 255, 105, 23, 0},
};

int pattern4[8][12] = {
  {0, 12, 55, 135, 255, 135, 55, 12, 0, 12, 55, 135},
  {12, 0, 12, 55, 135, 255, 135, 55, 12, 0, 12, 55},
  {55, 12, 0, 12, 55, 135, 255, 135, 55, 12, 0, 12},
  {135, 55, 12, 0, 12, 55, 135, 255, 135, 55, 12, 0},
  {255, 135, 55, 12, 0, 12, 55, 135, 255, 135, 55, 12},
  {135, 255, 135, 55, 12, 0, 12, 55, 135, 255, 135, 55},
  {55, 135, 255, 135, 55, 12, 0, 12, 55, 135, 255, 135},
  {12, 55, 135, 255, 135, 55, 12, 0, 12, 55, 135, 255},
};

const int displays[] = {pattern3[6][12], pattern4[8][12]};

void setup()
{
  for (uint8_t i = 0; i < totalnoleds; i++)
  {
    pinMode(leds[i], OUTPUT);
  }
}

template <size_t rows, size_t cols> void display_pattern(const int (&pattern)[rows][cols])
{
  display_pattern(&pattern[0][0], rows, cols);
}

void loop()
{
  // read the value from the sensor:
  sensorvalue = analogRead(sensorpin);

  if (millis() - loopMillis < delaytime)
  {
    display_pattern(pattern3);
  }
  else if ((millis() - loopMillis) >= 5010 && (millis() - loopMillis)  < 10000)
  {
    display_pattern(pattern4);
  }
  
  else if (millis() - loopMillis > 10010)
  {
    loopMillis = millis();
    dir = !dir;
  }
}

/code]

so,

I want to replace:

display_pattern(pattern4);

say with a reference to an object I can iterate through, so for example when I have 10 arrays, I can just use a for loop to get throught them all, instead of repeated calls.

Roger

It will be difficult because your pattern arrays are different sizes, thus making them different data types. Using templates hides that from you.

I feared that, as I had to ask for assistance passing the array to the function to include the rows and columns.

on to something else I guess. This was only to condense teh code, but since it only uses about 2% of ram I do not need to worry about it except for an easier way to edit and follow the code.

Thanks,

Roger

You could do something like this:

struct PatternStruct {
  int *ptr;
  uint8_t rows;
  uint8_t cols;
};

void display_pattern(PatternStruct &patt);

#define MAKE_STRUCT(s) {&s[0][0], sizeof(s) / sizeof(s[0]), sizeof(s[0]) / sizeof(s[0][0])}

int pattern3[6][12] = {
  {0, 23, 105, 255, 105, 23, 0, 23, 105, 255, 105, 23},
  {23, 0, 23, 105, 255, 105, 23, 0, 23, 105, 255, 105},
  {105, 23, 0, 23, 105, 255, 105, 23, 0, 23, 105, 255},
  {255, 105, 23, 0, 23, 105, 255, 105, 23, 0, 23, 105},
  {105, 255, 105, 23, 0, 23, 105, 255, 105, 23, 0, 23},
  {23, 105, 255, 105, 23, 0, 23, 105, 255, 105, 23, 0},
};

int pattern4[8][12] = {
  {0, 12, 55, 135, 255, 135, 55, 12, 0, 12, 55, 135},
  {12, 0, 12, 55, 135, 255, 135, 55, 12, 0, 12, 55},
  {55, 12, 0, 12, 55, 135, 255, 135, 55, 12, 0, 12},
  {135, 55, 12, 0, 12, 55, 135, 255, 135, 55, 12, 0},
  {255, 135, 55, 12, 0, 12, 55, 135, 255, 135, 55, 12},
  {135, 255, 135, 55, 12, 0, 12, 55, 135, 255, 135, 55},
  {55, 135, 255, 135, 55, 12, 0, 12, 55, 135, 255, 135},
  {12, 55, 135, 255, 135, 55, 12, 0, 12, 55, 135, 255},
};

PatternStruct patterns[] = {MAKE_STRUCT(pattern3), MAKE_STRUCT(pattern4)};
const uint8_t numPatterns = sizeof(patterns) / sizeof(patterns[0]);

void setup() {
  Serial.begin(115200);
  delay(1000);

  for (uint8_t i = 0; i < numPatterns; i++) {
    display_pattern(patterns[i]);
    Serial.println();
    Serial.println();
    Serial.println();
  }
}

void loop() {
}

void display_pattern(PatternStruct &patt) {
  uint16_t index;
  int *p = patt.ptr;
  for (uint8_t i = 0; i < patt.rows; i++) {
    for (uint8_t j = 0; j < patt.cols; j++) {
      index = i * patt.cols + j;
      Serial.print(p[index]);
      Serial.print(" ");
    }
    Serial.println();
  }
}

Serial Port Output:

0 23 105 255 105 23 0 23 105 255 105 23 
23 0 23 105 255 105 23 0 23 105 255 105 
105 23 0 23 105 255 105 23 0 23 105 255 
255 105 23 0 23 105 255 105 23 0 23 105 
105 255 105 23 0 23 105 255 105 23 0 23 
23 105 255 105 23 0 23 105 255 105 23 0 



0 12 55 135 255 135 55 12 0 12 55 135 
12 0 12 55 135 255 135 55 12 0 12 55 
55 12 0 12 55 135 255 135 55 12 0 12 
135 55 12 0 12 55 135 255 135 55 12 0 
255 135 55 12 0 12 55 135 255 135 55 12 
135 255 135 55 12 0 12 55 135 255 135 55 
55 135 255 135 55 12 0 12 55 135 255 135 
12 55 135 255 135 55 12 0 12 55 135 255

Are all your patterns like the two above? They are very repetitive and look like they could be generated by the same algorithm, given different parameters. That might sound complicated, but look how complex the above code is going to get in order to make that work! Plus, an algorithmic version would not take up all that memory space (flash or ram). So how would you describe the purpose or appearance of each pattern, how are their characteristics different from each other?

regarding flash or RAM ... none of your PWM values needs to be an int. A byte is sufficient. But I guess we had this already in your other topics regarding the Larson scanner.

Basically I agree with PaulRB, these kind of patterns could be generated with a function with different parameters ... something like

ledsToBeOnAtTheSameTime

-> one PWM to 255 (the middle position)
--> half of ledsToBeOnAtTheSameTime as trailer, each value calculated 255/ledsToBeOnAtTheSameTime/2*position
--> half of ledsToBeOnAtTheSameTime as header, ...

A different way to approach this would be to create a pattern class that can display itself. Then you can just list a bunch of object calls…

pattern1.display();
pattern2.display();

Or have an array of pattern objects…

for(int i=0;i<NUM_PATTERNS;i++) pattern[i]. display();

Or not…

-jim lee

All,

Thanks for the help.

Yes, some of the arrays can be replicated with algorithms easily. I started wiht algorithms, and was very successful with some, but others were near impossible, at least for me to figure out.

I have a long way to go to understand teh specific data and variable types in C++, I really am trying, but the memory situation and performance situation has not impacted my progeams (yet).

The patterns are just what I think can be interesting to look at. Right now, I have tried to make a wave-like pattern with ever longer ‘wavelength’ easily done with arrays, I cannot even immagine trying with algorithms. I have also used a gamma function to compute the intensities (separately) to improve the visible appearance.

Right now, I am moving over to neo-pixel strips which have their own peculiarities! my fist goal is to try to replicate some of the individual LED type programs/displays I have and then try to incorporate color changes as well. Ultimately, I am going to be helping my artist daughter design wearable and other artistic peices using small microcontrollers like teh gemma and derivatives of the gemma.

Roger