2015年7月5日 星期日

Debouncing Multiple Switches

Debouncing Multiple Switches


源自於 http://www.ediy.com.my/index.php/tutorials/item/96-debouncing-multiple-switches


If you want to input a manual switch signal into a digital circuit you'll need to debounce the signal so a single press doesn't appear like multiple presses. 


There is a Bounce library for Arduino which is very easy to use. However there is limitations with this Boounce library.
  • You are unlikely to enable the internal pull-up resistor on switch pins, therefore each switch require an external pull-up resistor
  • It is not possible to detect the switch state before main loop (setup). When you press a switch during power on, you will never get the state of the switch.
Adafruit wrote an example code for multi-button checker with debouncing which will solve that two problems.
  1. #define DEBOUNCE 10 // button debouncer, how many ms to debounce, 5+ ms is usually plenty
  2. // here is where we define the buttons that we'll use. button "1" is the first, button "6" is the 6th, etc
  3. byte buttons[] = {4, 5, 6, 7, 8, 9};
  4. // This handy macro lets us determine how big the array up above is, by checking the size
  5. #define NUMBUTTONS sizeof(buttons)
  6. // we will track if a button is just pressed, just released, or 'currently pressed'
  7. byte pressed[NUMBUTTONS], justpressed[NUMBUTTONS], justreleased[NUMBUTTONS];
  8. void setup() {
  9. byte i;
  10. // set up serial port
  11. Serial.begin(9600);
  12. Serial.print("Button checker with ");
  13. Serial.print(NUMBUTTONS, DEC);
  14. Serial.println(" buttons");
  15. // pin13 LED
  16. pinMode(13, OUTPUT);
  17. // Make input & enable pull-up resistors on switch pins
  18. for (i=0; i< NUMBUTTONS; i++) {
  19. pinMode(buttons[i], INPUT);
  20. digitalWrite(buttons[i], HIGH);
  21. }
  22. }
  23. void check_switches()
  24. {
  25. static byte previousstate[NUMBUTTONS];
  26. static byte currentstate[NUMBUTTONS];
  27. static long lasttime;
  28. byte index;
  29. if (millis() < lasttime) {
  30. lasttime = millis(); // we wrapped around, lets just try again
  31. }
  32. if ((lasttime + DEBOUNCE) > millis()) {
  33. return; // not enough time has passed to debounce
  34. }
  35. // ok we have waited DEBOUNCE milliseconds, lets reset the timer
  36. lasttime = millis();
  37. for (index = 0; index < NUMBUTTONS; index++) {
  38. justpressed[index] = 0; // when we start, we clear out the "just" indicators
  39. justreleased[index] = 0;
  40. currentstate[index] = digitalRead(buttons[index]); // read the button
  41. if (currentstate[index] == previousstate[index]) {
  42. if ((pressed[index] == LOW) &amp;&amp; (currentstate[index] == LOW)) {
  43. // just pressed
  44. justpressed[index] = 1;
  45. }
  46. else if ((pressed[index] == HIGH) &amp;&amp; (currentstate[index] == HIGH)) {
  47. // just released
  48. justreleased[index] = 1;
  49. }
  50. pressed[index] = !currentstate[index]; // remember, digital HIGH means NOT pressed
  51. }
  52. //Serial.println(pressed[index], DEC);
  53. previousstate[index] = currentstate[index]; // keep a running tally of the buttons
  54. }
  55. }
  56. void loop() {
  57. check_switches(); // when we check the switches we'll get the current state
  58. for (byte i = 0; i < NUMBUTTONS; i++) {
  59. if (justpressed[i]) {
  60. Serial.print(i, DEC);
  61. Serial.println(" Just pressed");
  62. // remember, check_switches() will CLEAR the 'just pressed' flag
  63. }
  64. if (justreleased[i]) {
  65. Serial.print(i, DEC);
  66. Serial.println(" Just released");
  67. // remember, check_switches() will CLEAR the 'just pressed' flag
  68. }
  69. if (pressed[i]) {
  70. Serial.print(i, DEC);
  71. Serial.println(" pressed");
  72. // is the button pressed down at this moment
  73. }
  74. }
  75. }
I'm modifying the example code, it is useful if you want something to only happen once when a button is pressed.
  1. #define DEBOUNCE 10 // how many ms to debounce, 5+ ms is usually plenty
  2. //define the buttons that we'll use.
  3. byte buttons[] = {4, 5, 6, 7, 8, 9};
  4. //determine how big the array up above is, by checking the size
  5. #define NUMBUTTONS sizeof(buttons)
  6. //track if a button is just pressed, just released, or 'currently pressed'
  7. byte pressed[NUMBUTTONS], justpressed[NUMBUTTONS], justreleased[NUMBUTTONS];
  8. byte previous_keystate[NUMBUTTONS], current_keystate[NUMBUTTONS];
  9. void setup() {
  10. byte i;
  11. Serial.begin(9600); //set up serial port
  12. Serial.print("Button checker with ");
  13. Serial.print(NUMBUTTONS, DEC);
  14. Serial.println(" buttons");
  15. // Make input &amp; enable pull-up resistors on switch pins
  16. for (i=0; i< NUMBUTTONS; i++) {
  17. pinMode(buttons[i], INPUT);
  18. digitalWrite(buttons[i], HIGH);
  19. }
  20. }
  21. void loop() {
  22. byte thisSwitch=thisSwitch_justPressed();
  23. switch(thisSwitch)
  24. {
  25. case 0:
  26. Serial.println("switch 1 just pressed"); break;
  27. case 1:
  28. Serial.println("switch 2 just pressed"); break;
  29. case 2:
  30. Serial.println("switch 3 just pressed"); break;
  31. case 3:
  32. Serial.println("switch 4 just pressed"); break;
  33. case 4:
  34. Serial.println("switch 5 just pressed"); break;
  35. case 5:
  36. Serial.println("switch 6 just pressed"); break;
  37. }
  38. }
  39. void check_switches()
  40. {
  41. static byte previousstate[NUMBUTTONS];
  42. static byte currentstate[NUMBUTTONS];
  43. static long lasttime;
  44. byte index;
  45. if (millis() < lasttime) {
  46. // we wrapped around, lets just try again
  47. lasttime = millis();
  48. }
  49. if ((lasttime + DEBOUNCE) > millis()) {
  50. // not enough time has passed to debounce
  51. return;
  52. }
  53. // ok we have waited DEBOUNCE milliseconds, lets reset the timer
  54. lasttime = millis();
  55. for (index = 0; index < NUMBUTTONS; index++) {
  56. justpressed[index] = 0; //when we start, we clear out the "just" indicators
  57. justreleased[index] = 0;
  58. currentstate[index] = digitalRead(buttons[index]); //read the button
  59. if (currentstate[index] == previousstate[index]) {
  60. if ((pressed[index] == LOW) &amp;&amp; (currentstate[index] == LOW)) {
  61. // just pressed
  62. justpressed[index] = 1;
  63. }
  64. else if ((pressed[index] == HIGH) &amp;&amp; (currentstate[index] == HIGH)) {
  65. justreleased[index] = 1; // just released
  66. }
  67. pressed[index] = !currentstate[index]; //remember, digital HIGH means NOT pressed
  68. }
  69. previousstate[index] = currentstate[index]; //keep a running tally of the buttons
  70. }
  71. }
  72. byte thisSwitch_justPressed() {
  73. byte thisSwitch = 255;
  74. check_switches(); //check the switches &amp; get the current state
  75. for (byte i = 0; i < NUMBUTTONS; i++) {
  76. current_keystate[i]=justpressed[i];
  77. if (current_keystate[i] != previous_keystate[i]) {
  78. if (current_keystate[i]) thisSwitch=i;
  79. }
  80. previous_keystate[i]=current_keystate[i];
  81. }
  82. return thisSwitch;
  83. }

沒有留言:

張貼留言

2024_09 作業3 以Node-Red 為主

 2024_09 作業3  (以Node-Red 為主  Arduino 可能需要配合修改 ) Arduino 可能需要修改的部分 1)mqtt broker  2) 主題Topic (發行 接收) 3) WIFI ssid , password const char br...