Call various array name as a string or int variable (use of pointers? Scalable?)

Hi everybody :slight_smile:

I am building a 32PWM light sequencer with a pair of daisy chained TLC5940. :grin:

Each sequence of light is written in a constant bi-dimesional array. I use PROGMEM to not waste the RAM. The second dimension represent the intensity of the light and the last number is the delay I will use. The first dimension represent the steps of the sequence. To do the tests, I build simple sequences. Each sequence could be build of a different number of steps (in this case for the moment the 3 are made of 7 steps but after they will be made of 10, 14 or different durations)

With another arduino, I will send I2C commands for global speed and sequence selection. This is the variable called “selection”.
Now what I want to do, in the main loop, is assign the actual readed array sequence to the “selection variable”.

For example:

“selection” will be = int 2. Now in the main loop, I want to get the size and read the data of the S2 array.
“selection” will be = int 1. Now in the main loop, I want to get the size and read the data of the S1 array.

Etc…

And I will program a total of 32 sequences… It is impossible to hardcode this… I want to do it nice and clean.

Basically with S1*[j] and change S1 as I want… I want to use a variable instead of a constant name for the array.*
I tried a couple of things but nothing works… :~
To perform this, I think I need to use pointers? O scalable variables? I looked over the web and I didn’t found anything helpful…
Hope someone can help me… :sweat_smile:
Regards…
(Sorry for my english, I’m french and living to Mexico :slight_smile: )
Here is the source code :
```
*#include “Tlc5940.h”
#include <Wire.h>
#include <avr/pgmspace.h>

int selection = 1;
int SpeedValue = 10;
int arraysize = 0;
const int LEVEL1 = 10                                                                                                                                          ;
const int LEVEL2 = 800;
const int LEVEL3 = 1500;
const int LEVEL4 = 4095;

void setup() {
  Tlc.init();
  Wire.begin(4);               
  Wire.onReceive(receiveEvent);
  Serial.begin(9600);
}

// Pointer test (not working)
//char* BlinkSequence = {“S1”,“S2”,“S3”};

byte S1[7][33] PROGMEM = {
 
  {0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0, 5},
  {1,1,1,1,1,1,1,1,  0,0,0,0,0,0,0,0,  1,1,1,1,1,1,1,1,  0,0,0,0,0,0,0,0, 5},
  {4,4,4,4,4,4,4,4,  0,0,0,0,0,0,0,0,  4,4,4,4,4,4,4,4,  0,0,0,0,0,0,0,0, 50},
  {0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0, 5},
  {4,4,4,4,4,4,4,4,  0,0,0,0,0,0,0,0,  4,4,4,4,4,4,4,4,  0,0,0,0,0,0,0,0, 5},
  {1,1,1,1,1,1,1,1,  0,0,0,0,0,0,0,0,  1,1,1,1,1,1,1,1,  0,0,0,0,0,0,0,0, 50},
  {0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0, 50},

};

byte S2[7][33] PROGMEM = {
 
  {0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0, 5},
  {0,0,0,0,0,0,0,0,  1,1,1,1,1,1,1,1,  0,0,0,0,0,0,0,0,  1,1,1,1,1,1,1,1, 5},
  {0,0,0,0,0,0,0,0,  4,4,4,4,4,4,4,4,  0,0,0,0,0,0,0,0,  4,4,4,4,4,4,4,4, 50},
  {0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0, 5},
  {0,0,0,0,0,0,0,0,  4,4,4,4,4,4,4,4,  0,0,0,0,0,0,0,0,  4,4,4,4,4,4,4,4, 5},
  {0,0,0,0,0,0,0,0,  1,1,1,1,1,1,1,1,  0,0,0,0,0,0,0,0,  1,1,1,1,1,1,1,1, 50},
  {0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0, 50},

};

byte S3[7][33] PROGMEM = {
 
  {4,4,4,4,4,4,4,4,  0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0, 5},
  {0,0,0,0,0,0,0,0,  1,1,1,1,1,1,1,1,  0,0,0,0,0,0,0,0,  1,1,1,1,1,1,1,1, 5},
  {0,0,0,0,0,0,0,0,  4,4,4,4,4,4,4,4,  0,0,0,0,0,0,0,0,  4,4,4,4,4,4,4,4, 20},
  {0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,  4,4,4,4,4,4,4,4,  0,0,0,0,0,0,0,0, 5},
  {0,0,0,0,0,0,0,0,  4,4,4,4,4,4,4,4,  0,0,0,0,0,0,0,0,  4,4,4,4,4,4,4,4, 5},
  {0,0,0,0,0,0,0,0,  1,1,1,1,1,1,1,1,  0,0,0,0,0,0,0,0,  1,1,1,1,1,1,1,1, 20},
  {4,4,4,4,4,4,4,4,  0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0, 20},

};

void loop() {

// Channels de 0 a 31 Maxi 4095
 
    Tlc.clear();
 
 
  // Pointer test (not working)
  //Serial.println(*(BlinkSequence+(selection-1))[1][12]);
 
  arraysize = (sizeof(S1) / (sizeof(byte)*33))-1;
 
  for (int j=0; j <= arraysize; j++){
   
    for (int i=0; i <= 31; i++){
     
      int LEVEL_VALUE = pgm_read_byte_near(&S1[j][i]); 
   
      if (LEVEL_VALUE == 0) {
      Tlc.set(i, 0); 
      }
     
      if (LEVEL_VALUE == 1) {
        Tlc.set(i, LEVEL1); 
      }
     
      if (LEVEL_VALUE == 2) {
        Tlc.set(i, LEVEL2); 
      }
     
      if (LEVEL_VALUE == 3) {
        Tlc.set(i, LEVEL3); 
      }
     
      if (LEVEL_VALUE == 4) {
        Tlc.set(i, LEVEL4); 
      }
 
    }
   
 
   
   
  Tlc.update();

delay(pgm_read_byte_near(&S1[j][32])*SpeedValue);
   
  }
 
 
}

void receiveEvent(int howMany)
{
  while(1 < Wire.available())
  {
  selection = Wire.read();
  // Serial.print(selection);
  }
  SpeedValue = Wire.read();
// Serial.println(SpeedValue);
}*
```

*(BlinkSequence+(selection-1))[1][12]

that is not possible in C to runtime construct variable names that are resolved already during compile time.

You could use a pointer this way (non progmem version

byte S1[3] = { 
  1,2,3 };
byte S2[3] = { 
  2,5,8 };

void setup() 
{
  Serial.begin(115200);
  Serial.println("Start ");

  byte* p = S1;  // pointer p should be set to S1 or S2 depending on the value of selection

  for (int i=0; i<3; i++)
  {
    Serial.println(p[i]);
  }

  p = S2;

  for (int i=0; i<3; i++)
  {
    Serial.println(p[i]);
  }
}

void loop() 
{
}

for 2D progmem its a bit more fiddling, please check if this does what you meant

//
//    FILE: .ino
//  AUTHOR: Rob Tillaart
// VERSION: 0.1.00
// PURPOSE: demo
//    DATE: 
//     URL:
//
// Released to the public domain
//

//byte S1[3] = { 
//  1,2,3 };
//byte S2[3] = { 
//  2,5,8 };

byte S1[7][33] PROGMEM = {

  {
    0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,0, 5    }
  ,
  {
    1,1,1,1,1,1,1,1,  0,0,0,0,0,0,0,0,  1,1,1,1,1,1,1,1,   0,0,0,0,0,0,0,0, 5    }
  ,
  {
    4,4,4,4,4,4,4,4,  0,0,0,0,0,0,0,0,  4,4,4,4,4,4,4,4,   0,0,0,0,0,0,0,0, 50    }
  ,
  {
    0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,0, 5    }
  ,
  {
    4,4,4,4,4,4,4,4,  0,0,0,0,0,0,0,0,  4,4,4,4,4,4,4,4,   0,0,0,0,0,0,0,0, 5    }
  ,
  {
    1,1,1,1,1,1,1,1,  0,0,0,0,0,0,0,0,  1,1,1,1,1,1,1,1,   0,0,0,0,0,0,0,0, 50    }
  ,
  {
    0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,0, 50    }
  ,

};

byte S2[7][33] PROGMEM = {

  {
    0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,0, 5    }
  ,
  {
    0,0,0,0,0,0,0,0,  1,1,1,1,1,1,1,1,  0,0,0,0,0,0,0,0,   1,1,1,1,1,1,1,1, 5    }
  ,
  {
    0,0,0,0,0,0,0,0,  4,4,4,4,4,4,4,4,  0,0,0,0,0,0,0,0,   4,4,4,4,4,4,4,4, 50    }
  ,
  {
    0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,0, 5    }
  ,
  {
    0,0,0,0,0,0,0,0,  4,4,4,4,4,4,4,4,  0,0,0,0,0,0,0,0,   4,4,4,4,4,4,4,4, 5    }
  ,
  {
    0,0,0,0,0,0,0,0,  1,1,1,1,1,1,1,1,  0,0,0,0,0,0,0,0,   1,1,1,1,1,1,1,1, 50    }
  ,
  {
    0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,0, 50    }
  ,

};

byte S3[7][33] PROGMEM = {

  {
    4,4,4,4,4,4,4,4,  0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,0, 5    }
  ,
  {
    0,0,0,0,0,0,0,0,  1,1,1,1,1,1,1,1,  0,0,0,0,0,0,0,0,   1,1,1,1,1,1,1,1, 5    }
  ,
  {
    0,0,0,0,0,0,0,0,  4,4,4,4,4,4,4,4,  0,0,0,0,0,0,0,0,   4,4,4,4,4,4,4,4, 20    }
  ,
  {
    0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,  4,4,4,4,4,4,4,4,   0,0,0,0,0,0,0,0, 5    }
  ,
  {
    0,0,0,0,0,0,0,0,  4,4,4,4,4,4,4,4,  0,0,0,0,0,0,0,0,   4,4,4,4,4,4,4,4, 5    }
  ,
  {
    0,0,0,0,0,0,0,0,  1,1,1,1,1,1,1,1,  0,0,0,0,0,0,0,0,   1,1,1,1,1,1,1,1, 20    }
  ,
  {
    4,4,4,4,4,4,4,4,  0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,0, 20    }
  ,

};



void setup() 
{
  Serial.begin(115200);
  Serial.println("Start ");

  for (int s = 0; s < 7; s++)  // seelection
  {

    byte* p = S1[s];
    for (int i=0; i<33; i++)
    {
      Serial.print(pgm_read_byte_near(&p[i]));
      Serial.print(", ");
    }
    Serial.println();

    p = S2[s];
    for (int i=0; i<33; i++)
    {
      Serial.print(pgm_read_byte_near(&p[i]));
      Serial.print(", ");
    }
    Serial.println();
  }
}

void loop() 
{
}

Hi Rob! Thanks for your answers :slight_smile:

I think this code could help me a lot to understand well how works pointers…

In the second example, you are really near for what I need…

I put you the code of what I need (and I get complation error :drooling_face: Type mismatch…)

//
//    FILE: .ino
//  AUTHOR: Rob Tillaart
// VERSION: 0.1.00
// PURPOSE: demo
//    DATE: 
//     URL:
//
// Released to the public domain
//

int arraysize = 0;

byte S1[7][33] PROGMEM = {

  {
    0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,0, 5    }
  ,
  {
    1,1,1,1,1,1,1,1,  0,0,0,0,0,0,0,0,  1,1,1,1,1,1,1,1,   0,0,0,0,0,0,0,0, 5    }
  ,
  {
    4,4,4,4,4,4,4,4,  0,0,0,0,0,0,0,0,  4,4,4,4,4,4,4,4,   0,0,0,0,0,0,0,0, 50    }
  ,
  {
    0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,0, 5    }
  ,
  {
    4,4,4,4,4,4,4,4,  0,0,0,0,0,0,0,0,  4,4,4,4,4,4,4,4,   0,0,0,0,0,0,0,0, 5    }
  ,
  {
    1,1,1,1,1,1,1,1,  0,0,0,0,0,0,0,0,  1,1,1,1,1,1,1,1,   0,0,0,0,0,0,0,0, 50    }
  ,
  {
    0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,0, 50    }
  ,

};

byte S2[7][33] PROGMEM = {

  {
    0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,0, 5    }
  ,
  {
    0,0,0,0,0,0,0,0,  1,1,1,1,1,1,1,1,  0,0,0,0,0,0,0,0,   1,1,1,1,1,1,1,1, 5    }
  ,
  {
    0,0,0,0,0,0,0,0,  4,4,4,4,4,4,4,4,  0,0,0,0,0,0,0,0,   4,4,4,4,4,4,4,4, 50    }
  ,
  {
    0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,0, 5    }
  ,
  {
    0,0,0,0,0,0,0,0,  4,4,4,4,4,4,4,4,  0,0,0,0,0,0,0,0,   4,4,4,4,4,4,4,4, 5    }
  ,
  {
    0,0,0,0,0,0,0,0,  1,1,1,1,1,1,1,1,  0,0,0,0,0,0,0,0,   1,1,1,1,1,1,1,1, 50    }
  ,
  {
    0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,0, 50    }
  ,

};

byte S3[7][33] PROGMEM = {

  {
    4,4,4,4,4,4,4,4,  0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,0, 5    }
  ,
  {
    0,0,0,0,0,0,0,0,  1,1,1,1,1,1,1,1,  0,0,0,0,0,0,0,0,   1,1,1,1,1,1,1,1, 5    }
  ,
  {
    0,0,0,0,0,0,0,0,  4,4,4,4,4,4,4,4,  0,0,0,0,0,0,0,0,   4,4,4,4,4,4,4,4, 20    }
  ,
  {
    0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,  4,4,4,4,4,4,4,4,   0,0,0,0,0,0,0,0, 5    }
  ,
  {
    0,0,0,0,0,0,0,0,  4,4,4,4,4,4,4,4,  0,0,0,0,0,0,0,0,   4,4,4,4,4,4,4,4, 5    }
  ,
  {
    0,0,0,0,0,0,0,0,  1,1,1,1,1,1,1,1,  0,0,0,0,0,0,0,0,   1,1,1,1,1,1,1,1, 20    }
  ,
  {
    4,4,4,4,4,4,4,4,  0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,0, 20    }
  ,

};

String SEQUENCE_MAME = "S1";


void setup() 
{
  Serial.begin(115200);
  Serial.println("Start ");
  
  arraysize = (sizeof(SEQUENCE_MAME) / (sizeof(byte)*33))-1;

  for (int s = 0; s < 7; s++)  // seelection
  {

    byte* p = SEQUENCE_MAME[s];
    for (int i=0; i<33; i++)
    {
      Serial.print(pgm_read_byte_near(&p[i]));
      Serial.print(", ");
    }
    Serial.println();
    
  }
}

void loop() 
{
}

I put a String variable called SEQUENCE_MAME. What I want to do exactly is when I put S1 in SEQUENCE_MAME is to read the S1 matrix content. When I put S2, read S2, etc… And in the final code, the variable SEQUENCE_MAME will change in function of I2C data reception…

And also I want to be able to do a sizeof(); on the multidimensional PROGMEM array, the sizeof() depending of course of the SEQUENCE_MAME selected array…

Thanks for the help 8)

I put a String variable called SEQUENCE_MAME.

Two problems. First, by convention, all uppercase names are #defined into existence. Second, do not use String.

A String is a class. A string is a NULL terminated array of chars. sizeof() is not the function to get the amount of data in either one.

you need to disconnect the name of the string runtime and compile time

YOu can use the runtime stringname to make a selection though

if ( strcmp(input, "S1") == 0 )   // if equal returns 0
{
  pointer points to S1  array
}
else if (strcmp(input, "S2") == 0) 
{
  pointer points to S2  array
}
else if (strcmp(input, "S3") == 0) 
{
  pointer points to S3 array
}

Do your loops...

strcmp works with char arrays but you could use equivalent String code

robtillaart: you need to disconnect the name of the string runtime and compile time

YOu can use the runtime stringname to make a selection though

if ( strcmp(input, "S1") == 0 )   // if equal returns 0
{
  pointer points to S1  array
}
else if (strcmp(input, "S2") == 0) 
{
  pointer points to S2  array
}
else if (strcmp(input, "S3") == 0) 
{
  pointer points to S3 array
}

Do your loops...




strcmp works with char arrays but you could use equivalent String code

Errrrr I'm totally lost... :drooling_face:

Basically with this code, I have to repeat each function once per once, I can't use only one loop?