/*
Implementación de la FSM3 para el control de la FSM1 y FSM2.
FSM1: Controla llenado y vaciado de tanque.
FSM2: Proceso de calibración de una báscula.
FSM3: Sincroniza FSM1 y FSM2 según las prioridades y señales de control.
Estudiantes:
Nombre 1 - Código
Nombre 2 - Código
*/
// ----------------------- FSM1: Llenado y vaciado de tanque -----------------------
enum EstadoFSM1 {IDLE_FSM1, DRAINING_FSM1, FILLING_FSM1};
EstadoFSM1 estadoActualFSM1 = IDLE_FSM1;
// Pines FSM1
const int habilitacionFSM1 = 2;
const int sensorMin = 3;
const int sensorMax = 4;
const int valvulaEntrada = 5;
const int valvulaSalida = 6;
// Variables FSM1
bool mensajeMostradoFSM1 = false;
bool busyFSM1 = false; // Virtual para FSM3
void fsm1() {
bool habilitadoFSM1 = !digitalRead(habilitacionFSM1);
bool nivelMin = !digitalRead(sensorMin);
bool nivelMax = !digitalRead(sensorMax);
switch (estadoActualFSM1) {
case IDLE_FSM1:
if (!mensajeMostradoFSM1) {
Serial.println("FSM1: IDLE.");
mensajeMostradoFSM1 = true;
}
digitalWrite(valvulaEntrada, LOW);
digitalWrite(valvulaSalida, LOW);
busyFSM1 = false;
if (habilitadoFSM1) {
estadoActualFSM1 = DRAINING_FSM1;
mensajeMostradoFSM1 = false;
}
break;
case DRAINING_FSM1:
if (!mensajeMostradoFSM1) {
Serial.println("FSM1: Vaciando...");
mensajeMostradoFSM1 = true;
}
digitalWrite(valvulaSalida, HIGH);
digitalWrite(valvulaEntrada, LOW);
busyFSM1 = true;
if (nivelMin) {
estadoActualFSM1 = FILLING_FSM1;
mensajeMostradoFSM1 = false;
} else if (!habilitadoFSM1) {
estadoActualFSM1 = IDLE_FSM1;
mensajeMostradoFSM1 = false;
}
break;
case FILLING_FSM1:
if (!mensajeMostradoFSM1) {
Serial.println("FSM1: Llenando...");
mensajeMostradoFSM1 = true;
}
digitalWrite(valvulaEntrada, HIGH);
digitalWrite(valvulaSalida, LOW);
if (nivelMax) {
estadoActualFSM1 = DRAINING_FSM1;
mensajeMostradoFSM1 = false;
} else if (!habilitadoFSM1) {
estadoActualFSM1 = DRAINING_FSM1; // Termina el ciclo.
mensajeMostradoFSM1 = false;
}
break;
}
}
// ----------------------- FSM2: Calibración de báscula -----------------------
enum EstadoFSM2 {SH, S0, S1, S2, S3, S4};
EstadoFSM2 estadoActualFSM2 = SH;
// Pines FSM2
const int habilitacionFSM2 = 7;
const int pulsadorA = 8;
const int pulsadorR = 9;
const int ledVacio = 10;
const int ledConocido = 11;
// Variables FSM2
float VCERO = 0;
float VCAL = 0;
float S = 0;
bool mensajeMostradoFSM2 = false;
bool busyFSM2 = false; // Virtual para FSM3
void fsm2() {
bool habilitadoFSM2 = !digitalRead(habilitacionFSM2);
bool avance = !digitalRead(pulsadorA);
bool retrocede = !digitalRead(pulsadorR);
switch (estadoActualFSM2) {
case SH:
if (!mensajeMostradoFSM2) {
Serial.println("FSM2: Inactivo.");
mensajeMostradoFSM2 = true;
}
digitalWrite(ledVacio, LOW);
digitalWrite(ledConocido, LOW);
busyFSM2 = false;
if (habilitadoFSM2) {
estadoActualFSM2 = S0;
mensajeMostradoFSM2 = false;
}
break;
case S0:
if (avance) {
estadoActualFSM2 = S1;
mensajeMostradoFSM2 = false;
}
break;
case S1:
if (!mensajeMostradoFSM2) {
Serial.println("FSM2: Ajuste de cero.");
mensajeMostradoFSM2 = true;
}
digitalWrite(ledVacio, HIGH);
if (avance) {
VCERO = analogRead(A0) * (5.0 / 1023.0);
estadoActualFSM2 = S2;
mensajeMostradoFSM2 = false;
} else if (retrocede) {
estadoActualFSM2 = S0;
mensajeMostradoFSM2 = false;
}
break;
case S2:
if (!mensajeMostradoFSM2) {
Serial.println("FSM2: Ajuste de sensibilidad.");
mensajeMostradoFSM2 = true;
}
digitalWrite(ledConocido, HIGH);
if (avance) {
VCAL = analogRead(A0) * (5.0 / 1023.0);
S = (VCAL - VCERO) / 10.0;
estadoActualFSM2 = S3;
mensajeMostradoFSM2 = false;
} else if (retrocede) {
estadoActualFSM2 = S1;
mensajeMostradoFSM2 = false;
}
break;
case S3:
if (!mensajeMostradoFSM2) {
Serial.println("FSM2: Validación.");
mensajeMostradoFSM2 = true;
}
digitalWrite(ledVacio, HIGH);
digitalWrite(ledConocido, HIGH);
if (avance) {
estadoActualFSM2 = S4;
mensajeMostradoFSM2 = false;
}
break;
case S4:
if (!mensajeMostradoFSM2) {
Serial.println("FSM2: Guardado de valores.");
mensajeMostradoFSM2 = true;
}
busyFSM2 = false;
if (!habilitadoFSM2) {
estadoActualFSM2 = SH;
mensajeMostradoFSM2 = false;
}
break;
}
}
// ----------------------- FSM3: Sincronización -----------------------
enum EstadoFSM3 {IDLE_FSM3, FSM1_ACTIVE, FSM2_ACTIVE};
EstadoFSM3 estadoActualFSM3 = IDLE_FSM3;
// Pines FSM3
const int callFillEmpty = 12;
const int callCalibrate = 13;
bool enableFSM1 = false;
bool enableFSM2 = false;
void fsm3() {
bool callFSM1 = !digitalRead(callFillEmpty);
bool callFSM2 = !digitalRead(callCalibrate);
switch (estadoActualFSM3) {
case IDLE_FSM3:
if (callFSM2) {
enableFSM2 = true;
estadoActualFSM3 = FSM2_ACTIVE;
} else if (callFSM1) {
enableFSM1 = true;
estadoActualFSM3 = FSM1_ACTIVE;
}
break;
case FSM1_ACTIVE:
if (callFSM2) {
enableFSM1 = false;
enableFSM2 = true;
estadoActualFSM3 = FSM2_ACTIVE;
} else if (!busyFSM1) {
enableFSM1 = false;
estadoActualFSM3 = IDLE_FSM3;
}
break;
case FSM2_ACTIVE:
if (!busyFSM2) {
enableFSM2 = false;
estadoActualFSM3 = IDLE_FSM3;
}
break;
}
}
// ----------------------- Configuración general -----------------------
void setup() {
Serial.begin(9600);
// Configuración pines FSM1
pinMode(habilitacionFSM1, INPUT_PULLUP);
pinMode(sensorMin, INPUT_PULLUP);
pinMode(sensorMax, INPUT_PULLUP);
pinMode(valvulaEntrada, OUTPUT);
pinMode(valvulaSalida, OUTPUT);
// Configuración pines FSM2
pinMode(habilitacionFSM2, INPUT_PULLUP);
pinMode(pulsadorA, INPUT_PULLUP);
pinMode(pulsadorR, INPUT_PULLUP);
pinMode(ledVacio, OUTPUT);
pinMode(ledConocido, OUTPUT);
// Configuración pines FSM3
pinMode(callFillEmpty, INPUT_PULLUP);
pinMode(callCalibrate, INPUT_PULLUP);
}
void loop() {
fsm3(); // Ejecuta FSM3
if (enableFSM1) fsm1(); // Ejecuta FSM1 si está habilitada
if (enableFSM2) fsm2(); // Ejecuta FSM2 si está habilitada
}