need help with button box project

my first arduino finally arrived in the mail today and im working on using an arduino leonardo as a racing/flight sim button box with a few momentary and toggle switches. I think i've learned the bare basics on getting the arduino to turn a button press into a keystroke, but i was wondering if it would be possible to have the arduino send a single keystroke when i toggle a switch on, then again when i toggle it off, but not send it continuously when the switch is on. here is the code ive managed to get together so far with the breadboard switches

char backspace = KEY_BACKSPACE;
char space = 0x20;

void setup() {
  pinMode(13, INPUT_PULLUP); //Stage, Space, momentary button
  pinMode(12, INPUT_PULLUP); // Toggle SAS state, t, toggle switch
  pinMode(11, INPUT_PULLUP); // Toggle RCS state, r, toggle switch
  pinMode(10, INPUT_PULLUP); //Gear, g, toggle switch
  pinMode(9, INPUT_PULLUP);  //Abort, Backspace, momentary button
  pinMode(8, INPUT_PULLUP); //Lights, l, toggle switch
  Keyboard.begin();
}

void loop() {
    if (digitalRead(13)==LOW){
        Keyboard.press(space);
        delay(250);
        Keyboard.release(space);
    }
    if (digitalRead(12)==LOW){
        Keyboard.press('t');
        delay(250);
        Keyboard.release('t');
    }
    if (digitalRead(11)==LOW){
        Keyboard.press('r');
        delay(250);
        Keyboard.release('r');
    }
    if (digitalRead(10)==LOW){
        Keyboard.press('g');
        delay(250);
        Keyboard.release('g');
    }
    if (digitalRead(9)==LOW){
        Keyboard.press(backspace);
        delay(250);
        Keyboard.release(backspace);
    }
    if (digitalRead(8)==LOW){
        Keyboard.press('l');
        delay(250);
        Keyboard.release('l');   
    }
}

i was wondering if it would be possible to have the arduino send a single keystroke when i toggle a switch on, then again when i toggle it off, but not send it continuously when the switch is on.

You need to act when the switch BECOMES pressed/not pressed rather than when it IS pressed/not pressed. Have a look at the StateChangeDetection example in the IDE.

UKHeliBob: You need to act when the switch BECOMES pressed/not pressed rather than when it IS pressed/not pressed. Have a look at the StateChangeDetection example in the IDE.

thanks, you've pointed me in the right direction but im having problems with the code, this works fine; i can press the button down and it presses t once, and it only sends 1 keystroke until i let go of the button and it sends another keystroke. it works perfectly:

char backspace = KEY_BACKSPACE;
char space = 0x20;

int buttonState = 0;
int lastButtonState = 0;

void setup(){
  pinMode(13, INPUT_PULLUP); //Stage, Space, momentary button
  pinMode(12, INPUT_PULLUP); // Toggle SAS state, t, toggle switch
  pinMode(11, INPUT_PULLUP); // Toggle RCS state, r, toggle switch
  pinMode(10, INPUT_PULLUP); //Gear, g, toggle switch
  pinMode(9, INPUT_PULLUP);  //Lights, l, toggle switch
  pinMode(8, INPUT_PULLUP); //Abort, Backspace, momentary button
  Keyboard.begin();
}

void loop() {
  if (digitalRead(13) == LOW) {
    Keyboard.press(space);
    delay(250);
    Keyboard.release(space);
  }
  buttonState = digitalRead(12);
  if (buttonState != lastButtonState) {
    if (buttonState == LOW) {
      Keyboard.press('t');
      Keyboard.release('t');
    }
     else {
       Keyboard.press('t');
       Keyboard.release('t');
    }
  lastButtonState = buttonState;
  }
}

however when i try to add another button, im unsure of how to seperate them and it spams tr or rt for a few seconds every time i press either button:

char backspace = KEY_BACKSPACE;
char space = 0x20;

int buttonState = 0;
int lastButtonState = 0;

void setup(){
  pinMode(13, INPUT_PULLUP); //Stage, Space, momentary button
  pinMode(12, INPUT_PULLUP); // Toggle SAS state, t, toggle switch
  pinMode(11, INPUT_PULLUP); // Toggle RCS state, r, toggle switch
  pinMode(10, INPUT_PULLUP); //Gear, g, toggle switch
  pinMode(9, INPUT_PULLUP);  //Lights, l, toggle switch
  pinMode(8, INPUT_PULLUP); //Abort, Backspace, momentary button
  Keyboard.begin();
}

void loop() {
  if (digitalRead(13) == LOW) {
    Keyboard.press(space);
    delay(250);
    Keyboard.release(space);
  }
  buttonState = digitalRead(12);
  if (buttonState != lastButtonState) {
    if (buttonState == LOW) {
      Keyboard.press('t');
      Keyboard.release('t');
    }
     else {
       Keyboard.press('t');
       Keyboard.release('t');
    }
  lastButtonState = buttonState;
  }
  buttonState = digitalRead(11);
  if (buttonState != lastButtonState) {
    if (buttonState == LOW) {
      Keyboard.press('r');
      Keyboard.release('r');
    }
    else {
      Keyboard.press('r');
      Keyboard.release('r');
    }
    lastButtonState = buttonState;
  } 
}

any pointers on how to seperate them or where i messed up?

In your first program I see

buttonState = digitalRead(12);
if (buttonState != lastButtonState)
{
  if (buttonState == LOW) {
    Keyboard.press('t');
    Keyboard.release('t');
  }
  else
  {
    Keyboard.press('t');
    Keyboard.release('t');
  }
}
lastButtonState = buttonState;

If it does not matter whether the button has just been pressed or released, just that it has changed why not

buttonState = digitalRead(12);
if (buttonState != lastButtonState)
{
  Keyboard.press('t');
  Keyboard.release('t');
}
lastButtonState = buttonState;

In the second program the most obvious problem is that you have only one lastButtonState variable but two buttons. Which button does lastButtonState refer to ? You need two lastButtonState varaibles, with different names, of course.

UKHeliBob: In your first program I see

buttonState = digitalRead(12);
if (buttonState != lastButtonState)
{
  if (buttonState == LOW) {
    Keyboard.press('t');
    Keyboard.release('t');
  }
  else
  {
    Keyboard.press('t');
    Keyboard.release('t');
  }
}
lastButtonState = buttonState;

If it does not matter whether the button has just been pressed or released, just that it has changed why not

buttonState = digitalRead(12);
if (buttonState != lastButtonState)
{
  Keyboard.press('t');
  Keyboard.release('t');
}
lastButtonState = buttonState;

In the second program the most obvious problem is that you have only one lastButtonState variable but two buttons. Which button does lastButtonState refer to ? You need two lastButtonState varaibles, with different names, of course.

thanks, this was the first time coding and you were a lot of help with it, i thought you had to define a starting state for the lastButtonState and i also had no clue you could number them, thanks for clearing it all up. here is my final code; do you care to give it a quick glance over?

char backspace = KEY_BACKSPACE;
char space = 0x20;

int buttonState = 0;
int lastButtonState = 0;
int lastButtonState11 = 0;
int lastButtonState10 = 0;
int lastButtonState9 = 0;
int lastButtonState8 = 0;

void setup(){
  pinMode(13, INPUT_PULLUP); //Stage, Space, momentary button
  pinMode(12, INPUT_PULLUP); // Toggle SAS state, t, toggle switch
  pinMode(11, INPUT_PULLUP); // Toggle RCS state, r, toggle switch
  pinMode(10, INPUT_PULLUP); //Gear, g, toggle switch
  pinMode(9, INPUT_PULLUP);  //Lights, l, toggle switch
  pinMode(8, INPUT_PULLUP); //Abort, Backspace, momentary button
  Keyboard.begin();
}

void loop() {
  if (digitalRead(13) == LOW) {
    Keyboard.press(space);
    delay(250);
    Keyboard.release(space);
  }
  buttonState = digitalRead(12);
  if (buttonState != lastButtonState) {
      Keyboard.press('t');
      Keyboard.release('t');
  }
  lastButtonState = buttonState;
  
  buttonState = digitalRead(11);
  if (buttonState != lastButtonState11) {
      Keyboard.press('r');
      Keyboard.release('r');
  }
    lastButtonState11 = buttonState;
    
  buttonState = digitalRead(10);
  if (buttonState != lastButtonState10) {
    Keyboard.press('g');
    Keyboard.release('g');
  }
    lastButtonState10 = buttonState;
  
  buttonState = digitalRead(9);
  if (buttonState != lastButtonState9) {
    Keyboard.press('l');
    Keyboard.release('l');
  }
    lastButtonState9 = buttonState;
    
  buttonState = digitalRead(8);
  if (buttonState != lastButtonState8) {
    Keyboard.press(backspace);
    Keyboard.release(backspace);
  }
    lastButtonState8 = buttonState;
}

It looks OK but would be better if you used byte instead of int where the value will not exceed 255 and const where the variable values will not change. Neither matter in this program but you may need to save space at some time so would be better using best practice now.

Try this program (untested)

const char backspace = KEY_BACKSPACE;
const char space = 0x20;

const byte buttonPins[] = {13, 12, 11, 10, 9, 8};
const byte NUM_BUTTONS = sizeof(buttonPins) / sizeof(buttonPins[0]);
byte prevButtonStates[NUM_BUTTONS];
char buttonChars[] = {space, 't', 'r', 'g', 'l', backspace};
byte buttonState;

void setup()
{
  for (int b = 0; b < NUM_BUTTONS; b++)
  {
    pinMode(buttonPins[b], INPUT_PULLUP);
  }
  Keyboard.begin();
}

void loop()
{
  if (digitalRead(buttonPins[0]) == LOW)
  {
    Keyboard.press(buttonChars[0]);
    delay(250);
    Keyboard.release(buttonChars[0]);
  }

  for (int b = 1; b < NUM_BUTTONS; b++)
  {
    buttonState = digitalRead(buttonPins[b]);
    if (buttonState != prevButtonStates[b])
    {
      Keyboard.press(buttonChars[b]);
      Keyboard.release(buttonChars[b]);
    }
    prevButtonStates[b] = buttonState;
  }
}

The program uses arrays to hold data and a for loop to cycle through the keys to make the code more compact as much of it is repeated, just with different keys and characters.

NOTE : I cannot test this program so it may not work and tweaks may be needed, but it does at least compile.

UKHeliBob:
It looks OK but would be better if you used byte instead of int where the value will not exceed 255 and const where the variable values will not change. Neither matter in this program but you may need to save space at some time so would be better using best practice now.

Try this program (untested)

const char backspace = KEY_BACKSPACE;

const char space = 0x20;

const byte buttonPins = {13, 12, 11, 10, 9, 8};
const byte NUM_BUTTONS = sizeof(buttonPins) / sizeof(buttonPins[0]);
byte prevButtonStates[NUM_BUTTONS];
char buttonChars = {space, ‘t’, ‘r’, ‘g’, ‘l’, backspace};
byte buttonState;

void setup()
{
  for (int b = 0; b < NUM_BUTTONS; b++)
  {
    pinMode(buttonPins[b], INPUT_PULLUP);
  }
  Keyboard.begin();
}

void loop()
{
  if (digitalRead(buttonPins[0]) == LOW)
  {
    Keyboard.press(buttonChars[0]);
    delay(250);
    Keyboard.release(buttonChars[0]);
  }

for (int b = 1; b < NUM_BUTTONS; b++)
  {
    buttonState = digitalRead(buttonPins[b]);
    if (buttonState != prevButtonStates[b])
    {
      Keyboard.press(buttonChars[b]);
      Keyboard.release(buttonChars[b]);
    }
    prevButtonStates[b] = buttonState;
  }
}



The program uses arrays to hold data and a for loop to cycle through the keys to make the code more compact as much of it is repeated, just with different keys and characters.

NOTE : I cannot test this program so it may not work and tweaks may be needed, but it does at least compile.

thanks, the program works fine, but i think im going to stick with mine. im trying to learn how the code works and what it does without just copying and pasting, and your code is quite a bit too advanced for me right now to even understand

I am glad it works(phew !) and can appreciate how you feel about just using it without understanding it. Would it help if I posted the program with comments about what is going on with the code ?

UKHeliBob: I am glad it works(phew !) and can appreciate how you feel about just using it without understanding it. Would it help if I posted the program with comments about what is going on with the code ?

yeah sure, that would help a lot. i decided when i buying the arduino i was going to try and learn learn the code isntead of just copying and pasting code for all the projects i want to do

const char backspace = KEY_BACKSPACE;           //constant values that will not change
const char space = 0x20;

const byte buttonPins[] = {13, 12, 11, 10, 9, 8};  //array holding the pin numbers of the buttons
const byte NUM_BUTTONS = sizeof(buttonPins) / sizeof(buttonPins[0]);  //calculate the number of buttons
                                                                      //allows the array above to be changed
                                                                      //without the need to alter code
byte prevButtonStates[NUM_BUTTONS];                //array to hold previous states
char buttonChars[] = {space, 't', 'r', 'g', 'l', backspace};  //array of characters corresponding to
                                                              //the buttons
byte buttonState;

void setup()
{
  for (int b = 0; b < NUM_BUTTONS; b++)  //use for loop to setup pinmodes
  {
    pinMode(buttonPins[b], INPUT_PULLUP);  //turn on internal pullup resistor
  }
  Keyboard.begin();
}

void loop()
{
  if (digitalRead(buttonPins[0]) == LOW)  //read button on pin 13 and act if pressed
                                          //could have used digitalRead(13) but done like this
                                          //for consistency
  {
    Keyboard.press(buttonChars[0]);
    delay(250);
    Keyboard.release(buttonChars[0]);
  }

  for (int b = 1; b < NUM_BUTTONS; b++)  //loop through the list of button pins
  {
    buttonState = digitalRead(buttonPins[b]);  //read each button in turn
    if (buttonState != prevButtonStates[b])    //test its state
    {
      Keyboard.press(buttonChars[b]);          //if pressed, send the corresponding character
      Keyboard.release(buttonChars[b]);
    }
    prevButtonStates[b] = buttonState;        //save the current state of the button
  }
}

Let me know if you have any queries.