/*
Signal zählen 3x in 3s zum schalten
by noiasca
2024-05-18 class Button to debounce
*/
#include <Streaming.h> // Streaming by Peter Polidoro (librarymanager) - macht das Serial.print einfacher.
// simple debounce of a button
class Button { // a simple class for buttons based on the "Debounce" example
const uint8_t buttonPin; // the GPIO / pin for the button
static constexpr byte debounceDelay = 30; // the debounce time; Static because we only need one value for all buttons
const bool active; // is the pin active HIGH or active LOW (will also activate the pullups!)
bool lastButtonState = HIGH; // the previous reading from the input pin
uint32_t lastDebounceTime = 0; // the last time the output pin was toggled
public:
/**
\brief constructor for a button
The constructor takes the GPIO as parameter.
If you omit the second parameter, the library will activate the internal pullup resistor
and the button should connect to GND.
If you set the second parameter to HIGH, the button is active HIGH.
The button should connect to VCC.
The internal pullups will not be used but you will need an external pulldown resistor.
\param buttonPin the GPIO for the button
\param active LOW (default) - if button connects to GND, HIGH if button connects to VCC
*/
Button(uint8_t buttonPin, bool active = LOW) : buttonPin(buttonPin), active(active) {}
/**
\brief set the pin to the proper state
Call this function in your setup().
The pinMode will be set according to your constructor.
*/
void begin() {
if (active == LOW)
pinMode(buttonPin, INPUT_PULLUP);
else
pinMode(buttonPin, INPUT);
}
/**
\brief indicate if button was pressed since last call
@return HIGH if button was pressed since last call - debounce
*/
bool wasPressed() {
bool buttonState = LOW; // the current reading from the input pin
byte reading = LOW; // "translated" state of button LOW = released, HIGH = pressed, despite the electrical state of the input pint
if (digitalRead(buttonPin) == active) reading = HIGH; // if we are using INPUT_PULLUP we are checking invers to LOW Pin
if ((millis() - lastDebounceTime) > debounceDelay) { // If the switch changed, AFTER any pressing or noise
if (reading != lastButtonState && lastButtonState == LOW) { // If there was a change and and last state was LOW (= released)
buttonState = HIGH;
}
lastDebounceTime = millis();
lastButtonState = reading;
}
return buttonState;
}
};
class Input {
Button input; // debounce the input with a common button class
uint32_t previousMillis = 0; // time management
uint8_t counter = 0; // how often was the button pressed
const uint16_t interval = 3000; // periode of
const uint8_t maxPress = 3; // how often do you need to press the button
public:
Input(uint8_t buttonPin, bool active = LOW) : input(buttonPin, active) {}
void begin() {
input.begin();
}
bool tripplePress(uint32_t currentMillis = millis()) {
if (currentMillis - previousMillis >= interval) {
counter = 0; // reset
}
if (input.wasPressed()) {
if (counter == 0) {
previousMillis = currentMillis; // remember first press
}
if (++counter >= maxPress) {
Serial << "fire" << endl;
counter = 0;
return true;
}
}
return false;
}
};
class Pulse { // a simple class for buttons based on the "Debounce" example
const uint8_t outputPin; // the GPIO / pin
const uint16_t interval = 500; // the debounce time; Static because we only need one value for all buttons
uint8_t state; // state / restbeeps
uint32_t previousMillis = 0; // Time management
const uint8_t active = HIGH; // high active;
const uint8_t inactive = LOW; // state for inactive;
public:
Pulse (uint8_t outputPin) : outputPin(outputPin) {}
void begin() {
pinMode(outputPin, OUTPUT);
}
void set (uint8_t pulses) {
state = pulses;
digitalWrite(outputPin, HIGH);
previousMillis = millis();
}
void update(uint32_t currentMillis = millis()) {
if (state) {
if (currentMillis - previousMillis > interval) {
previousMillis = currentMillis;
if (digitalRead(outputPin) == active) {
digitalWrite(outputPin, inactive);
state--;
}
else
digitalWrite(outputPin, active);
}
}
}
};
Input input(A0); // the input/ break
Pulse horn(11); // output to honk the horn
constexpr uint8_t outputPin{2};
enum State {IDLE, REVERSE} state;
void setup() {
Serial.begin(115200);
Serial << "Activate/deactivate after 3 presses\n";
delay(500);
input.begin();
horn.begin();
pinMode (outputPin, OUTPUT);
}
void loop() {
switch (state) {
case IDLE :
if (input.tripplePress()) {
digitalWrite(outputPin, HIGH);
horn.set(1); // einmal hupen
state = REVERSE;
}
break;
case REVERSE :
if (input.tripplePress()) {
digitalWrite(outputPin, LOW);
horn.set(2); // zweimal hupen
state = IDLE;
}
break;
}
horn.update(); // needs to be called to trigger the horn
}
//