#include <LiquidCrystal_I2C.h>
#define I2C_addr 0x27
#define columnsLCD 20
#define rowsLCD 4
LiquidCrystal_I2C lcd(I2C_addr, columnsLCD, rowsLCD);
#define ledPin1 4
#define ledPin2 16
#define ledPin3 17
#define button1 33
#define button2 25
#define button3 26
#define buttonrst 14
#define ESTADO_0 0
#define ESTADO_1 1
#define ESTADO_2 2
#define ESTADO_3 3
volatile int state = ESTADO_0;
volatile int counter = 0;
volatile int counter1 = 0;
volatile bool b1_interrupted = false;
volatile bool b1_pressed = false;
volatile bool b2_interrupted = false;
volatile bool b2_pressed = false;
volatile bool b3_interrupted = false;
volatile bool b3_pressed = false;
volatile bool rst_pressed = false;
volatile bool timer0_interrupted = false;
volatile bool timer1_interrupted = false;
volatile bool long_pressed = false;
volatile bool ok = false; // Variable de fin de cuenta del parpadeo
volatile bool once = false;
hw_timer_t *timer0 = NULL;
hw_timer_t *timer1 = NULL;
void IRAM_ATTR button_1_ISR() {
b1_interrupted = true;
b1_pressed = !b1_pressed; // Cambiar estado al detectar cambio
}
void IRAM_ATTR button_2_ISR() {
b2_interrupted = true;
b2_pressed = !b2_pressed;
}
void IRAM_ATTR button_3_ISR() {
b3_interrupted = true;
b3_pressed = !b3_pressed;
}
void IRAM_ATTR button_rst_ISR() {
rst_pressed = true;
resetVariables();
}
void IRAM_ATTR timer_count() {
timer0_interrupted = true;
}
void IRAM_ATTR timer_blink() {
timer1_interrupted = true;
}
void resetVariables() {
counter = 0;
long_pressed = false;
ok = false;
timer0_interrupted = false;
timer1_interrupted = false;
b1_interrupted = false;
b2_interrupted = false;
timerAlarmDisable(timer1);
timerAlarmDisable(timer0);
once = false;
}
void escribirLCD(String text) {
int maxLength = columnsLCD; // Limitar el texto al tamaño máximo de la pantalla
if (text.length() > maxLength) {
text = text.substring(0, maxLength); // Cortar el texto si excede el tamaño
}
lcd.clear();
lcd.setCursor(0, 0); // Empezamos desde la primera columna de la primera fila
lcd.print(text); // Escribimos el texto en la LCD
}
void FineStateMachine() {
switch (state) {
case ESTADO_0:
if (!once) {
escribirLCD("Pulse el primer boton");
once = true;
}
if (b1_interrupted) {
counter = 0;
b1_interrupted = false;
if (b1_pressed) {
Serial.println("Boton 1, presionado. Timer 0 arrancado");
timerRestart(timer0);
timerAlarmEnable(timer0);
} else {
Serial.println("Boton 1, soltado. Timer 0 parado");
timerAlarmDisable(timer0);
if (!long_pressed) {
Serial.println("Pulsacion corta, parpadea 3 veces y estado 1");
timerRestart(timer1);
timerAlarmEnable(timer1);
} else {
Serial.println("Pulsacion larga, parpadea 3 veces y, reset a estado 0");
timerRestart(timer1);
timerAlarmEnable(timer1);
}
}
}
if (timer0_interrupted) {
Serial.println("Es larga");
long_pressed = true;
timer0_interrupted = false;
}
if (timer1_interrupted) {
counter++;
if (counter < 6) {
digitalWrite(ledPin1, !digitalRead(ledPin1));
} else {
counter = 0;
ok = true;
timerAlarmDisable(timer1);
}
timer1_interrupted = false;
}
if (ok && !long_pressed) {
state = ESTADO_1;
digitalWrite(ledPin1, HIGH);
Serial.println("Siguiente estado -> 1");
once = true;
escribirLCD("Boton 1 correcto");
resetVariables();
}
if (ok && long_pressed) {
state = ESTADO_0;
digitalWrite(ledPin1, LOW);
digitalWrite(ledPin2, LOW);
digitalWrite(ledPin3, LOW);
Serial.println("Siguiente estado -> 0");
once = true;
escribirLCD("Boton 1 incorrecto");
resetVariables();
}
break;
case ESTADO_1:
if (!once) {
escribirLCD("Pulse el segundo boton");
once = true;
}
if (b2_interrupted) {
counter = 0;
b2_interrupted = false;
if (b2_pressed) {
Serial.println("Boton 2, presionado. Timer 0 arrancado");
timerRestart(timer0);
timerAlarmEnable(timer0);
} else {
Serial.println("Boton 2, soltado. Timer 0 parado");
timerAlarmDisable(timer0);
if (long_pressed) {
Serial.println("Pulsacion larga, parpadea 3 veces y estado 2");
timerRestart(timer1);
timerAlarmEnable(timer1);
} else {
Serial.println("Pulsacion corta parpadea 3 veces y , reset a estado 0");
timerRestart(timer1);
timerAlarmEnable(timer1);
}
}
}
if (timer0_interrupted) {
long_pressed = true;
timer0_interrupted = false;
}
if (timer1_interrupted) {
counter++;
if (counter < 6) {
digitalWrite(ledPin2, !digitalRead(ledPin2));
} else {
counter = 0;
ok = true;
timerAlarmDisable(timer1);
}
timer1_interrupted = false;
}
if (ok && long_pressed) {
state = ESTADO_2;
digitalWrite(ledPin2, HIGH);
Serial.println("Siguiente estado -> 2");
ok = false;
once = true;
escribirLCD("Boton 2 correcto");
resetVariables();
}
if (ok && !long_pressed) {
state = ESTADO_0;
digitalWrite(ledPin1, LOW);
digitalWrite(ledPin2, LOW);
digitalWrite(ledPin3, LOW);
Serial.println("Siguiente estado -> 0");
once = true;
escribirLCD("Boton 2 incorrecto");
ok = false;
resetVariables();
}
break;
case ESTADO_2:
if (!once) {
escribirLCD("Pulse el tercer boton");
once = true;
}
if (b3_interrupted) {
counter = 0;
b3_interrupted = false;
if (b3_pressed) {
Serial.println("Boton 3, presionado. Timer 0 arrancado");
timerRestart(timer0);
timerAlarmEnable(timer0);
} else {
Serial.println("Boton 3, soltado. Timer 0 parado");
timerAlarmDisable(timer0);
if (!long_pressed) {
Serial.println("Pulsacion corta, parpadea 3 veces y estado 3");
timerRestart(timer1);
timerAlarmEnable(timer1);
} else {
Serial.println("Pulsacion larga, parpadea 3 veces y, reset a estado 0");
timerRestart(timer1);
timerAlarmEnable(timer1);
}
}
}
if (timer0_interrupted) {
long_pressed = true;
timer0_interrupted = false;
}
if (timer1_interrupted) {
counter++;
if (counter < 6) {
digitalWrite(ledPin3, !digitalRead(ledPin3));
} else {
counter = 0;
ok = true;
timerAlarmDisable(timer1);
}
timer1_interrupted = false;
}
if (ok && long_pressed) {
state = ESTADO_0;
digitalWrite(ledPin1, LOW);
digitalWrite(ledPin2, LOW);
digitalWrite(ledPin3, LOW);
Serial.println("Siguiente estado -> 0");
once = true;
escribirLCD("Boton 3 incorrecto");
resetVariables();
}
if (ok && !long_pressed) {
digitalWrite(ledPin1, HIGH);
digitalWrite(ledPin2, HIGH);
digitalWrite(ledPin3, HIGH);
state = ESTADO_3;
Serial.println("Siguiente estado -> 3");
once = false;
escribirLCD("Boton 3 correcto");
once = false;
resetVariables();
timerRestart(timer1);
timerAlarmEnable(timer1);
}
break;
case ESTADO_3:
if (!once) {
escribirLCD("JUEGO COMPLETADO");
once = true;
}
if (timer1_interrupted) {
digitalWrite(ledPin1, !digitalRead(ledPin1));
digitalWrite(ledPin2, !digitalRead(ledPin2));
digitalWrite(ledPin3, !digitalRead(ledPin3));
timer1_interrupted = false;
}
if (rst_pressed) {
rst_pressed = false;
state = ESTADO_0;
Serial.println("FINAL, CODIGO CORRECTO. ESTADO 0");
digitalWrite(ledPin1, LOW);
digitalWrite(ledPin2, LOW);
digitalWrite(ledPin3, LOW);
resetVariables();
once = false;
}
break;
}
}
void setup() {
Serial.begin(9600);
// Configurar pines de botones y LEDs
pinMode(button1, INPUT_PULLUP);
pinMode(button2, INPUT_PULLUP);
pinMode(button3, INPUT_PULLUP);
pinMode(buttonrst, INPUT_PULLUP);
pinMode(ledPin1, OUTPUT);
pinMode(ledPin2, OUTPUT);
pinMode(ledPin3, OUTPUT);
// Configurar interrupciones
attachInterrupt(digitalPinToInterrupt(button1), button_1_ISR, CHANGE);
attachInterrupt(digitalPinToInterrupt(button2), button_2_ISR, CHANGE);
attachInterrupt(digitalPinToInterrupt(button3), button_3_ISR, CHANGE);
attachInterrupt(digitalPinToInterrupt(buttonrst), button_rst_ISR, FALLING);
// Configurar temporizador
timer0 = timerBegin(0, 80, true);
timerAttachInterrupt(timer0, &timer_count, true);
timerAlarmWrite(timer0, 1000000, true); // Aviso cada 1s
timer1 = timerBegin(1, 80, true);
timerAttachInterrupt(timer1, &timer_blink, true);
timerAlarmWrite(timer1, 500000, true); // Aviso cada 0.5s
//LCD
lcd.init();
lcd.backlight();
//Iniciialización
digitalWrite(ledPin1, LOW);
digitalWrite(ledPin2, LOW);
digitalWrite(ledPin3, LOW);
lcd.clear();
lcd.print("Empieza el juego");
}
void loop() {
FineStateMachine();
delay(10); // Pequeña espera para evitar rebotes
}