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)







Zitieren

Lesezeichen