Calling multiple variables at the same "slot?" of an array.

Hello, thanks for looking at my thread. Here's what I'm trying to do:

I want to push a button and have my Leonardo simulate multiple keypresses. This is pretty straightforward with a simple "if" statement.

The complexity arises by adding a selector knob. When the selector knob is in the first position, the button should simulate keypress "A" and "B", but when the selector switch is moved to the second position the button should simulate keypress "X" "Y" and "Z".

Here's what I tried in pseudo-code.

chars* firstSetOfValues = Keyboard.press("A") , Keyboard.press("B"); // No idea what the syntax should look like here, this is just fake code.

chars* secondSetOfValues = Keyboard.press("X") , Keyboard.press("Y") , Keyboard.press("Z") // Once again fake code.



chars* buttonPress [] = { firstSetOfValues , secondSetOfValues }; // The 2 commands for the button depending on the selector knob

int a = 0; // This links the knob position with what the button is supposed to do.
...



if( knob position is in the first position){  // Simplified fake code for the sake of example.
      a = 0;   // knob is in the first position
}
else{
     a = 1;   // knob is in the second position
}


if (the button is pushed){    //simplified for example
    buttonPress[a];      //do all the things found at this location
    Keyboard.releaseAll();  // then stop
}

My intention with this code is to relay what I've been trying to use to get a solution, not to proofread hundreds of lines of code. One of my many problems is that a) I'm clearly an idiot, and b) I have no experience with C++.

I know that I can't assign multiple variables to one global variable, but I want to, because I think I need to. I've been Googling for a day and a half and don't know enough to ask good questions, and not smart enough to understand the answers I find.

I've found some "buzz words" that I've been looking into for solutions. "Multi-dimensional arrays", "Array of objects", "Classes". But I'm really turning up a big goose egg.

Now granted , one solution is just to write a very lengthy if statement, identifying all the commands for all the positions. This becomes time consuming when applied to my real life project which contains 8 switches each with 2 positions, 2 buttons, and a 6 position selector switch.

Thanks again for your time.

-Kirk

You should have a function that you call for each position of the selector switch. In those functions, you should decide what to do based on the switch states. You should sew the buttons back on a shirt.

You could have two arrays of characters - for example

char arrayA[] = "ABCD";
char arrayB[] = "ZYXW";

Then you can use the switch to select which array is used. arrayA[1] will give you 'B' whereas arrayB[1] will give 'Y' (Edit - sorry for having 'Z' in the original version)

You could make the code simpler still by using a 2 dimensional array.

...R

Robin2:
You could have two arrays of characters - for example

char arrayA[] = "ABCD";

char arrayB[] = "ZYXW";




Then you can use the switch to select which array is used. `arrayA[1]` will give you 'B' whereas `arrayB[1]` will give 'Z'

You could make the code simpler still by using a 2 dimensional array.

...R

In this array can I still have more than one variable assigned to a given location? I don't completely understand. My selector switch is working well, but my problem is desiring more than one variable from a single call to an array. Using your example, when I make the call to arrayA[1] I want it to give me more than just 1 variable. It returns "B" but I would like it to return "B" and "C" and "D" all at the same time. Does that make sense?

It's entirely possible that my array is not the best solution of this problem, I'm interested in the 2 dimensional array, I'm just not sure what it looks like and how it's used. Many of the C++ tutorials don't look much like the C++ in arduino to my newbish eyes. Do you know of an example sketch that uses a 2 dimensional array?
Thanks

As I read it, your issue is that for each keypress you want to send one or more characters as if they were typed from the keyboard.

This means that your data structure is an array of pointers to strings like this (untested) code

char *arrayA[] = { "ABC", "DEF", "GHI" };
char *arrayB[] = { "UVW", "XYZ", "RST"};

arrayA[0] is "ABC", arrayB[1] is "XYZ".

You can simplify this as a 2 dimensional array as follows:

char *array[2][] = {{ "ABC", "DEF", "GHI" }, { "UVW", "XYZ", "RST"}};

(only the last index can be left unnumbered for the compiler to work out)

A more efficient solution is to store the strings in PROGMEM, but I would suggest getting it working from RAM first and then covert later.

marco_c:
You can simplify this as a 2 dimensional array as follows:

char *array[2][] = {{ "ABC", "DEF", "GHI" }, { "UVW", "XYZ", "RST"}};

This is quite good. How do I call it later? array[1] for example, would that give me "DEF""XYZ" or does it give me "UVW""XYZ""RST"?

Also can I do this out to a dozen or so commands? Or is the 2 dimensional array limited to just these 2?

PaulS:
You should have a function that you call for each position of the selector switch. In those functions, you should decide what to do based on the switch states. You should sew the buttons back on a shirt.

This sounds fascinating! I was reading a little bit about functions yesterday. How would it work?

How do I call it later? array[1] for example, would that give me "DEF""XYZ" or does it give me "UVW""XYZ""RST"?

You don't 'call' variables, you reference them.

In a multi dimensional array you can safely only reference a single value by its fully qualified indexes. You would never give your home address as just the street - it also includes the number for the house/building and the floor/apartment (like a 3 dimension array). So array[0][1] is "DEF".

[2] can be as big as you like, memory permitting.

I really think you need to read up on the "buzz words" before you continue as you seem to be asking very basic questions that are covered in most introduction tutorials for C++.

You want a struct, or even a class. (a struct is just a class where everything is public). There's a fair bit of code in this reply, but you should make an effort to read it.

class ButtonGroup {
public:
  char *sequenceA;
  char *sequenceB;

  ButtonGroup(char *a, char *b) :
    sequenceA(a), sequenceB(b) {
  }
};


ButtonGroup someButtons[] = {
  ButtonGroup("ABC", "XYZ"),
  ButtonGroup("DEFG", "UVW"),
  ButtonGroup("HI", "45?44th")
};

void setup() {
  // put your setup code here, to run once:

}

void loop() {
  for(int i = 0; i<3; i++)  {
    Serial.println(digitalRead(4) 
      ? someButtons[i].sequenceA 
      : someButtons[i].sequenceB);
  }
}

You can even do things like put the pin numbers inside the button class. This means that the pin assignments are only done once:

class ButtonGroup {
public:
  byte pin;
  char *sequenceA;
  char *sequenceB;

  ButtonGroup(byte pin, char *a, char *b) :
    pin(pin), sequenceA(a), sequenceB(b) {
  }
};


ButtonGroup someButtons[] = {
  ButtonGroup(5, "ABC", "XYZ"),
  ButtonGroup(6, "DEFG", "UVW"),
  ButtonGroup(7, "HI", "45?44th")
};

void setup() {
  for(int i = 0; i<3; i++)  {
    pinMode(someButtons[i].pin, INPUT_PULLUP); 
  }
}

void loop() {
  for(int i = 0; i<3; i++)  {
    Serial.println(digitalRead(someButtons[i].pin) 
      ? someButtons[i].sequenceA 
      : someButtons[i].sequenceB);
  }
}

The cool thing is that when a block of code deals with just the stuff inside a class and nothing outside it, often it makes sense to move that code into the class.

class ButtonGroup {
public:
  const byte pin;
  const char *sequenceA;
  const char *sequenceB;

  ButtonGroup(const byte pin, const char *a, const char *b) :
    pin(pin), sequenceA(a), sequenceB(b) {
  }

  const char *currentSequence() {
    if(digitalRead(pin) == HIGH)
      return sequenceA;
    else
      return sequenceB;
  }
};


ButtonGroup someButtons[] = {
  ButtonGroup(5, "ABC", "XYZ"),
  ButtonGroup(6, "DEFG", "UVW"),
  ButtonGroup(7, "HI", "45?44th")
};

void setup() {
  for(int i = 0; i<3; i++)  {
    pinMode(someButtons[i].pin, INPUT_PULLUP); 
  }
}

void loop() {
  for(int i = 0; i<3; i++)  {
    Serial.println(someButtons[i].currentSequence());
  }
}

See my page on OO programming in arduino for more on using objects.

How refreshingly helpful. Allow me some time to digest this before replying with questions. Thank you very much.

Delta_G:
You mean 'Y' right?

Thanks. And I was trying really hard not to make that mistake :slight_smile:

...R