You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I wanted the debounce and longpress capability that I enjoy from Button2 library but my input was a samd21 touch sensor. Might also have other inputs such as analog threshold or buttons on i2c IO expander. If we could set a custom _getState() handler and get around the check for valid pin in Button2::loop() then buttons that are not on digitalRead would be possible and a more generic way than the esp touch button implementation. I was able to do it by changing _getState() to virtual and derived class as follows, but it was extra work and I don't like changing libraries and having a bunch of notes about that in my code. Here's what I got that might give you ideas on a better way:
#pragma once
#ifndef Button2cb_h
#define Button2cb_h
#if defined(ARDUINO_ARCH_ESP32) || defined(ESP8266)
#include
#endif
#include "Arduino.h"
#include <Button2.h>
#define VIRTUAL_PIN 254
typedef byte (*ButtonStateCallbackFunction)(void); class Button2cb : public Button2 {
protected:
ButtonStateCallbackFunction getState_cb = NULL;
public:
void begin(boolean activeLow = true);
boolean isPressedRaw() const;
void setGetStateHandler(ButtonStateCallbackFunction f);
private: // note, to properly override this in the base class, it has to be made virtual in Button2.h byte _getState();
};
/////////////////////////////////////////////////////////////////
/*
Button2cb.cpp /
/////////////////////////////////////////////////////////////////
#include "Button2cb.h"
void Button2cb::begin(boolean activeLow / = true */)
{ pin = VIRTUAL_PIN; // this gets us past loop()'s (pin != UNDEFINED_PIN) check
longclick_detected_retriggerable = false;
_pressedState = activeLow ? LOW : HIGH;
setDebounceTime(DEBOUNCE_MS);
setLongClickTime(LONGCLICK_MS);
setDoubleClickTime(DOUBLECLICK_MS); // this constructor allows us to get around setting pinMode on our VIRTUAL_PIN
state = _getState();
prev_state = state;
} void Button2cb::setGetStateHandler(ButtonStateCallbackFunction f) {
getState_cb = f;
}
boolean Button2cb::isPressedRaw() const { // another digitalRead to work around
if(getState_cb != NULL)
return (getState_cb() == _pressedState);
return false;
}
/////////////////////////////////////////////////////////////////
// note, to properly override this in the base class, it has to be made virtual in Button2.h
byte Button2cb::_getState() {
if(getState_cb != NULL)
{
return getState_cb(); // use our installed callback function to get the virtual pin's state
}
return 0;
}
/////////////////// Now with the new class, I can use the following
Button2cb DebouncerQtColorChange; // callback function to read our samd21 qTouch via the measure() function to get the analog value of the touch peripheral
byte ButtonQtColorGetState()
{ return (ButtonQtColorChange.measure() > QtThreshold) ? LOW : HIGH;
}
void setup()
{
DebouncerQtColorChange.begin(); // Button2 subclass DebouncerQtColorChange.setGetStateHandler(ButtonQtColorGetState); // set my custom way to _getState()
DebouncerQtColorChange.setClickHandler(AnimationColorShiftButtonHandler);
DebouncerQtColorChange.setLongClickHandler(AnimationColorShiftButtonHandler);
}
The text was updated successfully, but these errors were encountered:
Hey,
thank you for the suggestion.
Yes, I understand your request and problem. And that's a nice idea.
Give me some time to think about it how to best implement and handle this inside the lib.
Hey,
thought about your suggestion a bit.
I think some people might be not too familiar with inheritance when they are into Arduino programming.
Thus I'd like to introduce something like this:
a function that allows you to set a custom getState() function, this eliminates the need for inheritance
refactored up the code, to there is only digitalRead() used in _getState()
kept the VIRTUAL_PIN to skip the pin setup in my begin() function
In the example below I use a regular button pin but I think it makes the idea clear
the only thing that is now not encapsulated is the initialization of the "custom button", here the pinMode(39, INPUT_PULLUP); but I feel that is ok
I wanted the debounce and longpress capability that I enjoy from Button2 library but my input was a samd21 touch sensor. Might also have other inputs such as analog threshold or buttons on i2c IO expander. If we could set a custom _getState() handler and get around the check for valid pin in Button2::loop() then buttons that are not on digitalRead would be possible and a more generic way than the esp touch button implementation. I was able to do it by changing _getState() to virtual and derived class as follows, but it was extra work and I don't like changing libraries and having a bunch of notes about that in my code. Here's what I got that might give you ideas on a better way:
#pragma once
#ifndef Button2cb_h
#define Button2cb_h
#if defined(ARDUINO_ARCH_ESP32) || defined(ESP8266)
#include
#endif
#include "Arduino.h"
#include <Button2.h>
#define VIRTUAL_PIN 254
typedef byte (*ButtonStateCallbackFunction)(void);
class Button2cb : public Button2 {
protected:
ButtonStateCallbackFunction getState_cb = NULL;
public:
void begin(boolean activeLow = true);
boolean isPressedRaw() const;
void setGetStateHandler(ButtonStateCallbackFunction f);
private:
// note, to properly override this in the base class, it has to be made virtual in Button2.h
byte _getState();
};
/////////////////////////////////////////////////////////////////
/*
Button2cb.cpp
/
/////////////////////////////////////////////////////////////////
#include "Button2cb.h"
void Button2cb::begin(boolean activeLow / = true */)
{
pin = VIRTUAL_PIN; // this gets us past loop()'s (pin != UNDEFINED_PIN) check
longclick_detected_retriggerable = false;
_pressedState = activeLow ? LOW : HIGH;
setDebounceTime(DEBOUNCE_MS);
setLongClickTime(LONGCLICK_MS);
setDoubleClickTime(DOUBLECLICK_MS);
// this constructor allows us to get around setting pinMode on our VIRTUAL_PIN
state = _getState();
prev_state = state;
}
void Button2cb::setGetStateHandler(ButtonStateCallbackFunction f) {
getState_cb = f;
}
boolean Button2cb::isPressedRaw() const { // another digitalRead to work around
if(getState_cb != NULL)
return (getState_cb() == _pressedState);
return false;
}
/////////////////////////////////////////////////////////////////
// note, to properly override this in the base class, it has to be made virtual in Button2.h
byte Button2cb::_getState() {
if(getState_cb != NULL)
{
return getState_cb(); // use our installed callback function to get the virtual pin's state
}
return 0;
}
/////////////////// Now with the new class, I can use the following
Button2cb DebouncerQtColorChange;
// callback function to read our samd21 qTouch via the measure() function to get the analog value of the touch peripheral
byte ButtonQtColorGetState()
{
return (ButtonQtColorChange.measure() > QtThreshold) ? LOW : HIGH;
}
void setup()
{
DebouncerQtColorChange.begin(); // Button2 subclass
DebouncerQtColorChange.setGetStateHandler(ButtonQtColorGetState); // set my custom way to _getState()
DebouncerQtColorChange.setClickHandler(AnimationColorShiftButtonHandler);
DebouncerQtColorChange.setLongClickHandler(AnimationColorShiftButtonHandler);
}
The text was updated successfully, but these errors were encountered: