I was using the Buttons Library from the playground at Arduino Playground - Buttons and I noticed by looking through the code that it currently supports Pull Up buttons (connected to vcc) only. I made a few changes to the header and source which add the function setHigh(boolean) and modified the button checking routine to call a new function that checks if the state is high or low and whether setHigh is true or false.
Anyway, hope it helps someone - trying to learn C++ with all the rest of it!
buttons.h
/*
* buttons.h
* One-shot and hold functions for buttons.
* Created by Franky on 29/01/09.
* Licensed under LGPL (free to modify and use as you wish)
*/
#include <inttypes.h>
#define OneShot 0
#define Memory 1
#define Timer 2
#define OneShotTimer 3
#define MemoryTimer 4
#define ON 1
#define OFF 0
#define Pressed 2
#define Released 3
#define Hold 4
typedef uint8_t byte;
class Button {
public:
Button();
Button(byte type);
void assign(byte pin);
byte check();
byte check(byte mode_v);
// Setters
void setMode(byte type_v);
void setTimer(unsigned int t);
void setRefresh(unsigned int r);
void turnOnPullUp();
void turnOffPullUp();
void setHigh(bool h);
bool read_button_pin(byte pin);
private:
byte pin;
byte mode;
unsigned long hold_timer;
unsigned long refresh_timer;
unsigned int hold_level;
unsigned int hold_refresh;
bool previous;
bool set_high;
};
/*
Button modes:
- OneShot: OneShot only, returns 2 values (ON/OFF)
- Memory: Returns (Pressed/ON/Released/OFF)
- Timer: Hold System (OFF/ON/Hold)
- OneShotTimer: Combi OneShot & Timer (ON/Hold/OFF)
- MemoryTimer: Combi Memory & Timer
(Pressed/ON/Hold/Released/OFF)
*/
buttons.cpp
/*
* buttons.cpp
* One-shot and hold functions for buttons.
* Created by Franky on 29/01/09.
* Licensed under LGPL (free to modify and use as you wish)
*/
#include "WConstants.h"
#include "buttons.h"
Button::Button() {
previous = false;
mode = OneShot;
hold_timer = millis();
refresh_timer = millis();
hold_level = 1000; // 1 second
hold_refresh = 100; // 100 ms
pin = 0;
}
Button::Button(byte mode_v) {
previous = false;
mode = mode_v;
hold_timer = millis();
refresh_timer = millis();
hold_level = 1000;
hold_refresh = 100;
pin = 0;
}
void Button::assign(byte pin_v) {
pin = pin_v;
pinMode(pin, INPUT);
}
void Button::turnOnPullUp() { if (pin) digitalWrite(pin, HIGH); }
void Button::turnOffPullUp() { if (pin) digitalWrite(pin, LOW); }
// Setters
void Button::setMode(byte mode_v) { mode = mode_v; }
void Button::setTimer(unsigned int t) { if (mode > Memory) hold_level = (unsigned long)t; }
void Button::setRefresh(unsigned int r) { hold_refresh = r; }
void Button::setHigh(bool h) {set_high = h;}
byte Button::check(byte mode_v) {
byte mem = mode;
mode = mode_v;
byte res = check();
mode = mem;
return res;
}
bool Button::read_button_pin(byte pin){
if ((digitalRead(pin) && set_high) || (!digitalRead(pin) && !set_high)) {
return true;
}
else
{
return false;
}
}
byte Button::check() {
if (read_button_pin(pin)) {
switch (mode) {
case OneShot:
if (previous) {
return OFF;
}
else {
previous = true;
return ON;
}
break;
case Memory:
if (previous) {
return ON;
}
else {
previous = true;
return Pressed;
}
break;
case Timer:
if (previous) {
// Is treshold reached?
if (millis() > hold_timer+hold_level) {
if (millis() > refresh_timer+hold_refresh) {
refresh_timer = millis();
return Hold;
}
else return OFF;
}
else {
return ON;
}
}
else {
previous = true;
hold_timer = millis();
refresh_timer = millis();
return ON;
}
break;
case OneShotTimer:
if (previous) {
// Is treshold reached?
if (millis() > hold_timer+hold_level) {
if (millis() > refresh_timer+hold_refresh) {
refresh_timer = millis();
return Hold;
}
else return OFF;
}
else {
return OFF;
}
}
else {
previous = true;
hold_timer = millis();
refresh_timer = millis();
return ON;
}
break;
case MemoryTimer:
if (previous) {
// Is treshold reached?
if (millis() > hold_timer+hold_level) {
if (millis() > refresh_timer+hold_refresh) {
refresh_timer = millis();
return Hold;
}
else return OFF;
}
else {
return ON;
}
}
else {
previous = true;
hold_timer = millis();
refresh_timer = millis();
return Pressed;
}
break;
default:
break;
}
}
else {
if (previous && (mode == 1 || mode == 4)) {
previous = false;
return Released;
}
previous = false;
hold_timer = millis();
refresh_timer = millis();
return OFF;
}
return OFF;
}