/*****************************************************************
Manuel Córdoba Ramos
En este ejercicio se debe diseñar una Máquina de Mealy que cumpla
los siguientes requisitos:
- Partiendo de un estado inicial, si se pulsa el botón:
- <1s se enciende el led
- >1s comienza a parpadear el led
- Cuando se pulse el botón volverá al estado inicial, con el led apagado
En este ejemplo se usa únicmante la librería Ticker
La lógica soltando botones en ocasiones es más fácil
*******************************************************************/
#include <Ticker.h>
Ticker timerParpadeo;
Ticker timerButton;
#define pinLed 18
#define pinButton 26
volatile int state;
volatile bool bPulsado;
volatile bool bEstaPulsado;
volatile bool bSuelto;
volatile bool bPulsadoLargo;
void IRAM_ATTR ISR_Button(void) {
if (digitalRead(pinButton) == 0) {
bPulsado = true;
} else {
bSuelto = true;
}
}
void PulsacionLarga(void) {
bPulsadoLargo = true;
timerButton.detach();
}
void ResetFlags(void) {
bPulsado = false;
bSuelto = false;
bPulsadoLargo = false;
bEstaPulsado = false;
}
void ConmutaLed(void) {
digitalWrite(pinLed, !digitalRead(pinLed));
}
void ToState1(void) {
Serial.print("State: ");
Serial.println(String(state));
digitalWrite(pinLed, HIGH);
ResetFlags();
}
void ToState2(void) {
Serial.print("State: ");
Serial.println(String(state));
timerParpadeo.attach(0.5, ConmutaLed);
ResetFlags();
}
void FromState1_ToState0(void) {
Serial.print("State: ");
Serial.println(String(state));
digitalWrite(pinLed, LOW);
ResetFlags();
}
void FromState2_ToState0(void) {
Serial.print("State: ");
Serial.println(String(state));
timerParpadeo.detach();
digitalWrite(pinLed, LOW);
ResetFlags();
}
void setup() {
Serial.begin(115200);
Serial.println("Hello, ESP32!");
// Configuración I/O
pinMode(pinLed, OUTPUT);
pinMode(pinButton, INPUT_PULLUP);
// Interrupciones
attachInterrupt(digitalPinToInterrupt(pinButton), &ISR_Button, CHANGE);
// Inicialización de variables
state = 0;
ResetFlags();
}
void loop() {
switch (state) {
case 0:
if (bPulsado) {
bPulsado = false;
bEstaPulsado = true;
timerButton.attach(1, PulsacionLarga);
}
if (bSuelto) {
bSuelto = false;
bEstaPulsado = false;
if (bPulsadoLargo) {
state = 2;
ToState2();
} else {
timerButton.detach();
state = 1;
ToState1();
}
}
break;
case 1:
if (bSuelto) {
bSuelto = false;
state = 0;
FromState1_ToState0();
}
break;
case 2:
if (bSuelto) {
bSuelto = false;
state = 0;
FromState2_ToState0();
}
break;
default:
break;
}
delay(10); // this speeds up the simulation
}