#include <LiquidCrystal_I2C.h>
#define I2C_ADDR 0x27
#define LCD_COLUMNS 20
#define LCD_LINES 4
#define btn_act 18 //boton de activo
#define btn_man 5 //boton de manual
#define btn_auto 16 //boton de automatico
#define btnAL 19 //boton de alarma
#define led_azul 26 //led de desarmada
#define led_verde 27 //led de maquina armada
#define led_amarillo 14 //led de funcionamiento
#define led_alarma 25 //led de alarma
#define BUZZER_PIN 4 //pin del buzzer
#define NOTE_C5 523
volatile bool btn_act_pressed = false;
volatile bool btn_man_pressed = false;
volatile bool btn_auto_pressed = false;
volatile bool btnAL_pressed = false;
int state = 0; //estado en el que se empieza
LiquidCrystal_I2C lcd(I2C_ADDR, LCD_COLUMNS, LCD_LINES);
TaskHandle_t HandleTask1; //handle de la tarea 1
TaskHandle_t HandleTask2; //handle de la tarea 2
//callbacks de los botones
void IRAM_ATTR btn_act_pulsado(){
btn_act_pressed = true;
}
void IRAM_ATTR btn_man_pulsado(){
btn_man_pressed = true;
}
void IRAM_ATTR btn_auto_pulsado(){
btn_auto_pressed = true;
}
void IRAM_ATTR btnAL_pulsado(){
btnAL_pressed = true;
}
void setup() {
Serial.begin(115200);
// Init
lcd.init();
lcd.backlight();
lcd.setCursor(3, 0);
lcd.print("Tren Parado");
lcd.setCursor(2, 1);
lcd.print("Inactivo");
pinMode(btn_act, INPUT_PULLUP);
pinMode(btn_man, INPUT_PULLUP);
pinMode(btn_auto, INPUT_PULLUP);
pinMode(btnAL, INPUT_PULLUP);
pinMode(led_azul, OUTPUT);
pinMode(led_verde, OUTPUT);
pinMode(led_amarillo, OUTPUT);
pinMode(led_alarma, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
//INTERRUPCIONES DE LOS BOTONES
attachInterrupt(digitalPinToInterrupt(btn_act),btn_act_pulsado, RISING);
attachInterrupt(digitalPinToInterrupt(btn_man),btn_man_pulsado, RISING);
attachInterrupt(digitalPinToInterrupt(btn_auto),btn_auto_pulsado, RISING);
attachInterrupt(digitalPinToInterrupt(btnAL),btnAL_pulsado, RISING);
// Configuración inicial para estado 0 (INACTIVO)
digitalWrite(led_azul, HIGH);
digitalWrite(led_verde, LOW);
digitalWrite(led_amarillo, LOW);
digitalWrite(led_alarma, LOW);
xTaskCreatePinnedToCore(
estados, // Function en la que se implementa la tarea
"Tarea que controla los estados", // Nombre de la tarea
10000, // Memoria (en Bytes) asignados a esta tarea
NULL, // Parámetro de entrada de la tarea (no hay ningún parámetro)
0, // Prioridad de la tarea (cuanto más alto, más prioridad)
&HandleTask1, // Handle de la tarea 1
0); // Core donde va a correr la tarea 1
xTaskCreatePinnedToCore(
alerta, // Function en la que se implementa la tarea
"Tarea que controla la alarma", // Nombre de la tarea
10000, // Memoria (en Bytes) asignados a esta tarea
NULL, // Parámetro de entrada de la tarea (no hay ningún parámetro)
2, // Prioridad de la tarea (cuanto más alto, más prioridad)
&HandleTask2, // Handle de la tarea 1
1); // Core donde va a correr la tarea 1
}
void loop() {
Serial.println(state);
delay(10); // this speeds up the simulation
}
void estados(void *parameter){
while(1){
vTaskDelay(500 / portTICK_PERIOD_MS); // Espera 500ms para alcanzar 2Hz
switch(state){
case 0:
lcd.setCursor(3, 0);
lcd.print("Tren Parado");
lcd.setCursor(2, 1);
lcd.print("Inactivo"); //INACTIVO PARADO
if(btn_act_pressed == true){
digitalWrite(led_azul, LOW);
digitalWrite(led_verde, HIGH);
lcd.clear();
lcd.setCursor(3, 0);
lcd.print("Tren Parado");
lcd.setCursor(2, 1);
lcd.print("Activo");
state = 1; //pasa a activo
btn_act_pressed = false;
}
break;
case 1: //ACTIVO PARADO
if(btn_man_pressed == true){
lcd.clear();
lcd.setCursor(3, 0);
lcd.print("Tren Estado");
lcd.setCursor(2, 1);
lcd.print("Manual");
state = 2; //pasa a manual
digitalWrite(led_azul, HIGH);
digitalWrite(led_verde, HIGH);
btn_man_pressed = false;
}
else if(btn_act_pressed == true){
lcd.clear();
lcd.setCursor(3, 0);
lcd.print("Tren Parado");
lcd.setCursor(2, 1);
lcd.print("Inactivo");
state = 0; // Pasa a inactivo
digitalWrite(led_azul, HIGH);
digitalWrite(led_verde, LOW);
btn_act_pressed = false;
}
break;
case 2: //MANUAL
if(btn_auto_pressed == true){
lcd.clear();
lcd.setCursor(3, 0);
lcd.print("Tren en Modo");
lcd.setCursor(2, 1);
lcd.print("Automatico");
state = 3; //pasa a automatico
digitalWrite(led_azul, LOW);
digitalWrite(led_verde, LOW);
digitalWrite(led_amarillo, HIGH);
btn_auto_pressed = false;
}
else if(btn_act_pressed){
lcd.clear();
lcd.setCursor(3, 0);
lcd.print("Tren Parado");
lcd.setCursor(2, 1);
lcd.print("Activo");
state = 1; // Pasa a activo
digitalWrite(led_azul, LOW);
digitalWrite(led_verde, HIGH);
digitalWrite(led_amarillo, LOW);
btn_act_pressed = false;
}
break;
case 3: //AUTOMATICO
if(btn_man_pressed == true){
lcd.clear();
lcd.setCursor(3, 0);
lcd.print("Tren en Modo");
lcd.setCursor(2, 1);
lcd.print("Manual");
state = 2; //pasa a manual
digitalWrite(led_azul, HIGH);
digitalWrite(led_verde, HIGH);
digitalWrite(led_amarillo, LOW);
btn_man_pressed = false;
}
}
break;
}
}
void alerta(void *parameter){
while(1){
vTaskDelay(200 / portTICK_PERIOD_MS); // Espera 200ms para alcanzar 5Hz
if(btnAL_pressed){
state = 2; //devuelve al estado manual porque no puede estar en automatico
digitalWrite(led_alarma, !digitalRead(led_alarma));
digitalWrite(led_amarillo, LOW);
lcd.clear();
tone(BUZZER_PIN, NOTE_C5); //activa el buzzer
lcd.setCursor(3, 0);
lcd.print("ALERTA!!");
lcd.setCursor(2, 1);
lcd.print("Modo Manual Activado");
btnAL_pressed = false;
}
else{
digitalWrite(led_alarma, LOW);
noTone(BUZZER_PIN);
}
}
}