Brandon Engineer

Shopping cart

Subtotal 0,00 

View cartCheckout

Como optimizar tu código en SCL

blank

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.

Leave A Comment

Your email address will not be published. Required fields are marked *

en_USEnglish