/************************************
ESRTRUCTURA FSM CON PULSACIONES LARGAS Y CORTAS
*********************************/
/********DEF PINES********/
#define LED_PIN 26 // LED conectado a GPIO26
#define BUTTON_PIN 14 // BUTTON conectado a GPIO14
/********DEF PUNTEROS TIMERS********/
hw_timer_t *timer0 = NULL; // Puntero al timer0 del hardware
hw_timer_t *timer1 = NULL; // Puntero al timer1 del hardware
/********DEF VARIABLES********/
volatile uint8_t interrupt_counter = 0; // Variable volátil para contar cuántas veces se produce la interrupción
volatile uint8_t fsm_state = 0; // Variable volátil para almacenar el estado de la FSM
volatile bool long_pressed = false; // Variable volátil para detectar cuándo se ha presionado
volatile bool button_pressed = false; // Variable volátil que almacena el estado del botón (true = pulsado)
volatile bool button_interrupted = false; // Variable volátil que indica si el botón se ha interrumpido o no
volatile bool timer0_interrupted = false; // Variable volátil que indica si ha habido una interrupción del timer0
volatile bool timer1_interrupted = false; // Variable volátil que indica si ha habido una interrupción del timer1
int timer_frequency = 1000000; // Frecuencia del timer en Hz (como de rápido cuenta el timer). Igual para los dos timers
/********DEF INTERRUPCIONES********/
// Callback ISR botón cambia de estado (se pulsa o se suelta)
void IRAM_ATTR buttonStateChange()
{
button_interrupted = true; // Se ha interrumpido el botón
button_pressed = !button_pressed; // Almaceno el cambio de estado del botón
}
// Callback ISR interrupción del timer 0
void IRAM_ATTR timer0Interrupt()
{
timer0_interrupted = true; // Se ha interrumpido el timer 0
}
// Callback ISR interrupción del timer 1
void IRAM_ATTR timer1Interrupt()
{
timer1_interrupted = true; // Se ha interrumpido el timer 1
}
/********DEF FUNCIONES AUXILIARES********/
void resetFlags() {
}
/********DEF FUNCIONES DE ESTADO********/
void functionState0()
{
if (button_interrupted) {
if (button_pressed) { // Si está pulsado
timerStart(timer1); // Activo el timer1 para que empiece a contar el tiempo
timer1_interrupted = false; // Lo pongo a false para que no cuente la primera interrupción al activar el timer
} else { // Si no está pulsado
if (!long_pressed) // Presionado menos de 1s
{
StateTo1();
}
else // Presionado más de 1s
{
StateTo2();
}
timerRestart(timer1);
timerStop(timer1); // Desactivo el timer1 para dejar de contar tiempo presionado
Serial.println("Counting time OFF");
long_pressed = false; // Se pone a FALSE la variable booleana que indica que la pulsación ha sido larga
}
button_interrupted = false;
}
if (timer1_interrupted) { // Si se interrumpe el timer1
long_pressed = true; // Se pone a TRUE la variable booleana que indica que la pulsación ha sido larga
Serial.println("Pulsación larga");
timer1_interrupted = false;
}
}
void functionState1()
{
if (button_interrupted) {
if (button_pressed) { // Si está pulsado
timerStart(timer1); // Activo el timer1 para que empiece a contar el tiempo
timer1_interrupted = false; // Lo pongo a false para que no cuente la primera interrupción al activar el timer
} else { // Si no está pulsado
if (!long_pressed) // Presionado menos de 1s
{
StateTo1();
}
else // Presionado más de 1s
{
StateTo2();
}
timerRestart(timer1);
timerStop(timer1); // Desactivo el timer1 para dejar de contar tiempo presionado
Serial.println("Counting time OFF");
long_pressed = false; // Se pone a FALSE la variable booleana que indica que la pulsación ha sido larga
}
button_interrupted = false;
}
if (timer1_interrupted) { // Si se interrumpe el timer1
long_pressed = true; // Se pone a TRUE la variable booleana que indica que la pulsación ha sido larga
Serial.println("Pulsación larga");
timer1_interrupted = false;
}
}
void functionState2()
{
if (button_interrupted && !button_pressed) {// Si se suelta el botón
StateTo0();
long_pressed = false; // Poner a FALSE la variable long_pressed
button_interrupted = false;
}
}
/********DEF FUNCIONES DE PASO DE ESTADO********/
void StateTo0() {
resetFlags();
}
void StateTo1() {
resetFlags();
}
void StateTo2() {
resetFlags();
}
// Función setup
void setup()
{
Serial.begin(115200);
// Establecer modos de los GPIO digitales del LED y BUTTON
pinMode(LED_PIN, OUTPUT);
pinMode(BUTTON_PIN, INPUT_PULLUP);
// Inicializar interrupción por pulsación del botón
attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), buttonStateChange, CHANGE); // Flanco de bajada = botón se presiona
// Inicializar el timer0
timer0 = timerBegin(timer_frequency); // Inicializar el timer que contará a la frecuencia timer_frequency
timerAttachInterrupt(timer0, &timer0Interrupt); // Adjuntar la función de manejo de interrupción
// Establecer la alarma del timer0 (parámetro 1) para que llame a timerInterrupt cada medio segundo (parámetro 2 - valor en microsegundos)
// Poner a true que se repita la alarma (parámetro 3) y lo haga de forma indefinida (parámetro 4 - 0=indefinido)
timerAlarm(timer0, 5e5, true, 0);
timerStop(timer0); // El timer empezará cuando se pase al estado 2 (parpadear)
// Inicializar el timer1
timer1 = timerBegin(timer_frequency); // Inicializar el timer que contará a la frecuencia timer_frequency
timerAttachInterrupt(timer1, &timer1Interrupt); // Adjuntar la función de manejo de interrupción
// Establecer la alarma del timer1 (parámetro 1) para que llame a timerInterrupt cada medio segundo (parámetro 2 - valor en microsegundos)
// Poner a true que se repita la alarma (parámetro 3) y lo haga de forma indefinida (parámetro 4 - 0=indefinido)
timerAlarm(timer1, 1e6, true, 0);
timerStop(timer1); // El timer empezará cuando se pulse el botón (acabará cuando se suelte)
// Empezamos con el LED apagado
digitalWrite(LED_PIN, LOW);
}
// Función loop
void loop()
{
switch (fsm_state) {
case 0:
functionState0();
break;
case 1:
functionState1();
break;
case 2:
functionState2();
break;
}
delay(10);
}