Creator: Andrew Mascolo (HazardsMind)
Date: 7/16/2014
Version 2.0
**Version 2 is now available. Now gives the user Double and Multiclick options. However, because the new structure, the code does not handle onRelease so well, so I took it out. Sorry :/ Also no more precision mode, now it is just using milliseconds, that is until I can figure out the bug the code has when using microseconds.
Version: 1.04
**Added Rollover check, and a few other odds and ends
Version: 1.03
**Added SetDebounceTime function
Version: 1.02
**fixed checkbutton function
This library can return the state of the button as Waiting, Pressed, Held or Released. Users can also assign that button to execute functions depending on those state (Except Waiting). Users can also execute multiple functions based on the time the button is pressed, held or released.
#define WAITING 0 #define PRESSED 1 #define HELD 2 #define RELEASED 3 #define SECONDS 1000000 #define MILLISECONDS 1000 #define MICROSECONDS 1 #if defined(ARDUINO) && ARDUINO >= 100 #include "Arduino.h" #else //just in case someone is still using old versions #include "WProgram.h" #endif class Button { private: bool State, lastState; unsigned long onTime, holdTime, heldTime, DBTime, DBInterval, RO_Time; byte _P; byte ButtonState; void (*F_on)(); void (*F_hold)(); void (*F_off)(); public: Button(byte Precision = LOW) : _P(Precision) { } // precision default = LOW or Milliseconds void SetStateAndTime(byte S = HIGH, unsigned long T = 500) { State = S; // Set the preferred state of the button. (Is the button HIGH or LOW when pressed?) lastState = !State; //lastState should be inverted from State holdTime = _P ? (T * 1000) : T; // Set the hold time in seconds } void SetDebounceTime(unsigned long T = 50) { DBInterval = _P ? (T * 1000) : T; } void onPressed(void (*ON)() ) { F_on = ON; } void onHold(void (*HOLD)() ) { F_hold = HOLD; } void onReleased(void (*OFF)() ) { F_off = OFF; } byte checkButton(byte _buttonPin ) { static byte _button; // Button has not been pressed yet ButtonState = WAITING; _button = digitalRead(_buttonPin); // First check to see if the button is pressed ie. State -> (LOW or HIGH) // and if it is different from it's lastState if (_button == State && lastState == !State) { DBTime = _P ? micros() : millis(); // record time onTime = _P ? micros() : millis(); // Execute ON function if (*F_on) // if something was assigned to that function, do it F_on(); // This prevents the code from entering this IF statement, // until lastState is set to the preferred State again. lastState = State; // Button was pressed ButtonState = PRESSED; } if ((_P ? micros() : millis()) - DBTime >= DBInterval) { heldTime = 0; // button is still held down if (_button == State && lastState == State) { // Check for Rollover RO_Time = (_P ? micros() : millis()); // current time into RollOver variable if (RO_Time < onTime) // is the RollOver variable smaller than ontime? onTime = 0; // if yes, reset ontime to zero // check to see if button is held down for X seconds if ( (heldTime = (RO_Time - onTime)) >= (holdTime - DBInterval)) // 1 second is 1,000 milliseconds or 1,000,000 microseconds { if (*F_hold) // if something was assigned to that function, do it F_hold(); // if button is held down for X seconds, execute the HOLD function ButtonState = HELD; } } if (_button == !State && lastState == State)//Button was released { if (*F_off) // if something was assigned to that function, do it F_off(); // otherwise execute the OFF function ButtonState = RELEASED; lastState = !State; // Update lastState } } return ButtonState; } // This returns the elapsed held time float GetHeldTime(float divisor = SECONDS) { if (divisor > 0) return heldTime / divisor; else return -1; } };// End Of CLass //======================================================================================== #define buttonPin 2 #define ledPin 13 unsigned long blinkTime = millis(); Button B(HIGH); // LOW = milliseconds, HIGH = microseconds, default is LOW //======================================================================================== // //======================================================================================== void LED_ON() { digitalWrite(ledPin, HIGH); } void LED_OFF() { digitalWrite(ledPin, LOW); } void BLINK() { if (millis() - blinkTime >= 100) { blinkTime += 100; digitalWrite(ledPin, !digitalRead(ledPin)); } } //======================================================================================== void setup() { Serial.begin(115200); pinMode(ledPin, OUTPUT); pinMode(buttonPin, INPUT_PULLUP); // Set what the button will be when pressed (default is HIGH) // and set the hold time (default is 500) B.SetStateAndTime(LOW, 0); // B.onPressed(LED_ON); // B.onHold(BLINK); // B.onReleased(LED_OFF); } void loop() { byte myButton = B.checkButton(buttonPin); if (myButton) // if myButton is anything but 0, it is true { unsigned long timer = B.GetHeldTime(SECONDS); switch (timer) { case 0: Serial.println("Quick press"); break; case 6 ... 10: Serial.println("Longer than 5 seconds"); break; default: Serial.print(timer); Serial.println(" Seconds"); break; } } }
Sketch with library
#include<Button.h> #define buttonPin 2 #define ledPin 13 unsigned long blinkTime = millis(); Button B(HIGH); // LOW = milliseconds, HIGH = microseconds, default is LOW //======================================================================================== // //======================================================================================== void LED_ON() { digitalWrite(ledPin, HIGH); } void LED_OFF() { digitalWrite(ledPin, LOW); } void BLINK() { if (millis() - blinkTime >= 100) { blinkTime += 100; digitalWrite(ledPin, !digitalRead(ledPin)); } } //======================================================================================== void setup() { Serial.begin(115200); pinMode(ledPin, OUTPUT); pinMode(buttonPin, INPUT_PULLUP); // Set what the button will be when pressed (default is HIGH) // and set the hold time (default is 500) B.SetStateAndTime(LOW, 1000); B.onPressed(LED_ON); B.onHold(BLINK); B.onReleased(LED_OFF); } void loop() { byte myButton = B.checkButton(buttonPin); if (myButton) // if myButton is anything but 0, it is true { switch (myButton) { case PRESSED: Serial.print("Button was Pressed "); break; case HELD: Serial.print("Buttons is Held:"); break; case RELEASED: Serial.print("Button was Released "); break; default: break; } Serial.println(B.GetHeldTime(SECONDS)); } }