Introducción
Esta tarde estaba aburrido en casa y puse a prueba una idea que lleva tiempo rondándome la cabeza: «¿Es más optimo usar una máquina de estados que un sistema tradicional?» Mi suposición es que al usar una máquina de estados esta saltará el código que no se usa y permitirá ignorar el código que no se utilizará por lo que podrías optimizarlo para no tener a tu maquina ahogándose.
¿Cómo se ha realizado?
Para esta prueba decidí ejecutarla en el entorno de Twincat de Beckhoff Automation, que me da control del conocimiento de cada núcleo y compararlo en el mismo instante de tiempo. Preparé los FB, al final llamé a 300 FB por cada una de las tareas con un tiempo de ejecución de 0.5ms y comparé los rendimientos.
Llamada de las tareas
Para hacer una carga grande de recursos se ha llamado a 300 FB para que sea apreciable los consumos
bSwitching(bStart=>bStart);
FOR counter:=1 TO 299 BY 1 DO
fb[counter](bInputDown:=bStart);
END_FOR;
«bStart» es un booleano que cambia de true a false cada segundo
Con estados
El código para la function block
FUNCTION_BLOCK FB_WaitandWriteState
VAR_INPUT
bInputUp : BOOL; // Entrada para subir
bInputDown : BOOL; // Entrada para bajar
END_VAR
VAR_OUTPUT
bOutputUp : BOOL := FALSE; // Salida para subir
bOutputDown : BOOL := FALSE; // Salida para bajar
END_VAR
VAR
Temporizador : TON := (PT:= T#60S); // Temporizador de 60 segundos
TemporizadorEspera : TON := (PT:= T#1S); // Temporizador de espera de 1 segundo
EstadoMaquinaActual : INT:=0;
END_VAR
El código usado para el programa ha sido:
CASE EstadoMaquinaActual OF
// Estado inicial, esperando la entrada
0:
IF bInputUp THEN
EstadoMaquinaActual := 10; // Cambiar al estado de subir
ELSIF bInputDown THEN
EstadoMaquinaActual := 20; // Cambiar al estado de bajar
END_IF
// Estado de subir
10:
bOutputUp := TRUE; // Activar la salida de subir
Temporizador(IN:= TRUE); // Iniciar temporizador de 60 segundos
IF Temporizador.Q THEN
EstadoMaquinaActual := 30; // Cambiar al estado de espera
END_IF
// Estado de bajar
20:
bOutputDown := TRUE; // Activar la salida de bajar
Temporizador(IN:= TRUE); // Iniciar temporizador de 60 segundos
IF Temporizador.Q THEN
EstadoMaquinaActual := 30; // Cambiar al estado de espera
END_IF
// Estado de espera
30:
TemporizadorEspera(IN:= TRUE);
IF TemporizadorEspera.Q THEN
// Reiniciar salidas y temporizadores
bOutputUp := FALSE;
bOutputDown := FALSE;
Temporizador(IN:= FALSE);
TemporizadorEspera(IN:= FALSE);
// Volver al estado inicial
EstadoMaquinaActual := 0;
END_IF
END_CASE
Sin estados
Este es el código de la tarea:
FUNCTION_BLOCK FB_Wait_andWrite_NON_State
VAR_INPUT
bInputUp : BOOL; // Entrada para subir
bInputDown : BOOL; // Entrada para bajar
END_VAR
VAR_OUTPUT
bOutputUp : BOOL := FALSE; // Salida para subir
bOutputDown : BOOL := FALSE; // Salida para bajar
END_VAR
VAR
Temporizador : TOF := (PT:= T#60S); // Temporizador de 60 segundos
TemporizadorEspera : TON := (PT:= T#1s); // Temporizador de espera de 1 segundo
bBajando: BOOL;
bSubiendo: BOOL;
END_VAR
El código para la function block
Temporizador(IN:= bSubiendo OR bBajando); // Iniciar temporizador si se está subiendo o bajando
bSubiendo := bInputUp AND NOT bSubiendo; // Marcar subida si no estaba subiendo antes
bBajando := bInputDown AND NOT bBajando; // Marcar bajada si no estaba bajando antes
bOutputUp := bSubiendo AND NOT Temporizador.Q; // Activar salida de subir mientras no se exceda el temporizador
bOutputDown := bBajando AND NOT Temporizador.Q; // Activar salida de bajar mientras no se exceda el temporizador
IF Temporizador.Q THEN
bSubiendo := FALSE; // Reiniciar flag de subir
bBajando := FALSE; // Reiniciar flag de bajar
TemporizadorEspera(IN:= TRUE); // Iniciar temporizador de espera de 1 segundo
END_IF
TemporizadorEspera(IN:= TemporizadorEspera.Q); // Reiniciar temporizador de espera si se completó
Conclusión
Como supuse es un aumento de rendimiento considerable (el software sin máquina de estados consume 3 veces más). Adjunto las fotos de los FB, el programa y las gráficas de los rendimientos.
¿Y ustedes? ¿Lo sabían ya? ¿Se imaginaban el resultado como yo? ¿Creéis que algo ha fallado en mi evaluación?
Yo la verdad es que me ha sorprendido los resultados, no me esperaba tanto y menos para una aplicación tan sencilla, son unos temporizadores y unos IF
Espero sus comentarios, chicos.