0

I have a function in which I change the pinMode on many of my Arduino's pins based on a passed in mode. I first construct an array of bytes specifying each pin to be an input or an output and then I iterate through the array to set all the pins.

void pinout(byte mode) {
  switch(mode) {
    case 0: char pins[13] = {'O','O','I','I','O','I','I','I','I','O','I','I','O'}; break;
    case 1: char pins[13] = {'O','I','I','O','O','I','O','O','I','O','I','O','I'}; break;
  //etc..
  }
  for(byte i = 0; i <= 13; i++) {
    if(pins[i] == 'I') pinMode(i, INPUT);
    else pinMode(i, OUTPUT);
  }
}

However, since the array is defined inside the switch statement, I loose scope of the pins array when I move onto the for loop. I tried defining the pins[] outside of the switch statement, but then I am confused on how to populate it efficiently. These all threw errors when I tried to populate the variable inside the switch statement:

pins[0,1,2,3,...,12,13] = {...};
pins[13] = {...};
pins[] = {...};
pins = {...};

I know I could go through each entry individually, but this could be rather inefficient use of memory and computational power as I add more cases. Any ideas?

2 Answers 2

1

Since your values are all constant you can define them all as constant values and just select between them. The simplest way is to add an extra dimension to your arrays:

const char pins[2][13] = 
    {'O','O','I','I','O','I','I','I','I','O','I','I','O'},
    {'O','I','I','O','O','I','O','O','I','O','I','O','I'}
};

for(byte i = 0; i < 13; i++) {
    if(pins[mode][i] == 'I') pinMode(i, INPUT);
    else pinMode(i, OUTPUT);
}

(Note: An array of size 13 has entries 0-12.)

However, that is very inefficient. Since you only have two states, I and O, and there are only 13 entries, you can store each array as a single 16-bit value:

const uint16_t pins[2] = {
    0b0110111101100,
    0b1010100100110
};

for(byte i = 0; i < 13; i++) {
    if((pins[mode] & (1 << i)) pinMode(i, INPUT);
    else pinMode(i, OUTPUT);
}

(Note: the data is stored backwards - pin 0 is on the right, pin 12 on the left.)

2
  • Just out of curiosity, how does marking a variable as const improve performance and/or memory? Is it similar to making a set-byte buffer array in other languages? Dec 20, 2017 at 19:45
  • On a little 8 bit Arduino it doesn't unless you also start working with PROGMEM. On 32-bit systems though it generally means the array takes no RAM.
    – Majenko
    Dec 20, 2017 at 19:46
0

I know I could go through each entry individually, but this could be rather inefficient use of memory and computational power as I add more cases.

The compiler produces assembly/machine code that takes the same effort to load the array, so it's not that inefficient. The bracket arrangement is just a construct for easier to read code.

3
  • So, are you saying that filling my array like this: char pins[13]; pins[0] = 'I'; pins[1] = 'O'; ... would be similar in memory footprint to this: char pins[13] = {'I', 'O',...};? Dec 20, 2017 at 19:29
  • Pretty much, though @Majenko has suggested a very memory efficient solution, using a bit array (i.e, a single 16-bit value) rather than an array of 12 bytes with only two possible values. Dec 20, 2017 at 19:31
  • @BenjaminBrownlee: char pins[13] = {'I', 'O',...} only works as a global (or static) initialization. It's more efficient than the alternative, as the copying is handled by the __do_copy_data routine of the C run time, which copies the whole program's data section from flash to RAM in one go. Dec 21, 2017 at 8:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.