Created
March 14, 2018 09:28
-
-
Save NormalUniverse/f8dbc04164ce240c973e739a1fb37eeb to your computer and use it in GitHub Desktop.
Simple Button Debounce State Machine
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Title: Button Debouncing using a State Machine, Complex Version | |
//Author: Chris Guichet | |
//Date: Jan 15, 2018 | |
// | |
//Description: | |
// -A State Machine is a useful tool to organize complex code | |
// -Think of it like the next step beyone "If Else" statements | |
// -This example code uses a State Machine to handle tac switch debouncing | |
// -It also has a "Hold" function to enable interaction with long button presses | |
// | |
//Wiring Instructions: | |
// -Wire a SPST momentary switch between a Digital I/O pin and Ground. (I use pin 12) | |
// (we will use an internal pullup resistor, so no need to worry about wiring a resistor) | |
// | |
//Code Reading Tip: | |
// -Before mentally digesting this code, collapse all folds to get a bird's eye view. | |
// -Ctrl-a (to select all) -> Right Click -> Folding -> Collapse All Folds | |
//Top Level Variables: | |
int DEBUG = 1; //Set to 1 to enable serial monitor debugging info | |
//Switch Variables: | |
int state_s1 = 0; | |
int state_prev_s1 = 0; | |
int pin_s1 = 12; | |
int val_s1 = 0; | |
unsigned long t_s1 = 0; | |
unsigned long t_0_s1 = 0; | |
unsigned long bounce_delay_s1 = 10; | |
unsigned long hold_delay_s1 = 1000; | |
void setup() { | |
// initialize digital pins | |
pinMode(12,INPUT_PULLUP); //INPUT_PULLUP will use the Arduino's internal pullup resistor | |
//if DEBUG is turned on, intiialize serial connection | |
if(DEBUG) {Serial.begin(115200);Serial.println("Debugging is ON");} | |
} | |
void loop() { | |
// put your main code here, to run repeatedly: | |
SM_s1(); | |
//If debug is enabled, do some printing of messages | |
//Let the world know when the state changes | |
if(DEBUG) { | |
if(state_prev_s1 != state_s1) {Serial.print("Switch State: "); Serial.println(state_s1);} | |
}; | |
//Let the world know when the button is held or pressed | |
if (DEBUG) {Serial.println("HOLDED!!");} | |
if (DEBUG) {Serial.println("TRIGGERED!!");} | |
} | |
void SM_s1() { | |
//Almost every state needs these lines, so I'll put it outside the State Machine | |
val_s1 = digitalRead(pin_s1); | |
state_prev_s1 = state_s1; | |
//State Machine Section | |
switch (state_s1) { | |
case 0: //RESET! | |
//Catch all "home base" for the State MAchine | |
state_s1 = 1; | |
break; | |
case 1: //WAIT | |
//Wait for the switch to go low | |
if (val_s1 == LOW) {state_s1 = 2;} | |
break; | |
case 2: //ARMING! | |
//Record the time and proceed to ARMED | |
t_0_s1 = millis(); | |
state_s1 = 3; | |
break; | |
case 3: //ARMED | |
//Check to see if the proper has delay has passed. If a bounce occures then RESET | |
t_s1 = millis(); | |
if (t_s1 - t_0_s1 > bounce_delay_s1) {state_s1 = 4;} | |
if (val_s1 == HIGH) {state_s1 = 0;} | |
break; | |
case 4: //DRAWN | |
//If switch goes HIGH, then TRIGGER. Also check timer for a "Long Pess" | |
t_s1 = millis(); | |
if (val_s1 == HIGH) {state_s1 = 5;} | |
if (t_s1 - t_0_s1 > hold_delay_s1) {state_s1 = 6;} | |
break; | |
case 5: //TRIGGERED! | |
//reset the State Machine | |
state_s1 = 0; | |
break; | |
case 6: //HOLD! | |
//proceed to LOW WAIT | |
state_s1 = 7; | |
break; | |
case 7: //LOW WAIT | |
//wait for switch to go back HIGH, then reset | |
if (val_s1 == HIGH) {state_s1 = 0;} | |
break; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment