/*****************************************************************
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 NO se usa la librería Ticker
La lógica soltando botones en ocasiones es más fácil
*******************************************************************/
hw_timer_t *timerButton = NULL;
hw_timer_t *timerParpadeo = NULL;
#define pinLed 18
#define pinButton 26
#define tiempoParpadeo (0.5)*1e6
volatile int state;
volatile bool bPulsado;
volatile bool bSuelto;
volatile bool ledDebeConmutar;
unsigned long tiempoPulsado;
void IRAM_ATTR ISR_Button(void) {
if (digitalRead(pinButton) == 0) {
bPulsado = true;
} else {
bSuelto = true;
}
}
void ResetFlags(void) {
bPulsado = false;
bSuelto = false;
ledDebeConmutar = false;
}
void IRAM_ATTR ConmutaLed(void) {
ledDebeConmutar = true;
}
void ToState1(void) {
Serial.print("State: ");
Serial.println(String(state));
digitalWrite(pinLed, HIGH);
ResetFlags();
}
void ToState2(void) {
Serial.print("State: ");
Serial.println(String(state));
timerRestart(timerParpadeo);
timerStart(timerParpadeo);
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));
timerStop(timerParpadeo);
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);
// Timers
// Este timer no necesito interrupciones, pues no las pongo
timerButton = timerBegin(0, 80, true); // Se pone directamente la frecuencia en Hz
timerStop(timerButton); // Para el timer
timerParpadeo = timerBegin(1, 80, true); // Elijo canales distintos
timerAttachInterrupt(timerParpadeo, &ConmutaLed, true);
timerAlarmWrite(timerParpadeo, tiempoParpadeo, true);
timerAlarmEnable(timerParpadeo);
timerStop(timerParpadeo); // Para el timer
// Inicialización de variables
state = 0;
ResetFlags();
}
void loop() {
switch (state) {
case 0:
if (bPulsado) {
bPulsado = false;
Serial.println("Botón pulsado!");
Serial.println("Contando tiempo!");
timerRestart(timerButton);
timerStart(timerButton);
}
if (bSuelto) {
bSuelto = false;
tiempoPulsado = timerReadMilis(timerButton);
Serial.print("Tiempo pulsado (ms): ");
Serial.println(String(tiempoPulsado));
if (tiempoPulsado > 1000) {
state = 2;
ToState2();
} else {
state = 1;
ToState1();
}
timerStop(timerButton);
}
break;
case 1:
if (bSuelto) {
bSuelto = false;
state = 0;
FromState1_ToState0();
}
break;
case 2:
if (bSuelto) {
bSuelto = false;
state = 0;
FromState2_ToState0();
}
if (ledDebeConmutar) {
ledDebeConmutar = false;
digitalWrite(pinLed, !digitalRead(pinLed));
}
break;
default:
break;
}
delay(10); // this speeds up the simulation
}