#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
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
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);
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);
//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);
digitalWrite(led_alarma, LOW);
xTaskCreatePinnedToCore(
estados, // Function en la que se implementa la tarea
"Tarea que controla los estados", // Nombre de la tarea
100000, // 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
100000, // Memoria (en Bytes) asignados a esta tarea
NULL, // Parámetro de entrada de la tarea (no hay ningún parámetro)
5, // 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){
switch(state){
case 0: //INACTIVO PARADO
if(btn_act_pressed == true){
digitalWrite(led_azul, LOW);
digitalWrite(led_verde, HIGH);
state = 1; //pasa a activo
btn_act_pressed = false;
}
break;
case 1: //ACTIVO PARADO
if(btn_man_pressed == true){
state = 2; //pasa a manual
digitalWrite(led_azul, HIGH);
digitalWrite(led_verde, HIGH);
btn_man_pressed = false;
}
else if(btn_act_pressed == true){
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){
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){
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){
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){
digitalRead(led_amarillo);
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);
btnAL_pressed = false;
}
else{
digitalWrite(led_alarma, LOW);
}
}
}
Diseñar y programar la Interfaz Hombre-Máquina (HMI) del puesto de conductor/a de un vagón de metro.
La interfaz estará basada en un microcontrolador ESP32 y deberá asegurar la ejecución de varias tareas en tiempo real.
Como mínimo1, la interfaz deberá realizar las siguientes tareas (ya sea de forma concurrente o paralela):
Gestión del estado del tren: Esta tarea deberá ejecutarse, al menos, con una frecuencia de 2Hz y tendrá prioridad baja. El tren podrá encontrarse en cualquiera de los siguientes estados
Parada inactivo. El tren está parado e inactivo. Desde este estado sólo se podrá pasar a activo si el conductor/a lo indica.
Parada activo2. El tren está parado y activo. Desde este estado sólo se podrá pasar a inactivo o a manual si el conductor/a lo indica y si el estado de alerta lo permite.
Manual. El tren está en modo conducción manual. El conductor/a es el encargado de la conducción. Desde este estado se podrá pasar a parada activo o a autónomo si el conductor/a lo indica.
Autónomo. El tren está en modo conducción autónoma. El conductor/a monitoriza la conducción. Desde este estado se podrá pasar a manual si el conductor/a lo indica o si hay una alerta.
Gestión del estado de alerta3: Esta tarea deberá ejecutarse, al menos, con una frecuencia de 5Hz y tendrá prioridad alta. La alerta podrá encontrarse en cualquiera de los siguientes estados:
Sin alerta.
Alerta. En este estado el tren no puede estar en modo de conducción autónoma.
En concreto, se pide:
Diseño de la interfaz HMI. Se deben incluir los mecanismos que permitan al conductor/a actuar sobre el panel de control, así como los indicadores que permitan al conductor/a conocer el estado del tren y de la alerta. (se puede diseñar en wokwi y subir una captura en la sección NOTAS SOBRE LA SOLUCIÓN PROPUESTA de la respuesta). [0.5 puntos4]
Programación correcta del dispositivo para la gestión de las tareas en tiempo real. [0.5 puntos]
Programación correcta de la tarea de gestión del estado del tren. [0.5 puntos]
Programación correcta de la tarea de gestión del estado de alerta (esto incluye también la interacción con la tarea de gestión del estado del tren). [1 punto]
NOTAS:
1 Se pide implementar, como mínimo, esas tareas (se pueden incluir más si se considera necesario).
2 Al pasar de modo manual a espera activo, el tren inicia un proceso de frenada automática de forma controlada en base a la velocidad actual del tren. El conductor/a ha sido previamente formado en el manejo de este vehículo y conoce su funcionamiento, por lo que NO es necesario indicarle que el tren está realizando una parada de emergencia.
3 Aunque el cambio del estado de alerta se hace, por lo general, de forma automática, la HMI DEBERÁ incluir algún mecanismo que permita al conductor/a cambiar el estado de alerta.
4 Para conseguir puntos por el diseño de la interfaz se debe haber realizado algo de la parte de programación (apartados 2, 3 o 4). A la hora de diseñar la interfaz se tiene que tener en cuenta lo explicado en el Tema 7 e incluir una breve descripción de la misma.