ok, hier ist die Klasse:
Code:
// Button Press Object
// (C) 2018 by dsyleixa
// This example code is in the public domain for private use.
// Use for professional or business purpose only by personal written permission
// by the author.
// history
// 0.0.8 new level 31 & debounce premature 2nd click
// 0.0.7 PCF + MCP pin-read (outline)
// 0.0.6 adjustable long press
// 0.0.5 adjustable dbl click speed, block press limit
// 0.0.4 constant long press intervall
// 0.0.3 long press= 6*short press
// ButtonClass.h
// ver 0.0.8
#ifndef __BTNCLASS__
#define __BTNCLASS__
#include <Arduino.h>
#define PCF_INPUT 8574
#define PCF_INPUT_PULLUP -8574
#define MCP_INPUT 23017
#define MCP_INPUT_PULLUP -23017
#define ANALOG_HIGH 900
#define ANALOG_LOW 100
#define ANALOG_50 50
#define ANALOG_100 100
#define ANALOG_200 200
#define ANALOG_300 300
#define ANALOG_400 400
#define ANALOG_500 500
#define ANALOG_600 600
#define ANALOG_700 700
#define ANALOG_800 800
#define ANALOG_900 900
#define ANALOG_1000 1000
class tButton {
//----------------------------------------------------------
protected:
int16_t pin;
int32_t mode;
uint32_t aktMillis, aktMillis2;
int8_t level,
dnstate, dnstate2, upstate,
btnstate, oldbtnstate;
uint32_t MINPRESSms, DBLCLICKms, LONGPRESSms, BLOCKPRESSms, DEBOUNCEms;
//-------------------------------------
int8_t dtimer() {
if (millis()-aktMillis >= LONGPRESSms) { // long press 400ms
return 3;
}
else
if (millis()-aktMillis >= MINPRESSms) {
return -1;
}
else
return 0;
}
//-------------------------------------
int8_t dtimer2() {
if (millis()-aktMillis2 >= BLOCKPRESSms) { // block press limit
return 2;
}
if (millis()-aktMillis2 >= DBLCLICKms) { // double click limit
return 1;
}
//else
return 0;
}
//-------------------------------------
int8_t readButton(int16_t _pin, int32_t _mode) {
if(_mode==INPUT) return digitalRead(_pin);
else
if(_mode==INPUT_PULLUP) return !digitalRead(_pin);
else
if(_mode==ANALOG_HIGH) return analogRead(_pin)>900;
else
if(_mode==ANALOG_LOW) return analogRead(_pin)<100;
else
if(_mode==ANALOG_50) return inRange(analogRead(_pin),50);
else
if(_mode==ANALOG_100) return inRange(analogRead(_pin),100);
else
if(_mode==ANALOG_200) return inRange(analogRead(_pin),200);
else
if(_mode==ANALOG_400) return inRange(analogRead(_pin),400);
else
if(_mode==ANALOG_800) return inRange(analogRead(_pin),800);
/*
else
if(_mode==PCF_INPUT) return !pcfRead(_pin);
else
if(_mode==PCF_INPUT_PULLUP) return !pcfRead(_pin);
else
if(_mode==MCP_INPUT) return !mcpRead(_pin);
else
if(_mode==MCP_INPUT_PULLUP) return !mcpRead(_pin);
*/
}
//----------------------------------------------------------
public:
tButton () :
pin(0xFF), aktMillis(0), aktMillis2(0),
MINPRESSms(40), // min duration for either button press
DBLCLICKms(150), // max priod between double click actions
LONGPRESSms(300), // min duration for long press
BLOCKPRESSms(200), // min wait duration after completed actions
DEBOUNCEms(20), // debounce time after btn press (idle, ignore)
mode(INPUT_PULLUP),
level(0), dnstate(0), dnstate2(0), upstate(0),
oldbtnstate(0), btnstate(0)
{ }
~tButton () { }
//-------------------------------------
void init(int16_t _pin, int32_t _mode, uint32_t _minpressms=40) {
pin = _pin;
mode = _mode;
MINPRESSms = _minpressms;
if(mode==INPUT || mode==INPUT_PULLUP) // Button at dig GPIO
{
pinMode(pin, mode);
}
else
if(mode==PCF_INPUT || mode==PCF_INPUT_PULLUP) // Button at PCF8574
{
// dummy
}
else
if(mode==MCP_INPUT || mode==MCP_INPUT_PULLUP) // Button at MCP23017
{
// dummy
}
}
//-------------------------------------
bool inRange(int val, int ref, int range=10 ) {
return( (val>ref-range)&&(val<ref+range) );
}
//-------------------------------------
void setclickdurations( uint32_t _minpressms,
uint32_t _dblclickms,
uint32_t _longpressms,
uint32_t _blockpressms )
{
MINPRESSms = _minpressms;
DBLCLICKms = _dblclickms;
LONGPRESSms = _longpressms;
BLOCKPRESSms = _blockpressms;
}
//-------------------------------------
int8_t click() { // returns 1(single), 2(double), 3(long), or 0(no press)
btnstate=readButton(pin, mode);
if(level==0) {
dnstate=0;
if(!oldbtnstate && btnstate) { // 1st new btn down:
aktMillis=millis(); // restart btn down timer
level=1;
return 0;
}
}
if(level==1) { // either btn stroke happened
//Serial.println("level1"); Serial.println(dnstate);
if(millis()-aktMillis <= DEBOUNCEms) { // debounce
return 0;
}
dnstate= dtimer(); // -1=short, 3=long pess
if(!btnstate){ // 1st btn up
if(dnstate){ // -1=short, 3=long pess
aktMillis2=millis();
if(dnstate==3) { // long press: finished !!
btnstate=0;
oldbtnstate=0;
dnstate=0;
aktMillis=millis();
aktMillis2=millis();
upstate=0;
level=4; // extra wait after long press
return 3;
}
else level=2; // short press: next level
}
}
}
if(level==2) { // short press happened
//Serial.println("level2"); Serial.println(dnstate);
upstate=dtimer2(); // check btn up pause
btnstate=readButton(pin, mode);
//Serial.print("upstate="); Serial.println(upstate);
if(btnstate) { // second btn click during pause: double click!
dnstate2=1;
//Serial.print(" dnstate2="); Serial.println(dnstate2);
}
if(upstate==0 && dnstate2) { // if double click: next level
level=3;
}
else
if(upstate>=1) { // dbl click time passed:
//Serial.println(millis()-aktMillis2); // single press finished !!
dnstate=0;
dnstate2=0;
//Serial.println(dnstate);
btnstate=0;
oldbtnstate=0;
level=4;
aktMillis=millis();
aktMillis2=millis();
upstate=0;
level=4; // extra wait after single press
return 1;
}
}
if(level==3) { // double click
if (btnstate) {
btnstate=readButton(pin, mode);
if (btnstate) level=31; // non-blocking while still pressed
return 0;
}
if (!btnstate) {
//Serial.println("level3");
dnstate=0; // double click finished !!
dnstate2=0;
upstate=0;
//Serial.println(dnstate);
oldbtnstate=0;
aktMillis=millis();
aktMillis2=millis();
level=4; // extra wait after double click
return 2;
}
}
if(level==4) { // BlockPress wait routine
upstate=dtimer2();
aktMillis=millis();
if(upstate>=2) {
level=0;
dnstate=0;
upstate=0;
aktMillis=millis();
aktMillis2=millis();
//Serial.println("level4 extra wait finished");
}
}
if(level==31) { // double click, still pressed
btnstate=readButton(pin, mode);
if (!btnstate) {
level=3;
return 0;
}
oldbtnstate=btnstate;
return 0;
}
oldbtnstate=btnstate;
return 0;
};
//-------------------------------------
int8_t state() { // returns 1(single), 2(double), 3(long), or 0(no press)
return click(); // alias
}
};
#endif
hier ist ein example:
Code:
// Button Press Lib Testcode
// (C) 2018 by dsyleixa
// This example code is in the public domain for private use.
// Use for professional or business purpose only by personal written permission
// by the author.
#include <ButtonClass.h>
tButton btn1;
tButton btn2;
void setup() {
Serial.begin(115200);
delay(2000);
pinMode(13, OUTPUT); // debug
Serial.println("Serial started\n");
btn1.init(4, INPUT_PULLUP); // <<< adjust
btn2.init(5, INPUT_PULLUP); // <<< adjust
}
//------------------------------------------------------------------------
void loop() {
int8_t btn;
btn=btn1.click();
if(btn) {
Serial.print("btn1.click()=");
Serial.println(btn);
}
btn=btn2.click();
if(btn) {
Serial.print("btn2.click()=");
Serial.println(btn);
}
// delay(10); // debug
}
den Teil für Analog-, MCP23017- und PCF8574-Buttonpads kannst du streichen, dazu kommen wir später
- - - Aktualisiert - - -
ach ja,
und hier eine Beschreibung:
Code:
# Arduino
ButtonClass tButton
Instances: e.g.
tButton mybtn;
// and perhaps more:
tButton mybtn1;
tButton mybtn2;
// etc
Init:
mybtn.init(pin_number, INPUT/INPUT_PULLUP)
- or -
mybtn.init(pin_number, INPUT/INPUT_PULLUP, min_press_ms)
(for INPUT_PULLUP mode, the press action is inverted automatically)
(min_press_ms default: 60ms)
to retrieve/refresh button click states:
call repeatedly
mybtn.click()
alias: mybtn.state()
it returns a int8_t value 0, 1, 2, or 3:
0: not pressed
1: 1 short click (default minimum duration = 60ms)
2: double click = 2 quick short clicks (default: within <= 150ms)
3: a long press (minimum duration= 300ms)
Lesezeichen