Jump to content

need help coding a switch on arduino for flight sim

SkippyDing
Go to solution Solved by minibois,
1 hour ago, AnotherMax said:

If it just spams a bunch that implies the switches you are using might already be toggle switches as oppose to buttons?

I don't think what minibois said would help as delaying going into the `doAction(i)` function won't change the actual delay between when the button is pressed and released.

I didn't really read/understand the full code, but just saw the debounce mentioned in the code.

The idea behind debouncing is that when you press a button, it's possible a very stable connection isn't made that very instant. Debounce basically looks at the first time a button was pressed and waits a little bit, to make sure the button press is 'legit' and not just a fluke.

 

That may not be the fix for sure though.

39 minutes ago, SkippyDing said:

ill have a little look at that now, thanks!

I just realized the problem is probably that every 'frame' the Arduino looks at the pins again to see which button(s) are pressed and based on your code it just goes "button x is press > press keycode y on the PC".

The problem with this, is that basically every 'frame' the Arduino goes "press keycode y!"

As you can see in the code, the button gets released each 'frame' too:

Keyboard.press('1');
delay(10);
Keyboard.releaseAll();

You'd need to make it so the button is held down, until you don't hold it down anymore.

So instead of just scanning for "is button pressed down", you need to scan for:

- Is button held down

- If not held down, release

 

That is what I think is going wrong. You're telling the Arduino each frame "press the button, now unpress it".

Hi!
im very new to Arduinos and coding, and am creating a panel for a flight sim
i have a bunch of switches hooked up to an Arduino micro but it doesnt do quite as i would like
the way the code is setup it just keeps cycling and pressing the button i want but this doesnt hold up well in games as it just spams the button rather than hold it
can anyone give any suggestions?
thanks!
 

#include "Keyboard.h"
int keys[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
void setup() {
 // put your setup code here, to run once:
 Keyboard.begin(); // setup keyboard
 for (int i = 2; i < 13; ++i) {
 // initilize pins
 pinMode(i, INPUT);
 }
}
void loop() {
 // put your main code here, to run repeatedly:
 for (int i = 2; i < 13; ++i) {
 // check buttons
 if(readButton(i)) {
 doAction(i); 
 }
 }
}
boolean readButton(int pin) {
 // check and debounce buttons
 if (digitalRead(pin) == HIGH) {
 delay(10);
 if (digitalRead(pin) == HIGH) {
 return true;
 }
 }
 return false;
}
void doAction(int pin) {
 switch (pin) {
 case 2:
 Keyboard.press('1');
 delay(10);
 Keyboard.releaseAll();
 break;
 case 3:
 Keyboard.press('2');
 delay(10);
 Keyboard.releaseAll();
 break;
 case 4:
  Keyboard.press('3');
 delay(10);
 Keyboard.releaseAll();
 break;
 case 5:
 Keyboard.press('4');
 delay(10);
 Keyboard.releaseAll();
 break;
 case 6:
 Keyboard.press('5');
 delay(10);
 Keyboard.releaseAll();
 break;
 case 7:
 Keyboard.press('6');
 delay(10);
 Keyboard.releaseAll();
 break;
 case 8:
 Keyboard.press('7');
  delay(10);
 Keyboard.releaseAll();
 break;
 case 9:
 Keyboard.press('8');
 delay(10);
 Keyboard.releaseAll();
 break;
 case 10:
 Keyboard.press('9');
 delay(10);
 Keyboard.releaseAll();
 break;
 }
}

sketch_apr13a.ino

Link to comment
Share on other sites

Link to post
Share on other sites

Your debounce delay in readButton might need to be increased a bit.

Otherwise, I would personally highly recommend QMK. Takes a little bit to setup, but has been working solid for a little keypad project I made.

"We're all in this together, might as well be friends" Tom, Toonami.

 

mini eLiXiVy: my open source 65% mechanical PCB, a build log, PCB anatomy and discussing open source licenses: https://linustechtips.com/topic/1366493-elixivy-a-65-mechanical-keyboard-build-log-pcb-anatomy-and-how-i-open-sourced-this-project/

 

mini_cardboard: a 4% keyboard build log and how keyboards workhttps://linustechtips.com/topic/1328547-mini_cardboard-a-4-keyboard-build-log-and-how-keyboards-work/

Link to comment
Share on other sites

Link to post
Share on other sites

I think a bit more info is needed to help:

What do you want the actually functionality to be (what behaviour do you want)? e.g. A toggle (you press and it holds)? A you press and it holds for a short while?

If it just spams a bunch that implies the switches you are using might already be toggle switches as oppose to buttons?

I don't think what minibois said would help as delaying going into the `doAction(i)` function won't change the actual delay between when the button is pressed and released.

Link to comment
Share on other sites

Link to post
Share on other sites

46 minutes ago, AnotherMax said:

I think a bit more info is needed to help:

What do you want the actually functionality to be (what behaviour do you want)? e.g. A toggle (you press and it holds)? A you press and it holds for a short while?

If it just spams a bunch that implies the switches you are using might already be toggle switches as oppose to buttons?

I don't think what minibois said would help as delaying going into the `doAction(i)` function won't change the actual delay between when the button is pressed and released.

Hi, thanks for your message
I guess i need it to hold, as it is a switch
my current code does this, and when i flip the switch it spams the 1 key for instance, and this is the only way ive found to "hold" the switch
i want it to act as though i am holding down a key, for instance the 'w' key to move in a game, instead it just spams the 'w' key so my character kind jitters 

 

Link to comment
Share on other sites

Link to post
Share on other sites

3 hours ago, minibois said:

Your debounce delay in readButton might need to be increased a bit.

Otherwise, I would personally highly recommend QMK. Takes a little bit to setup, but has been working solid for a little keypad project I made.

ill have a little look at that now, thanks!

 

Link to comment
Share on other sites

Link to post
Share on other sites

1 hour ago, AnotherMax said:

If it just spams a bunch that implies the switches you are using might already be toggle switches as oppose to buttons?

I don't think what minibois said would help as delaying going into the `doAction(i)` function won't change the actual delay between when the button is pressed and released.

I didn't really read/understand the full code, but just saw the debounce mentioned in the code.

The idea behind debouncing is that when you press a button, it's possible a very stable connection isn't made that very instant. Debounce basically looks at the first time a button was pressed and waits a little bit, to make sure the button press is 'legit' and not just a fluke.

 

That may not be the fix for sure though.

39 minutes ago, SkippyDing said:

ill have a little look at that now, thanks!

I just realized the problem is probably that every 'frame' the Arduino looks at the pins again to see which button(s) are pressed and based on your code it just goes "button x is press > press keycode y on the PC".

The problem with this, is that basically every 'frame' the Arduino goes "press keycode y!"

As you can see in the code, the button gets released each 'frame' too:

Keyboard.press('1');
delay(10);
Keyboard.releaseAll();

You'd need to make it so the button is held down, until you don't hold it down anymore.

So instead of just scanning for "is button pressed down", you need to scan for:

- Is button held down

- If not held down, release

 

That is what I think is going wrong. You're telling the Arduino each frame "press the button, now unpress it".

"We're all in this together, might as well be friends" Tom, Toonami.

 

mini eLiXiVy: my open source 65% mechanical PCB, a build log, PCB anatomy and discussing open source licenses: https://linustechtips.com/topic/1366493-elixivy-a-65-mechanical-keyboard-build-log-pcb-anatomy-and-how-i-open-sourced-this-project/

 

mini_cardboard: a 4% keyboard build log and how keyboards workhttps://linustechtips.com/topic/1328547-mini_cardboard-a-4-keyboard-build-log-and-how-keyboards-work/

Link to comment
Share on other sites

Link to post
Share on other sites

#include "Keyboard.h"
int keys[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};

// A nicer way would be to include an array of something like so
// 
//struct KeyThing {
//  int key;
//  char keyToPress;
//  boolean isActive;
//};
//
//KeyThing keyData[12];

int pinPressed = 0;
boolean isActive = false;

void setup() {
  Keyboard.begin();
  for (int i = 2; i < 13; ++i) {
    // initilize pins
    pinMode(i, INPUT);
  }
}
void loop() {
  for (int i = 2; i < 13; ++i) {
    handleButtonPin(i);
  }
  // Short delay
  delay(10);
}

boolean handleButtonPin(int pin) {
  if (digitalRead(pin) == HIGH && isActive == false) {
    // Store the pin thats pressed then set isActive to true so this can't be called again
    // by another pin
    pinPressed = pin;
    isActive = true;
    doAction(pin);
  } else if (pinPressed == pin && digitalRead(pin) == LOW && isActive == true) {
    // This will only get called when the pin thats pressed is the 'pin' and it's LOW and it's active
    isActive = false;
    Keyboard.releaseAll();
  }
}
void doAction(int pin) {
 switch (pin) {
   case 2:
     Keyboard.press('1');
     break;
   case 3:
     Keyboard.press('2');
     break;
   case 4:
     Keyboard.press('3');
     break;
   case 5:
     Keyboard.press('4');
     break;
   case 6:
     Keyboard.press('5');
     break;
   case 7:
     Keyboard.press('6');
     break;
   case 8:
     Keyboard.press('7');
     break;
   case 9:
     Keyboard.press('8');
     break;
   case 10:
     Keyboard.press('9');
     break;
 }
}

Modifed your code a little (not tested). So this can currently only handle 1 switch at a time due to having two variables for storing the state. This could be fixed but would be slightly more complex. I personally prefer code examples to understand things. If you want more of an explanation as to why this works (assuming it does) either ask for further details or inspect the code and add print statements to see what variables are what and when (this can help you understand it)

Link to comment
Share on other sites

Link to post
Share on other sites

1 hour ago, AnotherMax said:

#include "Keyboard.h"
int keys[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};

// A nicer way would be to include an array of something like so
// 
//struct KeyThing {
//  int key;
//  char keyToPress;
//  boolean isActive;
//};
//
//KeyThing keyData[12];

int pinPressed = 0;
boolean isActive = false;

void setup() {
  Keyboard.begin();
  for (int i = 2; i < 13; ++i) {
    // initilize pins
    pinMode(i, INPUT);
  }
}
void loop() {
  for (int i = 2; i < 13; ++i) {
    handleButtonPin(i);
  }
  // Short delay
  delay(10);
}

boolean handleButtonPin(int pin) {
  if (digitalRead(pin) == HIGH && isActive == false) {
    // Store the pin thats pressed then set isActive to true so this can't be called again
    // by another pin
    pinPressed = pin;
    isActive = true;
    doAction(pin);
  } else if (pinPressed == pin && digitalRead(pin) == LOW && isActive == true) {
    // This will only get called when the pin thats pressed is the 'pin' and it's LOW and it's active
    isActive = false;
    Keyboard.releaseAll();
  }
}
void doAction(int pin) {
 switch (pin) {
   case 2:
     Keyboard.press('1');
     break;
   case 3:
     Keyboard.press('2');
     break;
   case 4:
     Keyboard.press('3');
     break;
   case 5:
     Keyboard.press('4');
     break;
   case 6:
     Keyboard.press('5');
     break;
   case 7:
     Keyboard.press('6');
     break;
   case 8:
     Keyboard.press('7');
     break;
   case 9:
     Keyboard.press('8');
     break;
   case 10:
     Keyboard.press('9');
     break;
 }
}

Modifed your code a little (not tested). So this can currently only handle 1 switch at a time due to having two variables for storing the state. This could be fixed but would be slightly more complex. I personally prefer code examples to understand things. If you want more of an explanation as to why this works (assuming it does) either ask for further details or inspect the code and add print statements to see what variables are what and when (this can help you understand it)

thank you very much!!
ill test that out tomorrow and let you know, i really apricate your help

Link to comment
Share on other sites

Link to post
Share on other sites

1 hour ago, minibois said:

I didn't really read/understand the full code, but just saw the debounce mentioned in the code.

The idea behind debouncing is that when you press a button, it's possible a very stable connection isn't made that very instant. Debounce basically looks at the first time a button was pressed and waits a little bit, to make sure the button press is 'legit' and not just a fluke.

 

That may not be the fix for sure though.

I just realized the problem is probably that every 'frame' the Arduino looks at the pins again to see which button(s) are pressed and based on your code it just goes "button x is press > press keycode y on the PC".

The problem with this, is that basically every 'frame' the Arduino goes "press keycode y!"

As you can see in the code, the button gets released each 'frame' too:


Keyboard.press('1');
delay(10);
Keyboard.releaseAll();

You'd need to make it so the button is held down, until you don't hold it down anymore.

So instead of just scanning for "is button pressed down", you need to scan for:

- Is button held down

- If not held down, release

 

That is what I think is going wrong. You're telling the Arduino each frame "press the button, now unpress it".

thats done an amazing job at explaining it, thank you so much
you have been incredibly helpful!
ill give these suggestions a test

Link to comment
Share on other sites

Link to post
Share on other sites

2 hours ago, minibois said:

The idea behind debouncing is that when you press a button, it's possible a very stable connection isn't made that very instant. Debounce basically looks at the first time a button was pressed and waits a little bit, to make sure the button press is 'legit' and not just a fluke.

Oh good point, I was thinking of debouce incorrectly in my little brain.

 

You will probably want to re-add you're debounce back in given what minibois has stated.

Link to comment
Share on other sites

Link to post
Share on other sites

14 hours ago, AnotherMax said:

#include "Keyboard.h"
int keys[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};

// A nicer way would be to include an array of something like so
// 
//struct KeyThing {
//  int key;
//  char keyToPress;
//  boolean isActive;
//};
//
//KeyThing keyData[12];

int pinPressed = 0;
boolean isActive = false;

void setup() {
  Keyboard.begin();
  for (int i = 2; i < 13; ++i) {
    // initilize pins
    pinMode(i, INPUT);
  }
}
void loop() {
  for (int i = 2; i < 13; ++i) {
    handleButtonPin(i);
  }
  // Short delay
  delay(10);
}

boolean handleButtonPin(int pin) {
  if (digitalRead(pin) == HIGH && isActive == false) {
    // Store the pin thats pressed then set isActive to true so this can't be called again
    // by another pin
    pinPressed = pin;
    isActive = true;
    doAction(pin);
  } else if (pinPressed == pin && digitalRead(pin) == LOW && isActive == true) {
    // This will only get called when the pin thats pressed is the 'pin' and it's LOW and it's active
    isActive = false;
    Keyboard.releaseAll();
  }
}
void doAction(int pin) {
 switch (pin) {
   case 2:
     Keyboard.press('1');
     break;
   case 3:
     Keyboard.press('2');
     break;
   case 4:
     Keyboard.press('3');
     break;
   case 5:
     Keyboard.press('4');
     break;
   case 6:
     Keyboard.press('5');
     break;
   case 7:
     Keyboard.press('6');
     break;
   case 8:
     Keyboard.press('7');
     break;
   case 9:
     Keyboard.press('8');
     break;
   case 10:
     Keyboard.press('9');
     break;
 }
}

Modifed your code a little (not tested). So this can currently only handle 1 switch at a time due to having two variables for storing the state. This could be fixed but would be slightly more complex. I personally prefer code examples to understand things. If you want more of an explanation as to why this works (assuming it does) either ask for further details or inspect the code and add print statements to see what variables are what and when (this can help you understand it)

ive had a test and everything works, unfortunately having multiple switches on at the same time is kind of a requirement, any suggestions on how to do this?
thanks so much for your time

 

Link to comment
Share on other sites

Link to post
Share on other sites

3 hours ago, SkippyDing said:

ive had a test and everything works, unfortunately having multiple switches on at the same time is kind of a requirement, any suggestions on how to do this?
thanks so much for your time

 

Take a look at the top of the code that's commented out. Personally, I'd take an approach where you create an array of struct such as that and store all the data within those:

e.g.

#include "Keyboard.h"
int keys[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};

// A nicer way would be to include an array of something like so
 
struct KeyThing {
  int pin;
  char keyToPress;
  boolean isActive;
};

KeyThing allKeys[12];

void setup() {
  Keyboard.begin();
  // '1' starts at the decimal number 49
  int x = 49;  // https://www.ibm.com/docs/en/aix/7.2?topic=adapters-ascii-decimal-hexadecimal-octal-binary-conversion-table
  for (int i = 0; i < 11; ++i) {
    // initilize pins
    pinMode(i, INPUT);
    // Add all the keys into the 'allKeys' with the correct values
    allKeys[i].pin = keys[i];
    allKeys[i].keyToPress = x;
    allKeys[i].isActive = false;
    x++;
  }
}
void loop() {
  for (int i = 0; i < 11; ++i) {
    handleSwitchPin(allKeys[i]);
  }
  // Short delay
  delay(10);
}

boolean handleSwitchPin(KeyThing keyData) {
  if (digitalRead(keyData.pin) == HIGH && keyData.isActive == false) {
    // Store the pin thats pressed then set isActive to true so this can't be called again
    // by another pin
    keyData.isActive = true;
    Keyboard.press(keyData.keyToPress);
  } else if (digitalRead(keyData.pin) == LOW && keyData.isActive == true) {
    // This will only get called when the pin thats pressed is the 'pin' and it's LOW and it's active
    keyData.isActive = false;
    Keyboard.release(keyData.keyToPress);  // Release specific key
  }
}

My C is a bit rusty so this might not work first time. I'd also come up with a better struct name other then 'KeyThing'

Link to comment
Share on other sites

Link to post
Share on other sites

10 hours ago, AnotherMax said:

Take a look at the top of the code that's commented out. Personally, I'd take an approach where you create an array of struct such as that and store all the data within those:

e.g.


#include "Keyboard.h"
int keys[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};

// A nicer way would be to include an array of something like so
 
struct KeyThing {
  int pin;
  char keyToPress;
  boolean isActive;
};

KeyThing allKeys[12];

void setup() {
  Keyboard.begin();
  // '1' starts at the decimal number 49
  int x = 49;  // https://www.ibm.com/docs/en/aix/7.2?topic=adapters-ascii-decimal-hexadecimal-octal-binary-conversion-table
  for (int i = 0; i < 11; ++i) {
    // initilize pins
    pinMode(i, INPUT);
    // Add all the keys into the 'allKeys' with the correct values
    allKeys[i].pin = keys[i];
    allKeys[i].keyToPress = x;
    allKeys[i].isActive = false;
    x++;
  }
}
void loop() {
  for (int i = 0; i < 11; ++i) {
    handleSwitchPin(allKeys[i]);
  }
  // Short delay
  delay(10);
}

boolean handleSwitchPin(KeyThing keyData) {
  if (digitalRead(keyData.pin) == HIGH && keyData.isActive == false) {
    // Store the pin thats pressed then set isActive to true so this can't be called again
    // by another pin
    keyData.isActive = true;
    Keyboard.press(keyData.keyToPress);
  } else if (digitalRead(keyData.pin) == LOW && keyData.isActive == true) {
    // This will only get called when the pin thats pressed is the 'pin' and it's LOW and it's active
    keyData.isActive = false;
    Keyboard.release(keyData.keyToPress);  // Release specific key
  }
}

My C is a bit rusty so this might not work first time. I'd also come up with a better struct name other then 'KeyThing'

im very unfamiliar with this, but i do really apricate you taking the time to help! 
ill have a little play around and see if i can get some meaningful results
really apricate it

Link to comment
Share on other sites

Link to post
Share on other sites

8 minutes ago, SkippyDing said:

im very unfamiliar with this, but i do really apricate you taking the time to help! 
ill have a little play around and see if i can get some meaningful results
really apricate it

How do you physically have everything setup? As in, I assume you have an Arduino Pro Micro, with the buttons set up in a matrix? With or without diodes?

If the keyboard.h library doesn't work out, I'd heavily suggest using QMK, they even have a guide on how to use QMK for a handwired board: https://docs.qmk.fm/#/hand_wire

"We're all in this together, might as well be friends" Tom, Toonami.

 

mini eLiXiVy: my open source 65% mechanical PCB, a build log, PCB anatomy and discussing open source licenses: https://linustechtips.com/topic/1366493-elixivy-a-65-mechanical-keyboard-build-log-pcb-anatomy-and-how-i-open-sourced-this-project/

 

mini_cardboard: a 4% keyboard build log and how keyboards workhttps://linustechtips.com/topic/1328547-mini_cardboard-a-4-keyboard-build-log-and-how-keyboards-work/

Link to comment
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×