Initial commit
rodzic
cd86d94617
commit
622e00990f
|
@ -0,0 +1,126 @@
|
|||
/**
|
||||
* ESP32 Morse decoder using trained machine learning model
|
||||
*/
|
||||
|
||||
// DEFINES
|
||||
// IS_TRAINING should be defined when gathering training data
|
||||
// Otherwise, comment out to use the model to classify inputs
|
||||
// #define IS_TRAINING
|
||||
|
||||
// INCLUDES
|
||||
// See https://github.com/LennartHennigs/Button2
|
||||
#include "src/Button2.h"
|
||||
// Uncomment when doing classification
|
||||
#ifndef IS_TRAINING
|
||||
#include "model.h"
|
||||
#endif
|
||||
|
||||
// CONSTANTS
|
||||
// This pin will be used to read dots and dashes - could be connected to any digital input that can be sustained - e.g. a mic, light sensor, or button
|
||||
const byte inputPin = 16;
|
||||
// This pin will be driven HIGH when input is being received
|
||||
const byte buzzerPin = 5;
|
||||
// This LED will light up when receiving character input
|
||||
const byte ledPin = 2;
|
||||
// Every letter can be represented by a maximum of four Morse dots/dashes (if including numbers, this needs to increase to five)
|
||||
const byte patternLength = 4;
|
||||
// The maximum allowed space between "dots" and "dashes" within the same character
|
||||
// If the time elapsed since last input was received exceeds this value, we'll move onto the next character
|
||||
const int intraCharacterPause = 800;
|
||||
|
||||
// GLOBALS
|
||||
// A button object
|
||||
Button2 button;
|
||||
// The duration of inputs received in the current pattern
|
||||
float pattern[patternLength];
|
||||
// The time at which the last input was received
|
||||
unsigned long lastReleaseTime;
|
||||
// Counter of how many elements have been received in the current pattern
|
||||
uint8_t counter;
|
||||
// If we're not training...
|
||||
#ifndef IS_TRAINING
|
||||
// Grab a reference to the model's classifier function exported from SciKit-Learn
|
||||
Eloquent::ML::Port::RandomForest classifier;
|
||||
#endif
|
||||
|
||||
void setup() {
|
||||
// Initialise serial monitor connection
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__ __DATE__);
|
||||
|
||||
// Initialise LED and buzzer pins used for user feedback
|
||||
pinMode(buzzerPin, OUTPUT);
|
||||
digitalWrite(buzzerPin, LOW);
|
||||
pinMode(ledPin, OUTPUT);
|
||||
digitalWrite(ledPin, LOW);
|
||||
|
||||
// Configure the button input
|
||||
// Anything less than 30ms we won't register as an input at all
|
||||
button.setDebounceTime(30);
|
||||
button.setPressedHandler(onButtonPress);
|
||||
button.setReleasedHandler(onButtonRelease);
|
||||
button.begin(inputPin);
|
||||
}
|
||||
|
||||
// Called when a complete character pattern has been received
|
||||
void onCharacterReceive() {
|
||||
|
||||
// If we're gathering training data
|
||||
#ifdef IS_TRAINING
|
||||
// Send the pattern input to the serial monitor
|
||||
for(int i=0; i<patternLength; i++) {
|
||||
Serial.print(pattern[i]);
|
||||
Serial.print(i==patternLength-1 ? '\n' : ',');
|
||||
}
|
||||
// If we're applying the classifier function
|
||||
#else
|
||||
// Send the model's prediction to the serial monitor
|
||||
Serial.println(classifier.predictLabel(pattern));
|
||||
#endif
|
||||
|
||||
// Reset the counter and pattern array
|
||||
counter = 0;
|
||||
memset(pattern, 0, sizeof(pattern));
|
||||
|
||||
// Turn LED off to show we have finished reading input
|
||||
digitalWrite(ledPin, LOW);
|
||||
}
|
||||
|
||||
// When any sort of input is received
|
||||
void onButtonPress(Button2& btn) {
|
||||
// Turn the LED on when we're recording input
|
||||
digitalWrite(ledPin, HIGH);
|
||||
// Make the buzzer sound
|
||||
digitalWrite(buzzerPin, HIGH);
|
||||
}
|
||||
|
||||
// When any sort of input ends
|
||||
void onButtonRelease(Button2& btn) {
|
||||
// Record how long the most recent input lasted for
|
||||
unsigned int duration = btn.wasPressedFor();
|
||||
// Store it in the pattern array
|
||||
pattern[counter] = duration;
|
||||
// Store the current time
|
||||
lastReleaseTime = millis();
|
||||
// Increment the index in the pattern array
|
||||
counter++;
|
||||
// If we've recorded the maximum number of dots/dashes, we know the input
|
||||
// must have ended
|
||||
if(counter == patternLength) {
|
||||
onCharacterReceive();
|
||||
}
|
||||
// Turn the buzzer off
|
||||
digitalWrite(buzzerPin, LOW);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Read button input
|
||||
button.loop();
|
||||
|
||||
// If we've received at least one dot/dash, but user is not currently inputting anything, and the time elapsed
|
||||
// since last input was released exceeds threshold
|
||||
if(!button.isPressed() && counter > 0 && millis() - lastReleaseTime > intraCharacterPause) {
|
||||
// Assume the character has ended
|
||||
onCharacterReceive();
|
||||
}
|
||||
}
|
Plik diff jest za duży
Load Diff
|
@ -0,0 +1,451 @@
|
|||
/////////////////////////////////////////////////////////////////
|
||||
/*
|
||||
Button2.cpp - Arduino Library to simplify working with buttons.
|
||||
Created by Lennart Hennigs.
|
||||
*/
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "Button2.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// initalize static counter
|
||||
|
||||
int Button2::_nextID = 0;
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// default contructor
|
||||
|
||||
Button2::Button2() {
|
||||
pin = UNDEFINED_PIN;
|
||||
id = _nextID++;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// contructor
|
||||
|
||||
Button2::Button2(byte attachTo, byte buttonMode /* = INPUT_PULLUP */, boolean activeLow /* = true */) {
|
||||
begin(attachTo, buttonMode, activeLow);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
void Button2::begin(byte attachTo, byte buttonMode /* = INPUT_PULLUP */, boolean activeLow /* = true */) {
|
||||
pin = attachTo;
|
||||
id = _nextID++;
|
||||
#ifndef _IGNORE_LONG
|
||||
longclick_detected_counter = 0;
|
||||
longclick_detected_retriggerable = false;
|
||||
#endif
|
||||
_pressedState = activeLow ? LOW : HIGH;
|
||||
if (attachTo != VIRTUAL_PIN) {
|
||||
pinMode(attachTo, buttonMode);
|
||||
}
|
||||
// state = activeLow ? HIGH : LOW;
|
||||
state = _getState();
|
||||
prev_state = state ;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
void Button2::setDebounceTime(unsigned int ms) {
|
||||
debounce_time_ms = ms;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
void Button2::setLongClickTime(unsigned int ms) {
|
||||
longclick_time_ms = ms;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
void Button2::setDoubleClickTime(unsigned int ms) {
|
||||
doubleclick_time_ms = ms;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
unsigned int Button2::getDebounceTime() const {
|
||||
return debounce_time_ms;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
unsigned int Button2::getLongClickTime() const {
|
||||
return longclick_time_ms;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
unsigned int Button2::getDoubleClickTime() const {
|
||||
return doubleclick_time_ms;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
byte Button2::getPin() const {
|
||||
return pin;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
void Button2::setButtonStateFunction(StateCallbackFunction f) {
|
||||
get_state_cb = f;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
bool Button2::operator == (Button2 &rhs) {
|
||||
return (this == &rhs);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
void Button2::setChangedHandler(CallbackFunction f) {
|
||||
change_cb = f;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
void Button2::setPressedHandler(CallbackFunction f) {
|
||||
pressed_cb = f;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
void Button2::setReleasedHandler(CallbackFunction f) {
|
||||
released_cb = f;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
void Button2::setClickHandler(CallbackFunction f) {
|
||||
click_cb = f;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
void Button2::setTapHandler(CallbackFunction f) {
|
||||
tap_cb = f;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _IGNORE_LONG
|
||||
void Button2::setLongClickHandler(CallbackFunction f) {
|
||||
long_cb = f;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
void Button2::setLongClickDetectedRetriggerable(bool retriggerable) {
|
||||
longclick_detected_retriggerable = retriggerable;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
void Button2::setLongClickDetectedHandler(CallbackFunction f) {
|
||||
longclick_detected_cb = f;
|
||||
}
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _IGNORE_DOUBLE
|
||||
void Button2::setDoubleClickHandler(CallbackFunction f) {
|
||||
double_cb = f;
|
||||
}
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _IGNORE_TRIPLE
|
||||
void Button2::setTripleClickHandler(CallbackFunction f) {
|
||||
triple_cb = f;
|
||||
}
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
unsigned int Button2::wasPressedFor() const {
|
||||
return down_time_ms;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
boolean Button2::isPressed() const {
|
||||
return (state == _pressedState);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
boolean Button2::isPressedRaw() {
|
||||
return (_getState() == _pressedState);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
byte Button2::getNumberOfClicks() const {
|
||||
return click_count;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
clickType Button2::getType() const {
|
||||
return last_click_type;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
int Button2::getID() const {
|
||||
return id;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
void Button2::setID(int newID) {
|
||||
id = newID;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
String Button2::clickToString(clickType type) const {
|
||||
if (type == single_click) return "click";
|
||||
#ifndef _IGNORE_LONG
|
||||
if (type == long_click) return "long click";
|
||||
#endif
|
||||
#ifndef _IGNORE_DOUBLE
|
||||
if (type == double_click) return "double click";
|
||||
#endif
|
||||
#ifndef _IGNORE_TRIPLE
|
||||
if (type == triple_click) return "triple click";
|
||||
#endif
|
||||
return "empty";
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
bool Button2::wasPressed() const {
|
||||
return was_pressed;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
clickType Button2::read(bool keepState /* = false */) {
|
||||
if (!keepState) {
|
||||
clickType res = last_click_type;
|
||||
last_click_type = empty;
|
||||
was_pressed = false;
|
||||
return res;
|
||||
}
|
||||
return last_click_type;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
clickType Button2::wait(bool keepState /* = false */) {
|
||||
while(!wasPressed()) {
|
||||
loop();
|
||||
}
|
||||
return read(keepState);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
void Button2::waitForClick(bool keepState /* = false */) {
|
||||
do {
|
||||
while(!wasPressed()) {
|
||||
loop();
|
||||
}
|
||||
} while(read() != single_click);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _IGNORE_DOUBLE
|
||||
void Button2::waitForDouble(bool keepState /* = false */) {
|
||||
do {
|
||||
while(!wasPressed()) {
|
||||
loop();
|
||||
}
|
||||
} while(read() != double_click);
|
||||
}
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _IGNORE_TRIPLE
|
||||
void Button2::waitForTriple(bool keepState /* = false */) {
|
||||
do {
|
||||
while(!wasPressed()) {
|
||||
loop();
|
||||
}
|
||||
} while(read() != triple_click);
|
||||
}
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _IGNORE_LONG
|
||||
void Button2::waitForLong(bool keepState /* = false */) {
|
||||
do {
|
||||
while(!wasPressed()) {
|
||||
loop();
|
||||
}
|
||||
} while(read() != long_click);
|
||||
}
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
byte Button2::_getState() const {
|
||||
if (get_state_cb != NULL) {
|
||||
return get_state_cb();
|
||||
} else {
|
||||
return digitalRead(pin);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
void Button2::loop() {
|
||||
if (pin != UNDEFINED_PIN) {
|
||||
unsigned long now = millis();
|
||||
prev_state = state;
|
||||
state = _getState();
|
||||
|
||||
// is button pressed?
|
||||
if (state == _pressedState) {
|
||||
// is it pressed now?
|
||||
if (prev_state != _pressedState) {
|
||||
down_ms = now;
|
||||
pressed_triggered = false;
|
||||
click_ms = down_ms;
|
||||
// trigger pressed event (after debounce has passed)
|
||||
} else if (!pressed_triggered && (now - down_ms >= debounce_time_ms)) {
|
||||
pressed_triggered = true;
|
||||
click_count++;
|
||||
if (change_cb != NULL) change_cb (*this);
|
||||
if (pressed_cb != NULL) pressed_cb (*this);
|
||||
}
|
||||
#ifndef _IGNORE_LONG
|
||||
// is a longpress detected callback defined?
|
||||
if (longclick_detected_cb != NULL) {
|
||||
// check to see that the longclick_ms period has been exceeded and call the appropriate callback
|
||||
bool longclick_period_detected = now - down_ms >= (longclick_time_ms * (longclick_detected_counter + 1));
|
||||
if (longclick_period_detected && !longclick_detected_reported) {
|
||||
longclick_detected_reported = true;
|
||||
longclick_detected = true;
|
||||
if (longclick_detected_retriggerable) {
|
||||
// increate the counter and reset the "reported" flag (as the counter will stop the false trigger)
|
||||
longclick_detected_counter++;
|
||||
longclick_detected_reported = false;
|
||||
}
|
||||
if (longclick_detected_cb != NULL) longclick_detected_cb(*this);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// is the button released?
|
||||
} else if (state != _pressedState) {
|
||||
// is it released right now?
|
||||
if (prev_state == _pressedState) {
|
||||
down_time_ms = now - down_ms;
|
||||
// is it beyond debounce time?
|
||||
if (down_time_ms >= debounce_time_ms) {
|
||||
last_click_type = single_click;
|
||||
// trigger release
|
||||
if (change_cb != NULL) change_cb (*this);
|
||||
if (released_cb != NULL) released_cb (*this);
|
||||
// trigger tap
|
||||
if (tap_cb != NULL) tap_cb (*this);
|
||||
#ifndef _IGNORE_LONG
|
||||
// was it a longclick? (preceeds single / double / triple clicks)
|
||||
if (down_time_ms >= longclick_time_ms) {
|
||||
longclick_detected = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
// is the button released and the time has passed for multiple clicks?
|
||||
} else if (now - click_ms > doubleclick_time_ms) {
|
||||
#ifndef _IGNORE_LONG
|
||||
// was there a longclick?
|
||||
if (longclick_detected) {
|
||||
// was it part of a combination?
|
||||
if (click_count == 1) {
|
||||
last_click_type = long_click;
|
||||
if (long_cb != NULL) long_cb (*this);
|
||||
was_pressed = true;
|
||||
}
|
||||
longclick_detected = false;
|
||||
longclick_detected_reported = false;
|
||||
longclick_detected_counter = 0;
|
||||
|
||||
// determine the number of single clicks
|
||||
} else if (click_count > 0) {
|
||||
#else
|
||||
// determine the number of single clicks
|
||||
if (click_count > 0) {
|
||||
#endif
|
||||
switch (click_count) {
|
||||
case 1:
|
||||
last_click_type = single_click;
|
||||
if (click_cb != NULL) click_cb (*this);
|
||||
break;
|
||||
#ifndef _IGNORE_DOUBLE
|
||||
#ifdef _IGNORE_TRIPLE // all multi-clicks are now identified as double
|
||||
default:
|
||||
#else
|
||||
case 2:
|
||||
#endif
|
||||
last_click_type = double_click;
|
||||
if (double_cb != NULL) double_cb (*this);
|
||||
break;
|
||||
#endif
|
||||
#ifndef _IGNORE_TRIPLE
|
||||
case 3:
|
||||
last_click_type = triple_click;
|
||||
if (triple_cb != NULL) triple_cb (*this);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
was_pressed = true;
|
||||
}
|
||||
// clean up
|
||||
click_count = 0;
|
||||
click_ms = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
void Button2::reset() {
|
||||
pin = UNDEFINED_PIN;
|
||||
click_count = 0;
|
||||
last_click_type = empty;
|
||||
down_time_ms = 0;
|
||||
pressed_triggered = false;
|
||||
#ifndef _IGNORE_LONG
|
||||
longclick_detected = false;
|
||||
longclick_detected_reported = false;
|
||||
longclick_detected_counter = 0;
|
||||
#endif
|
||||
pressed_cb = NULL;
|
||||
released_cb = NULL;
|
||||
change_cb = NULL;
|
||||
tap_cb = NULL;
|
||||
click_cb = NULL;
|
||||
#ifndef _IGNORE_LONG
|
||||
long_cb = NULL;
|
||||
longclick_detected_cb = NULL;
|
||||
#endif
|
||||
#ifndef _IGNORE_DOUBLE
|
||||
double_cb = NULL;
|
||||
#endif
|
||||
#ifndef _IGNORE_TRIPLE
|
||||
triple_cb = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,190 @@
|
|||
/////////////////////////////////////////////////////////////////
|
||||
/*
|
||||
Button2.h - Arduino Library to simplify working with buttons.
|
||||
Created by Lennart Hennigs.
|
||||
*/
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef Button2_h
|
||||
#define Button2_h
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// uncommenting one of these compiler switches will remove the
|
||||
// code for one of these click types
|
||||
|
||||
// #define _IGNORE_DOUBLE
|
||||
// #define _IGNORE_TRIPLE
|
||||
// #define _IGNORE_LONG
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(ARDUINO_ARCH_ESP32) || defined(ESP8266)
|
||||
#include <functional>
|
||||
#endif
|
||||
#include <Arduino.h>
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef _IGNORE_DOUBLE
|
||||
#pragma message "Not compiling double click code"
|
||||
#endif
|
||||
#ifdef _IGNORE_TRIPLE
|
||||
#pragma message "Not compiling triple click code"
|
||||
#endif
|
||||
#ifdef _IGNORE_LONG
|
||||
#pragma message "Not compiling long click code"
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
#define DEBOUNCE_MS 50
|
||||
#define LONGCLICK_MS 200
|
||||
#define DOUBLECLICK_MS 300
|
||||
|
||||
#define UNDEFINED_PIN 255
|
||||
#define VIRTUAL_PIN 254
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
enum clickType {
|
||||
single_click,
|
||||
#ifndef _IGNORE_DOUBLE
|
||||
double_click,
|
||||
#endif
|
||||
#ifndef _IGNORE_TRIPLE
|
||||
triple_click,
|
||||
#endif
|
||||
#ifndef _IGNORE_LONG
|
||||
long_click,
|
||||
#endif
|
||||
empty
|
||||
};
|
||||
|
||||
class Button2 {
|
||||
|
||||
protected:
|
||||
int id;
|
||||
byte pin;
|
||||
byte state;
|
||||
byte prev_state;
|
||||
byte click_count = 0;
|
||||
clickType last_click_type = empty;
|
||||
bool was_pressed = false;
|
||||
unsigned long click_ms;
|
||||
unsigned long down_ms;
|
||||
|
||||
#ifndef _IGNORE_LONG
|
||||
bool longclick_detected_retriggerable;
|
||||
uint16_t longclick_detected_counter = 0;
|
||||
bool longclick_detected = false;
|
||||
bool longclick_detected_reported = false;
|
||||
#endif
|
||||
|
||||
unsigned int debounce_time_ms = DEBOUNCE_MS;
|
||||
unsigned int longclick_time_ms = LONGCLICK_MS;
|
||||
unsigned int doubleclick_time_ms = DOUBLECLICK_MS;
|
||||
|
||||
unsigned int down_time_ms = 0;
|
||||
bool pressed_triggered = false;
|
||||
|
||||
#if defined(ARDUINO_ARCH_ESP32) || defined(ESP8266)
|
||||
typedef std::function<void(Button2 &btn)> CallbackFunction;
|
||||
typedef std::function<byte()> StateCallbackFunction;
|
||||
#else
|
||||
typedef void (*CallbackFunction)(Button2 &);
|
||||
typedef byte (*StateCallbackFunction)();
|
||||
#endif
|
||||
|
||||
StateCallbackFunction get_state_cb = NULL;
|
||||
|
||||
CallbackFunction pressed_cb = NULL;
|
||||
CallbackFunction released_cb = NULL;
|
||||
CallbackFunction change_cb = NULL;
|
||||
CallbackFunction tap_cb = NULL;
|
||||
CallbackFunction click_cb = NULL;
|
||||
#ifndef _IGNORE_LONG
|
||||
CallbackFunction long_cb = NULL;
|
||||
CallbackFunction longclick_detected_cb = NULL;
|
||||
#endif
|
||||
#ifndef _IGNORE_DOUBLE
|
||||
CallbackFunction double_cb = NULL;
|
||||
#endif
|
||||
#ifndef _IGNORE_TRIPLE
|
||||
CallbackFunction triple_cb = NULL;
|
||||
#endif
|
||||
|
||||
public:
|
||||
Button2();
|
||||
Button2(byte attachTo, byte buttonMode = INPUT_PULLUP, boolean activeLow = true);
|
||||
|
||||
void begin(byte attachTo, byte buttonMode = INPUT_PULLUP, boolean activeLow = true);
|
||||
|
||||
void setDebounceTime(unsigned int ms);
|
||||
void setLongClickTime(unsigned int ms);
|
||||
void setDoubleClickTime(unsigned int ms);
|
||||
|
||||
unsigned int getDebounceTime() const;
|
||||
unsigned int getLongClickTime() const;
|
||||
unsigned int getDoubleClickTime() const;
|
||||
byte getPin() const;
|
||||
|
||||
void reset();
|
||||
|
||||
void setButtonStateFunction(StateCallbackFunction f);
|
||||
|
||||
void setChangedHandler(CallbackFunction f);
|
||||
void setPressedHandler(CallbackFunction f);
|
||||
void setReleasedHandler(CallbackFunction f);
|
||||
|
||||
void setTapHandler(CallbackFunction f);
|
||||
void setClickHandler(CallbackFunction f);
|
||||
#ifndef _IGNORE_DOUBLE
|
||||
void setDoubleClickHandler(CallbackFunction f);
|
||||
#endif
|
||||
#ifndef _IGNORE_TRIPLE
|
||||
void setTripleClickHandler(CallbackFunction f);
|
||||
#endif
|
||||
#ifndef _IGNORE_LONG
|
||||
void setLongClickHandler(CallbackFunction f);
|
||||
void setLongClickDetectedHandler(CallbackFunction f);
|
||||
void setLongClickDetectedRetriggerable(bool retriggerable);
|
||||
#endif
|
||||
unsigned int wasPressedFor() const;
|
||||
boolean isPressed() const;
|
||||
boolean isPressedRaw();
|
||||
|
||||
bool wasPressed() const;
|
||||
clickType read(bool keepState = false);
|
||||
clickType wait(bool keepState = false);
|
||||
void waitForClick(bool keepState = false);
|
||||
#ifndef _IGNORE_DOUBLE
|
||||
void waitForDouble(bool keepState = false);
|
||||
#endif
|
||||
#ifndef _IGNORE_TRIPLE
|
||||
void waitForTriple(bool keepState = false);
|
||||
#endif
|
||||
#ifndef _IGNORE_LONG
|
||||
void waitForLong(bool keepState = false);
|
||||
#endif
|
||||
byte getNumberOfClicks() const;
|
||||
clickType getType() const;
|
||||
String clickToString(clickType type) const;
|
||||
|
||||
int getID() const;
|
||||
void setID(int newID);
|
||||
|
||||
bool operator == (Button2 &rhs);
|
||||
|
||||
void loop();
|
||||
|
||||
private:
|
||||
static int _nextID;
|
||||
byte _pressedState;
|
||||
|
||||
byte _getState() const;
|
||||
};
|
||||
/////////////////////////////////////////////////////////////////
|
||||
#endif
|
||||
/////////////////////////////////////////////////////////////////
|
Ładowanie…
Reference in New Issue