[Problems] Passing multiple multidimensional arrays as parameter

The code I'm working on is related to a dual color matrix driver using shiftregister. I coded a few sub-routines for updating the screen and reseting it. But I want to make these sub-routines more compatible for futher projects.

/******************************************************************************
 ** assign hardware pins to register pins
 *******************************************************************************/
const int cathodeScreenPins[8] = {
  0,1,2,3,4,5,6,7};
const int greenScreenPins[8]   = {
  15,14,13,12,11,10,9,8};
const int redScreenPins[8]     = {
  16,17,18,19,20,21,22,23};

/******************************************************************************
 ** information
 *******************************************************************************/
// 2 dimensional arrays to store led states
int greenScreen[8][8];
int redScreen[8][8];

void setup(){
  ResetScreen(greenScreen);
  ResetScreen(redScreen);
  UpdateScreen(cathodeScreenPins, greenScreenPins, redScreenPins);
}

void loop(){

}

void UpdateScreen(int cathodePins[][8], int greenPins[][8], int redPins[][8]){
for(int  thisPin = 0; thisPin < 8; thisPin++){
    shifter.setPin(cathodePins[thisPin],HIGH);
    shifter.setPin(greenPins[thisPin],LOW);
    shifter.setPin(redPins[thisPin],LOW);
  }

  for(int thisCathode = 0; thisCathode < 8; thisCathode++){
    for(int thisAnode = 0; thisAnode < 8; thisAnode++){

      boolean greenState = greenScreen[thisCathode][thisAnode];
      boolean redState   = redScreen[thisCathode][thisAnode];

      shifter.setPin(cathodePins[thisCathode],LOW);
      shifter.setPin(greenPins[thisAnode],greenState);
      shifter.setPin(redPins[thisAnode],redState);
    }
    shifter.write();
    shifter.setPin(cathodePins[thisCathode],HIGH);
  }
}

void ResetScreen(int screenToReset[][8]){
  for(int i = 0 ;i < 8; i++){
    for(int ii = 0 ;ii < 8; ii++){
      screenToReset[i][ii] = LOW;
    }
  } 
}

When I compile this code I get the following errors:

tic_tac_toe.ino: In function 'void setup()':
tic_tac_toe:43: error: no matching function for call to 'UpdateScreen(const int [8], const int [8], const int [8])'
tic_tac_toe.ino:19: note: candidates are: void UpdateScreen(int (*)[8], int (*)[8], int (*)[8])
tic_tac_toe.ino:21: note:                 void UpdateScreen(int (*)[8], int (*)[8], int (*)[8], int (*)[8], int (*)[8])
tic_tac_toe.ino: In function 'void UpdateScreen(int (*)[8], int (*)[8], int (*)[8])':
tic_tac_toe:52: error: invalid conversion from 'int*' to 'int'
tic_tac_toe:52: error: initializing argument 1 of 'void Shifter::setPin(int, boolean)'
tic_tac_toe:53: error: invalid conversion from 'int*' to 'int'
tic_tac_toe:53: error: initializing argument 1 of 'void Shifter::setPin(int, boolean)'
tic_tac_toe:54: error: invalid conversion from 'int*' to 'int'
tic_tac_toe:54: error: initializing argument 1 of 'void Shifter::setPin(int, boolean)'
tic_tac_toe:63: error: invalid conversion from 'int*' to 'int'
tic_tac_toe:63: error: initializing argument 1 of 'void Shifter::setPin(int, boolean)'
tic_tac_toe:64: error: invalid conversion from 'int*' to 'int'
tic_tac_toe:64: error: initializing argument 1 of 'void Shifter::setPin(int, boolean)'
tic_tac_toe:65: error: invalid conversion from 'int*' to 'int'
tic_tac_toe:65: error: initializing argument 1 of 'void Shifter::setPin(int, boolean)'
tic_tac_toe:68: error: invalid conversion from 'int*' to 'int'
tic_tac_toe:68: error: initializing argument 1 of 'void Shifter::setPin(int, boolean)'
MatrixControl.ino: In function 'void UpdateScreen(int (*)[8], int (*)[8], int (*)[8], int (*)[8], int (*)[8])':
MatrixControl:126: error: invalid conversion from 'int*' to 'int'
MatrixControl:126: error: initializing argument 1 of 'void Shifter::setPin(int, boolean)'
MatrixControl:127: error: invalid conversion from 'int*' to 'int'
MatrixControl:127: error: initializing argument 1 of 'void Shifter::setPin(int, boolean)'
MatrixControl:128: error: invalid conversion from 'int*' to 'int'
MatrixControl:128: error: initializing argument 1 of 'void Shifter::setPin(int, boolean)'
MatrixControl:137: error: invalid conversion from 'int*' to 'int'
MatrixControl:137: error: initializing argument 1 of 'void Shifter::setPin(int, boolean)'
MatrixControl:138: error: invalid conversion from 'int*' to 'int'
MatrixControl:138: error: initializing argument 1 of 'void Shifter::setPin(int, boolean)'
MatrixControl:139: error: invalid conversion from 'int*' to 'int'
MatrixControl:139: error: initializing argument 1 of 'void Shifter::setPin(int, boolean)'
MatrixControl:142: error: invalid conversion from 'int*' to 'int'
MatrixControl:142: error: initializing argument 1 of 'void Shifter::setPin(int, boolean)'

Full code:

/******************************************************************************
 ** include libraries
 *******************************************************************************/
#include <Shifter.h>

/******************************************************************************
 ** set register parameters
 *******************************************************************************/
#define SER_Pin 4 // 14 SER_IN
#define RCLK_Pin 3 // 12 L_CLOCK
#define SRCLK_Pin 2 // 11 CLOCK
#define randomInput A0

#define NUM_REGISTERS 3 // how many registers are in the chain
//initaize shifter using the Shifter library
Shifter shifter(SER_Pin, RCLK_Pin, SRCLK_Pin, NUM_REGISTERS); 

/******************************************************************************
 ** assign hardware pins to register pins
 *******************************************************************************/
const int cathodeScreenPins[8] = {
  0,1,2,3,4,5,6,7};
const int greenScreenPins[8]   = {
  15,14,13,12,11,10,9,8};
const int redScreenPins[8]     = {
  16,17,18,19,20,21,22,23};

/******************************************************************************
 ** information
 *******************************************************************************/
// 2 dimensional arrays to store led states
int greenScreen[8][8];
int redScreen[8][8];

/******************************************************************************
 ** global variables
 *******************************************************************************/


void setup(){
  ResetScreen(greenScreen);
  ResetScreen(redScreen);
  UpdateScreen(cathodeScreenPins, greenScreenPins, redScreenPins);
}

void loop(){

}

void UpdateScreen(int cathodePins[][8], int greenPins[][8], int redPins[][8]){
  for(int  thisPin = 0; thisPin < 8; thisPin++){
    shifter.setPin(cathodePins[thisPin],HIGH);
    shifter.setPin(greenPins[thisPin],LOW);
    shifter.setPin(redPins[thisPin],LOW);
  }

  for(int thisCathode = 0; thisCathode < 8; thisCathode++){
    for(int thisAnode = 0; thisAnode < 8; thisAnode++){

      boolean greenState = greenScreen[thisCathode][thisAnode];
      boolean redState   = redScreen[thisCathode][thisAnode];

      shifter.setPin(cathodePins[thisCathode],LOW);
      shifter.setPin(greenPins[thisAnode],greenState);
      shifter.setPin(redPins[thisAnode],redState);
    }
    shifter.write();
    shifter.setPin(cathodePins[thisCathode],HIGH);
  }
}

void ResetScreen(int screenToReset[][8]){
  for(int i = 0 ;i < 8; i++){
    for(int ii = 0 ;ii < 8; ii++){
      screenToReset[i][ii] = LOW;
    }
  } 
}

Does anyone have an idea to resolve my problem?

Thanks.

You're telling the compiler to expect three 2d arrays of int, but you're passing three const one dimensional arrays of int.
Try:

void UpdateScreen(const int cathodePins[], const int greenPins[], const int redPins[]){

You will need to do one of two things:

  • Instead of passing a multidimensional array (which you can't really do anyway), you should pass pointers to the top level of the multidimensional array.
  • Just deal with modifying global arrays in your functions and realize that you will have to declare the same global arrays for re-use.

The first option is probably best because:

  • The same function can work on two different arrays in the same sketch.
  • You can cut and paste the function to different sketches and/or work it into a user library.
  • You learn about pointers. (Something I need to get a handle on, myself.)

Ok, I was aware of those two options. Currently, I'm using the second option. But I want to try the first one. Do you have got any example of a sketch which uses that method? If I google it I only can find codes written in c or c++. It would be easier to see a code written in true arduino.

GlennTech:
Ok, I was aware of those two options. Currently, I'm using the second option. But I want to try the first one. Do you have got any example of a sketch which uses that method? If I google it I only can find codes written in c or c++. It would be easier to see a code written in true arduino.

Unfortunately, not I. I understand the concept, and know methods exist, but I haven't done this yet myself. (Thus the "Something I need to get a handle on, myself." comment...) :wink: I've done it in assembler, but not something higher level like C/C++/Wiring.

I'm sure there are others here that can point you to useful reference material.

Edit: Quick grammar fix and added the bit about assembler experience.

As they are declared as global do you actually need to pass the arrays at all ?

UKHeliBob:
As they are declared as global do you actually need to pass the arrays at all ?

Well, the arrays are declared as global. But I want to turn my sub-routines into a library later on. So I need a way to pass the arrays as parameters in those sub routines.

Sembazuru:

GlennTech:
Ok, I was aware of those two options. Currently, I'm using the second option. But I want to try the first one. Do you have got any example of a sketch which uses that method? If I google it I only can find codes written in c or c++. It would be easier to see a code written in true arduino.

Unfortunately, not I. I understand the concept, and know methods exist, but I haven't done this yet myself. (Thus the "Something I need to get a handle on, myself." comment...) :wink: I've done it in assembler, but not something higher level like C/C++/Wiring.

I'm sure there are others here that can point you to useful reference material.

Edit: Quick grammar fix and added the bit about assembler experience.

http://pw1.netcom.com/~tjensen/ptr/ch2x.htm

Stripping out the library, which I don't have, and simplifying, I get:

/******************************************************************************
 ** assign hardware pins to register pins
 *******************************************************************************/
const int cathodeScreenPins[8] = {
  0,1,2,3,4,5,6,7};
const int greenScreenPins[8]   = {
  15,14,13,12,11,10,9,8};
const int redScreenPins[8]     = {
  16,17,18,19,20,21,22,23};

/******************************************************************************
 ** information
 *******************************************************************************/
// 2 dimensional arrays to store led states
int greenScreen[8][8];
int redScreen[8][8];

void setup(){
  ResetScreen(greenScreen);
  ResetScreen(redScreen);
  UpdateScreen(cathodeScreenPins, greenScreenPins, redScreenPins);
}

void loop(){ }

void UpdateScreen(int cathodePins[][8], int greenPins[][8], int redPins[][8]){
  for(int  thisPin = 0; thisPin < 8; thisPin++)
    {
   
    }

}

void ResetScreen(int screenToReset[][8]){
  for(int i = 0 ;i < 8; i++){
    for(int ii = 0 ;ii < 8; ii++){
      screenToReset[i][ii] = LOW;
    }
  } 
}

Which gives:

sketch_may11b.ino: In function 'void setup()':
sketch_may11b:21: error: cannot convert 'const int*' to 'int (*)[8]' for argument '1' to 'void UpdateScreen(int (*)[8], int (*)[8], int (*)[8])'

Changing one line (the function UpdateScreen) and it compiles OK:

/******************************************************************************
 ** assign hardware pins to register pins
 *******************************************************************************/
const int cathodeScreenPins[8] = {
  0,1,2,3,4,5,6,7};
const int greenScreenPins[8]   = {
  15,14,13,12,11,10,9,8};
const int redScreenPins[8]     = {
  16,17,18,19,20,21,22,23};

/******************************************************************************
 ** information
 *******************************************************************************/
// 2 dimensional arrays to store led states
int greenScreen[8][8];
int redScreen[8][8];

void setup(){
  ResetScreen(greenScreen);
  ResetScreen(redScreen);
  UpdateScreen(cathodeScreenPins, greenScreenPins, redScreenPins);
}

void loop(){ }

void UpdateScreen(const int cathodePins[8], const int greenPins[8], const int redPins[8]){
  for(int  thisPin = 0; thisPin < 8; thisPin++)
    {
   
    }

}

void ResetScreen(int screenToReset[][8]){
  for(int i = 0 ;i < 8; i++){
    for(int ii = 0 ;ii < 8; ii++){
      screenToReset[i][ii] = LOW;
    }
  } 
}

GlennTech:
If I google it I only can find codes written in c or c++. It would be easier to see a code written in true arduino.

Arduino uses C++.

Read this before posting a programming question

Point 1.

I can't test your code because I don't have the Shifter library. However, some suggestions:

First, your calls to ResetScreen() can be made more efficient by using the memset() C standard library function:

void ResetScreen(int *screenToReset)
{
memset(screenToReset, 0, 128);
}

The first argument is the base address of the memory block to be initialized. The second is the value to use, and the third is the number of bytes to be initialized to the value. Because arrays are nothing more than blocks of memory divided up into uniform chunks, the array name is the same as the base memory address of that array. Therefore, using the syntax shown here says the ResetScreen() function has been passed a pointer to a block of memory that just happens to be an array of int's. Given what your code does, it doesn't matter if it has rank one, two, or three...all you want to do is zero out the array block. All you need to do is figure out how many bytes to set. A more portable way to code the memset() call is:

memset(screenToReset, LOW, 64 * sizeof(int));

That way, if the size of a int changes at some future date from 2 to 4 bytes, your code won't break.

Because you are now using a pointer as the parameter to the ResetScreen() call, passing in just the array name works fine.

As to understanding pointers, I'm between a rock and a hard place. The Beginning C for Arduino book by Jack Purdum does a great job of explaining pointers...the book has two chapters just on pointers. The rock part is that it's my book, so I'm hardly unbiased.

This might also be helpful in understanding what pointers are all about:

Thank you all for the response. The library is from here: http://bildr.org/2011/08/74hc595-breakout-arduino/.

Thanks for the fix, but I want also to pass the greenScreen and redScreen as parameter in the UpdateScreen().
void UpdateScreen(const int cathodePins[8], const int greenPins[8], const int redPins[8], int greenScreen[][8], int redScreen[][8]){

when compiling I get this error:

Vier_op_een_rij_V2.ino: In function 'void setup()':
Vier_op_een_rij_V2:85: error: cannot convert 'byte (*)[8]' to 'int (*)[8]' for argument '4' to 'void UpdateScreen(const int*, const int*, const int*, int (*)[8], int (*)[8])'
Vier_op_een_rij_V2.ino: In function 'void loop()':
Vier_op_een_rij_V2:93: error: cannot convert 'byte (*)[8]' to 'int (*)[8]' for argument '4' to 'void UpdateScreen(const int*, const int*, const int*, int (*)[8], int (*)[8])'
Animations.ino: In function 'void ShowImage(byte*, byte*, long unsigned int)':
Animations:26: error: cannot convert 'byte (*)[8]' to 'int (*)[8]' for argument '4' to 'void UpdateScreen(const int*, const int*, const int*, int (*)[8], int (*)[8])'
Animations:29: error: cannot convert 'byte (*)[8]' to 'int (*)[8]' for argument '4' to 'void UpdateScreen(const int*, const int*, const int*, int (*)[8], int (*)[8])'
Animations.ino: In function 'void AnimationDrop()':
Animations:43: error: cannot convert 'byte (*)[8]' to 'int (*)[8]' for argument '4' to 'void UpdateScreen(const int*, const int*, const int*, int (*)[8], int (*)[8])'
Animations:54: error: cannot convert 'byte (*)[8]' to 'int (*)[8]' for argument '4' to 'void UpdateScreen(const int*, const int*, const int*, int (*)[8], int (*)[8])'
Controller.ino: In function 'void ButtonCursors()':
Controller:91: error: cannot convert 'byte (*)[8]' to 'int (*)[8]' for argument '4' to 'void UpdateScreen(const int*, const int*, const int*, int (*)[8], int (*)[8])'
Controller:125: error: cannot convert 'byte (*)[8]' to 'int (*)[8]' for argument '4' to 'void UpdateScreen(const int*, const int*, const int*, int (*)[8], int (*)[8])'
Controller.ino: In function 'void SerialCursors()':
Controller:165: error: cannot convert 'byte (*)[8]' to 'int (*)[8]' for argument '4' to 'void UpdateScreen(const int*, const int*, const int*, int (*)[8], int (*)[8])'
Controller:196: error: cannot convert 'byte (*)[8]' to 'int (*)[8]' for argument '4' to 'void UpdateScreen(const int*, const int*, const int*, int (*)[8], int (*)[8])'
GameFunctions.ino: In function 'void GameReset()':
GameFunctions:19: error: cannot convert 'byte (*)[8]' to 'int (*)[8]' for argument '4' to 'void UpdateScreen(const int*, const int*, const int*, int (*)[8], int (*)[8])'
GameFunctions.ino: In function 'void GamePlayerSelect()':
GameFunctions:51: error: cannot convert 'byte (*)[8]' to 'int (*)[8]' for argument '4' to 'void UpdateScreen(const int*, const int*, const int*, int (*)[8], int (*)[8])'
GameFunctions:56: error: cannot convert 'byte (*)[8]' to 'int (*)[8]' for argument '4' to 'void UpdateScreen(const int*, const int*, const int*, int (*)[8], int (*)[8])'
GameFunctions.ino: In function 'void GameWin()':
GameFunctions:182: error: cannot convert 'byte (*)[8]' to 'int (*)[8]' for argument '4' to 'void UpdateScreen(const int*, const int*, const int*, int (*)[8], int (*)[8])'

Here's my full code: Dropbox - Error - Simplify your life

your link seems dead. are the two variables still declared int:

int greenScreen[8][8];
int redScreen[8][8];

or are they declared as char arrays?

char greenScreen[8][8];
char redScreen[8][8];

The technique for dealing with such a plethora of scary errors is to just fix the first one and recompile. You will often find that many of the others disappear. In this case:

 error: cannot convert 'byte (*)[8]' to 'int (*)[8]' for argument '4' to 'void UpdateScreen(const int*, const int*, const int*, int (*)[8], int (*)[8])'

It sounds like pyro_65 has nailed the issue.

pYro_65:
your link seems dead. are the two variables still declared int:

int greenScreen[8][8];

int redScreen[8][8];




or are they declared as char arrays?


char greenScreen[8][8];
char redScreen[8][8];

They are declared as

int greenScreen[8][8];
int redScreen[8][8];

Thanks for all the help.

It works:

/******************************************************************************
 ** include libraries
 *******************************************************************************/
#include <Shifter.h>

/******************************************************************************
 ** set register parameters
 *******************************************************************************/
#define SER_Pin 4 // 14 SER_IN
#define RCLK_Pin 3 // 12 L_CLOCK
#define SRCLK_Pin 2 // 11 CLOCK
#define NUM_REGISTERS 3 // how many registers are in the chain
//initaize shifter using the Shifter library
Shifter shifter(SER_Pin, RCLK_Pin, SRCLK_Pin, NUM_REGISTERS); 

/******************************************************************************
 ** assign hardware pins to register pins
 *******************************************************************************/
const int cathodePins[8] = {
  0,1,2,3,4,5,6,7};
const int greenPins[8]   = {
  15,14,13,12,11,10,9,8};
const int redPins[8]     = {
  16,17,18,19,20,21,22,23};

/******************************************************************************
 ** screen information
 *******************************************************************************/
// 2 dimensional arrays to store led states
int greenScreen[8][8];
int redScreen[8][8];

void setup(){
  ResetScreen(greenScreen);
  ResetScreen(redScreen);
  UpdateScreen(cathodePins, greenPins, redPins, greenScreen, redScreen);
}

void loop(){
  greenScreen[0][0] = HIGH;
  greenScreen[0][7] = HIGH;
  greenScreen[7][0] = HIGH;
  greenScreen[7][7] = HIGH;
  
  UpdateScreen(cathodePins, greenPins, redPins, greenScreen, redScreen);
}

void ResetScreen(int screenToReset[][8]){
  memset(screenToReset, LOW, 64 * sizeof(int));
}

void UpdateScreen(const int cathodePinsToUse[8], const int greenPinsToUse[8], const int redPinsToUse[8], int greenScreenToUse[][8], int redScreenToUse[][8]){
  for(int  thisPin = 0; thisPin < 8; thisPin++){
    shifter.setPin(cathodePinsToUse[thisPin],HIGH);
    shifter.setPin(greenPinsToUse[thisPin],LOW);
    shifter.setPin(redPinsToUse[thisPin],LOW);
  }

  for(int thisCathode = 0; thisCathode < 8; thisCathode++){
    for(int thisAnode = 0; thisAnode < 8; thisAnode++){

      boolean greenState = greenScreen[thisCathode][thisAnode];
      boolean redState   = redScreen[thisCathode][thisAnode];

      shifter.setPin(cathodePinsToUse[thisCathode],LOW);
      shifter.setPin(greenPinsToUse[thisAnode],greenState);
      shifter.setPin(redPinsToUse[thisAnode],redState);
    }
    shifter.write();
    shifter.setPin(cathodePinsToUse[thisCathode],HIGH);
  }
}