Completed
Estructurar la lógica del PLC en C++ de Arduino: máquinas de estados en lugar de bucles largos
Una única función loop() que crece sin parar con sentencias if se vuelve ilegible y difícil de depurar muy rápido. En este curso construirás un solo proyecto de principio a fin: el control de una estación de bombeo con depósito. En esta primera lección le das una estructura sólida con una máquina de estados, el patrón que acaba necesitando casi toda la lógica de PLC en C++ de Arduino.
Qué aprenderás
- Sustituir if anidados por estados con nombre y transiciones explícitas.
- Escribir una máquina de tres estados con una salida segura del fallo.
- Decidir cuándo una nueva condición merece un nuevo estado.
El proyecto: un pulsador de marcha en I0_0, una parada de emergencia en I0_1, un contactor de bomba en Q0_0 y un piloto de alarma en Q0_1. Las lecciones siguientes añaden el nivel del depósito, temporización, Modbus, memoria, watchdog y un panel de control.
Por qué un loop() largo se desmorona
A medida que crece un sketch, un loop() que comprueba decenas de condiciones se vuelve difícil de leer, de probar y fácil de romper con un cambio ajeno. Una máquina de estados da a tu programa un conjunto pequeño de estados con nombre y reglas claras para pasar de uno a otro.
La estación de bombeo como máquina de estados
enum State { IDLE, RUNNING, FAULT };
State currentState = IDLE;
void setup() {
pinMode(I0_0, INPUT); // pulsador de marcha
pinMode(I0_1, INPUT); // parada de emergencia
pinMode(Q0_0, OUTPUT); // contactor de la bomba
pinMode(Q0_1, OUTPUT); // piloto de alarma
digitalWrite(Q0_0, LOW);
digitalWrite(Q0_1, LOW);
}
void loop() {
switch (currentState) {
case IDLE:
digitalWrite(Q0_0, LOW);
if (digitalRead(I0_0) == HIGH) {
currentState = RUNNING;
}
break;
case RUNNING:
digitalWrite(Q0_0, HIGH);
if (digitalRead(I0_1) == HIGH) {
currentState = FAULT;
}
break;
case FAULT:
digitalWrite(Q0_0, LOW);
digitalWrite(Q0_1, HIGH);
if (digitalRead(I0_1) == LOW && digitalRead(I0_0) == HIGH) {
digitalWrite(Q0_1, LOW);
currentState = IDLE;
}
break;
}
}
Cada case es exactamente un estado, y un estado solo cambia dentro de su propio case, lo que facilita rastrear cómo la máquina pasó de IDLE a FAULT. Fíjate en la salida de FAULT: la máquina solo vuelve a IDLE cuando se suelta la parada de emergencia y el operario pulsa marcha como reconocimiento. Un estado de fallo sin salida es un error de diseño habitual.
Resultado esperado: al pulsar I0_0 se activa Q0_0, al activar I0_1 se apaga y se enciende Q0_1, y el sistema solo se rearma tras soltar I0_1 y reconocer con I0_0.
Cuándo añadir un estado en lugar de otro if
Si te preguntas en qué modo está la máquina ahora mismo y la respuesta depende de tres variables más, esa combinación probablemente es un estado que falta. Una nueva condición es señal de un nuevo estado, no de otro if anidado dentro de uno existente.
Estados y el ciclo de scan del PLC
A diferencia de un scan de PLC tradicional, el loop() de Arduino se ejecuta tan rápido como permite el código, sin un tiempo de scan fijo por defecto. Una máquina de estados no cambia eso, pero hace predecible cada pasada: leer entradas, evaluar el estado actual, fijar salidas y continuar.
Para profundizar
- Arduino PLC vs ESP32 PLC vs Raspberry Pi PLC: cuál elegir
- 8 señales de que tu prototipo no está listo para producción
Siguiente lección: temporización sin bloqueo, para que la estación de bombeo pueda esperar y seguir reaccionando. Haz primero el cuestionario de abajo.
There are no comments for now.