Global Variables Set From Switch Statement?

I'm pretty new to coding in Arduino, so bear with me here. I've been floating around the forum and searching every phrasing of my question I can come up with, but I can't find anything that directly answers what I'm looking for.

Basically, I have an LCD screen with 4 buttons, and the screen is going to display custom characters and do miscellaneous things based on button presses. But, what those custom characters are is defined by which "language" the user selects at the beginning of the code (there are 3 different 26-letter alphabets to choose from). So, those custom characters need to be global so that they can be referenced in all the following functions.

I have it set up so that the user presses a button to select the language which outputs a specific case variable which then indicates which set of custom characters needs to be made the "global alphabet". Basically, the user clicks a button, and depending on which button they click, one of the custom alphabets is selected. However, I'm stuck in that I'm seeing everyone saying that no code will run outside of functions in the global space. I don't have the hardware set-up currently to actually test the code (it's more complicated than just an LCD, and I'm waiting on parts to come in), but based on what I'm reading, it seems like having a SWITCH or IF statement outside of the main functions wouldn't work. So, how do declare my alphabet outside of my main functions to make it global while not being able to run a SWITCH/IF outside the functions?

I have a couple dozen functions that are called inside my main loop, so I don't think redefining all 26 characters inside each sub-function is a good idea. That's why I wanted them global. But if what's below won't work, I'm not sure what else to do.

Below is a watered-down version of what I have (watered-down because the code is long and frankly repetitive so I'm cutting it down to make it more palatable).

//sets up lanPinChanged as global variable for language check, sets to unused pin number
int lanPinChanged = 14;

void setup() {
  //Choose Font Language
  byte qma[8] = {B00010, B01010, B01010, B01010, B01010, B01010, B01010, B00010};
  byte qaa[8] = {B10001, B10010, B11100, B00000, B00000, B11100, B10010, B10001};
  byte qla[8] = {B00100, B01010, B10001, B10001, B11111, B10001, B10001, B10001};

  lcd.createChar(0, qma);
  lcd.createChar(1, qaa);
  lcd.createChar(2, qla);

  lcd.setCursor(1, 1);  lcd.write(byte(0));
  lcd.setCursor(5, 1);  lcd.write(byte(1));
  lcd.setCursor(9, 1);  lcd.write(byte(2));

  void loop(){ 
    lanPinChanged = checkPush(0);   //checks which pin is triggered (will loop until something is changed), lanPinChanged will become the associated pin number when a button is pressed
  
    if (lanPinChanged != 14 && lanPinChanged != 7){ 
      //7 is the unused 4th button, so pressing it shouldn't break the loop. Only 4-6 are used as buttons.
      break;
    }
  }
}

switch (languageChoice) {
  case 4: //Language1
    byte mya[8] = {B00010, B01010, B01010, B01010, B01010, B01010, B01010, B00010};
    ...
    byte myz[8] = {B01110, B00100, B00100, B00110, B00100, B01100, B01100, B00100};
    break;
  case 5: //Language2
    byte mya[8] = {B00010, B01010, B01010, B01010, B01010, B01010, B01010, B00010};
    ...
    byte myz[8] = {B01110, B00100, B00100, B00110, B00100, B01100, B01100, B00100};
    break;
  case 6: //Language3
    byte mya[8] = {B00010, B01010, B01010, B01010, B01010, B01010, B01010, B00010};
    ...
    byte myz[8] = {B01110, B00100, B00100, B00110, B00100, B01100, B01100, B00100};
    break;
}

void loop(){
//the rest of the code which references the custom alphabet chosen
}

Welcome,

You can use a global multidimensional array, like this: uJZQqb - Online C++ Compiler & Debugging Tool - Ideone.com

Then have another variable holding the current user language id (between 0 and 2), and use this variable as an index of the first dimension of this multidimensional array
lcd.createChar( 0, languages[user_language][0] ); // create character 'a'

What LCD display are you using? Most of the common ones based on the Hitachi HD44780 driver only support 8 custom characters, not the entire alphabet.

It's a basic 16x2 character LCD. I'm well-aware of the 8 custom character limit. It's part of the reason my code is so obscenely long, I have to redefine those 8 characters for every "display screen". Also had to go through and choose phrases that only used 8 unique letters/characters at a time. It was a blast. Haha. But yes, I'm aware of this and have worked around it.

That link doesn't seem to work for me, it comes up as "forbidden".

But, I think I understand what you're getting at. I think at one point I looked at multi-dimensional arrays, but there was an issue using them with the LCD so I stopped exploring it. But, I think the issue was people trying to use them to bypass the LCD 8 custom character limit, and not what you're saying. I'll give it a try. Hoping I'll have the hardware set-up ready to go in a week or so, then I can actually give it all a try and confirm it works. Thanks!

If you have lots and lots of custom characters but only 8 in use at any given time, you might want to store them in PROGMEM rather than consume SRAM and then read/copy as needed. It depends on what processor you are using and how much memory it has. It might not be worth the effort.

Sorry try again now

I'm using a basic Arduino Nano. Not sure how much memory that affords me relative to what I need.

So basically, I'd have 36 custom characters for each alphabet (all letters plus numbers), and 3 alphabets, plus an additional 8 custom characters for other things. Total of 116 custom characters. The three alphabets are now stored in a multi-dimensional array, and the other 8 are stored outside it. Also, to make the rest of the code more readable, I went ahead and made it so that the "chosen" alphabet is it's own set of 36 global variables (that way I'm just calling an easy-to-reference variable instead of an indexed array). So, in short:

  • 1 global multidimensional array containing 108 characters
  • 8 global additional custom characters
  • 36 global custom characters for the chosen alphabet

This probably... takes up a lot of space? Again, no frame of reference here, so no idea how much of a problem this would actually be. If it looks like it'll be an issue, is there a way to erase the global multidimensional array after the chosen alphabet is put into its global variables? Free up that space again?

Works now! Thanks a lot! I just fixed up my code, so hopefully this works! Will update this thread if it does (or doesn't, haha).

And each custom char take 8 bytes so you are consuming 152 * 8 = 1216 bytes.

A nano only has 2048 bytes of SRAM so you have used more than half already. When you compile your code, the compiler reports how large your sketch it as well as how much global variable space has been allocated.

Depending on what else you are doing, you may be pushing your memory limit... You might have to ditch the "easy-to-reference" alphabet which is a duplication of existing memory.

Been a while, but I finally got around to messing with this code again, and I figured out how to make it work without taking up a ton of memory.

Basically, I first made the "easy to reference" alphabet into global variables with placeholder characters (basically just a bunch of "X"s). Then inside the setup() function, I made the multidimensional array with all 3 languages (3 x 36 x 8 array), making that a local variable instead. Kept the same method of having the user choose the alphabet inside the setup() loop. Then, depending on their choice, a for() loop (still inside the setup() loop) goes through all 8 bytes of each global alphabet character and replaces it with the corresponding letter of the alphabet referenced from the multidimensional array. So basically:

for (int counter = 0; counter <= 7; counter++){
    ma[counter] = {languages[selectedLanguage][0][counter]};
    mb[counter] = {languages[selectedLanguage][1][counter]};
    mc[counter] = {languages[selectedLanguage][2][counter]};
    md[counter] = {languages[selectedLanguage][3][counter]};
    ...
}

That way, I'm not taking up a ton of unnecessary global space because the multidimensional array with all three languages is contained locally within the setup() loop. Seems to work. Thanks to everyone for your help and input!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.