#define B1 34
#define B2 35
#define B3 32
#define R 33
#define L1 16
#define L2 4
#define L3 0
// Variable para seleccionar LED
uint8_t LED_PIN = L1;
// Constante de número de blinks. Tener en cuenta que un blink es apagado y encendido. 6 blinks significa que el LED parpadea 3 veces
const uint8_t numberOfBlinks = 6;
// Variable para indicar si se está parpadeando
bool blinking = false;
// Variable para indicar si el botón pulsado es correcto
bool correct_button = false;
hw_timer_t *timer1 = NULL;
hw_timer_t *timer2 = NULL;
volatile bool B1_released = false;
volatile bool B2_pressed = false;
volatile bool B2_released = false;
volatile bool B3_released = false;
volatile bool reset_code = false;
volatile bool timer1_activated;
volatile uint8_t fsm_state = 0;
volatile bool long_pressed=false;
volatile uint8_t timer1_interrupt_counter = 0; // Variable volátil para contar cuántas veces se produce la interrupción por timer 1
volatile uint8_t timer2_interrupt_counter = 0; // Variable volátil para contar los segundos que está pulsado el botón
void IRAM_ATTR timer1Interrupt(){
timer1_interrupt_counter++;
timer1_activated=true;
}
void IRAM_ATTR timer2Interrupt(){
if(timer2_interrupt_counter >=1){
long_pressed= true;
timer2_interrupt_counter++;
}
}
void IRAM_ATTR B1Released(){
Serial.println("B1 pulsado");
B1_released = true;
}
void IRAM_ATTR B2Released(){
B2_pressed = !B2_pressed;
if(B2_pressed){
Serial.println("B2 pulsado");
Serial.println("Contando tiempo que está pulsado");
timerAlarmEnable(timer2);
}
else{
Serial.println("B2 soltado");
B2_released = true;
timerAlarmDisable(timer2);
Serial.println("Dejo de contar");
timer2_interrupt_counter=0;
}
}
void IRAM_ATTR B3Released(){
Serial.println("B3 pulsado");
B3_released = true;
}
void IRAM_ATTR RReleased(){
Serial.println("Reset pulsado");
reset_code = true;
}
void setup() {
Serial.begin(115200);
pinMode(B1, INPUT_PULLUP);
pinMode(B2, INPUT_PULLUP);
pinMode(B3, INPUT_PULLUP);
pinMode(R, INPUT_PULLUP);
pinMode(L1, OUTPUT);
pinMode(L2, OUTPUT);
pinMode(L3, OUTPUT);
attachInterrupt(digitalPinToInterrupt(B1),B1Released,FALLING);
attachInterrupt(digitalPinToInterrupt(B2),B2Released,CHANGE);
attachInterrupt(digitalPinToInterrupt(B3),B3Released,FALLING);
attachInterrupt(digitalPinToInterrupt(R),RReleased,FALLING);
// Inicializar el timer 1
// Parámetro 1: Timer que queremos usar. El ESP32 tiene 4 timers => valores válidos 0,1,2,3
// Parámetro 2: Prescaler. El reloj por defecto del ESP32 va a 80MHz. Si ponemos 80, dividimos el reloj por 80, dándonos 1 000 000 ticks/s
// Parámetro 3: true indica que el timer empieza en ON, false sería OFF
timer1 = timerBegin(0, 80, true); // Timer 0, divisor de reloj 80
timerAttachInterrupt(timer1, &timer1Interrupt, true); // Adjuntar la función de manejo de interrupción
timerAlarmWrite(timer1, 5e5, true); // Interrupción cada 500 ms (500 ON, 500 OFF)
// Inicializar el timer 2
// Parámetro 1: Timer que queremos usar. El ESP32 tiene 4 timers => valores válidos 0,1,2,3
// Parámetro 2: Prescaler. El reloj por defecto del ESP32 va a 80MHz. Si ponemos 80, dividimos el reloj por 80, dándonos 1 000 000 ticks/s
// Parámetro 3: true indica que el timer empieza en ON, false sería OFF
timer2 = timerBegin(1, 80, true); // Timer 0, divisor de reloj 80
timerAttachInterrupt(timer2, &timer2Interrupt, true); // Adjuntar la función de manejo de interrupción
timerAlarmWrite(timer2, 1e6, true); // Interrupción cada 500 ms (500 ON, 500 OFF)
}
void loop() {
if(reset_code){
Serial.println("Reseteando codigo");
fsm_state=0;
Serial.println(fsm_state);
B1_released = false;
B2_pressed = false;
B2_released = false;
B3_released = false;
reset_code = false;
long_pressed= false;
digitalWrite(L1, LOW);
digitalWrite(L2, LOW);
digitalWrite(L3, LOW);
timer1_activated = false;
timerAlarmDisable(timer1);
timerAlarmDisable(timer2);
timer1_interrupt_counter = 0;
timer2_interrupt_counter = 0;
}
if(!blinking){
if(B1_released || B2_released || B3_released ){
timer1_activated = true;
timerAlarmEnable(timer1);
blinking=true;
}
switch(fsm_state){
case 0:
LED_PIN = L1;
if(B1_released && !B2_released && !B3_released){
B1_released = false;
correct_button = true;
}
else{
correct_button = false;
}
break;
case 1:
LED_PIN = L2;
if(!B1_released && B2_released && !B3_released && long_pressed){
B2_released = false;
long_pressed = false;
correct_button = true;
}
else{
correct_button = false;
}
break;
case 2:
LED_PIN = L3;
if(!B1_released && !B2_released && B3_released){
B3_released = false;
correct_button = true;
}
else{
correct_button = false;
}
break;
}
}
if(timer1_activated){
if(timer1_interrupt_counter < numberOfBlinks){
digitalWrite(LED_PIN,!digitalRead(LED_PIN));
}
else if(timer1_interrupt_counter == numberOfBlinks){
timer1_interrupt_counter = 0;
timerAlarmDisable(timer1);
blinking = false;
if(correct_button){
Serial.println("Boton correcto");
fsm_state++;
Serial.println(fsm_state);
digitalWrite(LED_PIN, HIGH);
}
else{
Serial.println("Boton incorrecto");
reset_code = true;
}
}
timer1_activated = false;
}
if(fsm_state==3){
timer1_activated=true;
timerAlarmEnable(timer1);
while(!reset_code){
if(timer1_activated){
digitalWrite(L1, !digitalRead(L1));
digitalWrite(L2, !digitalRead(L2));
digitalWrite(L3, !digitalRead(L3));
timer1_activated = false;
}
}
}
delay(100); // this speeds up the simulation
}