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.
#define DEBOUNCE 10 // button debouncer, how many ms to debounce, 5+ ms is usually plenty // here is where we define the buttons that we'll use. button "1" is the first, button "6" is the 6th, etc byte buttons[] = {4, 5, 6, 7, 8, 9}; // This handy macro lets us determine how big the array up above is, by checking the size #define NUMBUTTONS sizeof(buttons) // we will track if a button is just pressed, just released, or 'currently pressed' byte pressed[NUMBUTTONS], justpressed[NUMBUTTONS], justreleased[NUMBUTTONS]; void setup() { byte i; // set up serial port Serial.begin(9600); Serial.print("Button checker with "); Serial.print(NUMBUTTONS, DEC); Serial.println(" buttons"); // pin13 LED pinMode(13, OUTPUT); // Make input & enable pull-up resistors on switch pins for (i=0; i< NUMBUTTONS; i++) { pinMode(buttons[i], INPUT); digitalWrite(buttons[i], HIGH); } } void check_switches() { static byte previousstate[NUMBUTTONS]; static byte currentstate[NUMBUTTONS]; static long lasttime; byte index; if (millis() < lasttime) { lasttime = millis(); // we wrapped around, lets just try again } if ((lasttime + DEBOUNCE) > millis()) { return; // not enough time has passed to debounce } // ok we have waited DEBOUNCE milliseconds, lets reset the timer lasttime = millis(); for (index = 0; index < NUMBUTTONS; index++) { justpressed[index] = 0; // when we start, we clear out the "just" indicators justreleased[index] = 0; currentstate[index] = digitalRead(buttons[index]); // read the button if (currentstate[index] == previousstate[index]) { if ((pressed[index] == LOW) && (currentstate[index] == LOW)) { // just pressed justpressed[index] = 1; } else if ((pressed[index] == HIGH) && (currentstate[index] == HIGH)) { // just released justreleased[index] = 1; } pressed[index] = !currentstate[index]; // remember, digital HIGH means NOT pressed } //Serial.println(pressed[index], DEC); previousstate[index] = currentstate[index]; // keep a running tally of the buttons } } void loop() { check_switches(); // when we check the switches we'll get the current state for (byte i = 0; i < NUMBUTTONS; i++) { if (justpressed[i]) { Serial.print(i, DEC); Serial.println(" Just pressed"); // remember, check_switches() will CLEAR the 'just pressed' flag } if (justreleased[i]) { Serial.print(i, DEC); Serial.println(" Just released"); // remember, check_switches() will CLEAR the 'just pressed' flag } if (pressed[i]) { Serial.print(i, DEC); Serial.println(" pressed"); // is the button pressed down at this moment } } }
I'm modifying the example code, it is useful if you want something to only happen once when a button is pressed.
#define DEBOUNCE 10 // how many ms to debounce, 5+ ms is usually plenty //define the buttons that we'll use. byte buttons[] = {4, 5, 6, 7, 8, 9}; //determine how big the array up above is, by checking the size #define NUMBUTTONS sizeof(buttons) //track if a button is just pressed, just released, or 'currently pressed' byte pressed[NUMBUTTONS], justpressed[NUMBUTTONS], justreleased[NUMBUTTONS]; byte previous_keystate[NUMBUTTONS], current_keystate[NUMBUTTONS]; void setup() { byte i; Serial.begin(9600); //set up serial port Serial.print("Button checker with "); Serial.print(NUMBUTTONS, DEC); Serial.println(" buttons"); // Make input & enable pull-up resistors on switch pins for (i=0; i< NUMBUTTONS; i++) { pinMode(buttons[i], INPUT); digitalWrite(buttons[i], HIGH); } } void loop() { byte thisSwitch=thisSwitch_justPressed(); switch(thisSwitch) { case 0: Serial.println("switch 1 just pressed"); break; case 1: Serial.println("switch 2 just pressed"); break; case 2: Serial.println("switch 3 just pressed"); break; case 3: Serial.println("switch 4 just pressed"); break; case 4: Serial.println("switch 5 just pressed"); break; case 5: Serial.println("switch 6 just pressed"); break; } } void check_switches() { static byte previousstate[NUMBUTTONS]; static byte currentstate[NUMBUTTONS]; static long lasttime; byte index; if (millis() < lasttime) { // we wrapped around, lets just try again lasttime = millis(); } if ((lasttime + DEBOUNCE) > millis()) { // not enough time has passed to debounce return; } // ok we have waited DEBOUNCE milliseconds, lets reset the timer lasttime = millis(); for (index = 0; index < NUMBUTTONS; index++) { justpressed[index] = 0; //when we start, we clear out the "just" indicators justreleased[index] = 0; currentstate[index] = digitalRead(buttons[index]); //read the button if (currentstate[index] == previousstate[index]) { if ((pressed[index] == LOW) && (currentstate[index] == LOW)) { // just pressed justpressed[index] = 1; } else if ((pressed[index] == HIGH) && (currentstate[index] == HIGH)) { justreleased[index] = 1; // just released } pressed[index] = !currentstate[index]; //remember, digital HIGH means NOT pressed } previousstate[index] = currentstate[index]; //keep a running tally of the buttons } } byte thisSwitch_justPressed() { byte thisSwitch = 255; check_switches(); //check the switches & get the current state for (byte i = 0; i < NUMBUTTONS; i++) { current_keystate[i]=justpressed[i]; if (current_keystate[i] != previous_keystate[i]) { if (current_keystate[i]) thisSwitch=i; } previous_keystate[i]=current_keystate[i]; } return thisSwitch; }
沒有留言:
張貼留言