/* BLOCK COMMENT
ATTENTION: This Sketch contains elements of C++.
https://www.learncpp.com/cpp-tutorial/
Many thanks to LarryD
https://europe1.discourse-cdn.com/arduino/original/4X/7/e/0/7e0ee1e51f1df32e30893550c85f0dd33244fb0e.jpeg
https://forum.arduino.cc/t/changing-button-states-from-momentary-to-latch/993706
Tested with Arduino: Mega[ ] - UNO [X] - Nano [ ]
Copied from https://forum.arduino.cc/t/changing-button-states-from-momentary-to-latch/993706/20?u=davex
*/
#define ProjectName "Changing button states from momentary to latch"
// HARDWARE AND TIMER SETTINGS
// YOU MAY NEED TO CHANGE THESE CONSTANTS TO YOUR HARDWARE AND NEEDS
#define OutPutTest
constexpr unsigned long OutPutTestTime {1000};
// VARIABLE DECLARATION AND DEFINITION
unsigned long currentTime;
enum {Stop, Start, Blink};
struct TIMER { // has the following members
unsigned long duration; // memory for interval time
unsigned long stamp; // memory for actual time
int onOff; // control for stop/start/blink
};
// data struct for button handler -----------
enum ButtonStatus {Released, Pressed};
enum Action {NoneLatch, Latch};
struct BUTTONOUTPUT { // has the following members
byte buttonPin; // port number for button
byte outputPin; // port number for output
bool action; // action either latch or none latch
TIMER scan; // timer for button debouncing
int statusQuo; // current button state
};
BUTTONOUTPUT buttonOutputs[] {
{A0, 2, NoneLatch, 20, 0, Blink, false},
{A1, 3, NoneLatch, 20, 0, Blink, false},
{A2, 4, Latch, 20, 0, Blink, false},
};
// time handler ------------------------------------------------------
bool timerEvent (TIMER &timer) {
bool reTurn = currentTime - timer.stamp >= timer.duration && timer.onOff;
if (reTurn) timer.onOff == Blink ? timer.stamp = currentTime : timer.onOff = Stop;
return reTurn;
}
// -------------------------------------------------------------------
void setup() {
Serial.begin(115200);
Serial.println(F("."));
Serial.print(F("File : ")), Serial.println(__FILE__);
Serial.print(F("Date : ")), Serial.println(__DATE__);
Serial.print(F("Project: ")), Serial.println(ProjectName);
pinMode (LED_BUILTIN, OUTPUT); // used as heartbeat indicator
// https://www.learncpp.com/cpp-tutorial/for-each-loops/
for (auto buttonOutput : buttonOutputs) pinMode(buttonOutput.buttonPin, INPUT_PULLUP);
for (auto buttonOutput : buttonOutputs) pinMode(buttonOutput.outputPin, OUTPUT);
#ifdef OutPutTest
// check outputs
Serial.print("Output test... ");
for (auto buttonOutput : buttonOutputs) digitalWrite(buttonOutput.outputPin, HIGH), delay(OutPutTestTime);
for (auto buttonOutput : buttonOutputs) digitalWrite(buttonOutput.outputPin, LOW), delay(OutPutTestTime);
Serial.println("Complete.");
#endif
}
void loop () {
currentTime = millis();
digitalWrite(LED_BUILTIN, (currentTime / 500) % 2);
// get access to the structured array
for (auto &buttonOutput : buttonOutputs) {
// check debounce time
if (timerEvent (buttonOutput.scan)) {
// check current button state. Attention: pinMode=INPUT_PULLUP
int stateNew = !digitalRead(buttonOutput.buttonPin);
// check button state change
if (buttonOutput.statusQuo != stateNew) {
// save new state
Serial.print(buttonOutput.outputPin);
buttonOutput.statusQuo = stateNew;
// take action what shall happens to the different states and desired function
switch (stateNew) {
case Pressed:
switch (buttonOutput.action) {
case Latch:
Serial.print("toggle");
digitalWrite(buttonOutput.outputPin, !digitalRead(buttonOutput.outputPin));
break;
case NoneLatch:
Serial.print("on");
digitalWrite(buttonOutput.outputPin, HIGH);
break;
}
break;
case Released:
switch (buttonOutput.action) {
case Latch:
Serial.print("released");
break;
case NoneLatch:
digitalWrite(buttonOutput.outputPin, LOW);
Serial.print("off");
break;
}
break;
}
Serial.println();
}
}
}
}