Estuve viendo algunos problemas que se presentan en distintos casos, haciendo que los circuitos no funcionen como se espera, y a mi entender se debe a un problema en la lógica general del código que C que genera IDE4PLC. Estoy usando IDE4PLC versión 1.0.2
Un ejemplo rápido : El siguiente circuito debería hacer que cuando se pulsa TEC_1 se encienda el LED_1 y cuando se suelta se apague. Pero lo que hace es que LED_1 se encienda al pulsar TEC_1 y no se apague al soltarlo.
El circuito debería funcionar de la siguiente manera : El bloque MOV hace var1=0, Cuando se pulsa TEC_1 el bloque ADD hace var1 = var1 + 1. Si TEC_1 no se pulsa var1 sigue en cero. El bloque EQ enciende el LED_1 si var1 == 1, sino el LED_1 permanece apagado.
Mas abajo, usando dos casos, trato de ejemplificar y analizar con mas detalle el problema, pero para no aburrir mas de lo necesario, ya resumo el tema : creo que el problema ocurre porque la salida .OUT de un bloque se asigna a la variable de salida del bloque independientemente que el bloque haya realizado la operación o no lo haya hecho (asignación independiente de la habilitación del bloque).
El siguiente es parte del código que genera el circuito anterior. Aunque ADD_INT_VAR.EN no esté habilitada, la asignación de la variable var1 (pxPOU->var1 = pxPOU->ADD_INT_VAR.OUT;) se realiza igualmente, asignado a var1 el último valor de ADD_INT_VAR.OUT :
PLC_IL_LD( &(pxPOU->TEC_1), sizeof(pxPOU->TEC_1), BOOL, NullModifier); // LD TEC_1
PLC_IL_ST( &(pxPOU->ADD_INT_VAR.EN), sizeof(pxPOU->ADD_INT_VAR.EN), NullModifier); // ST ADD_INT_VAR.EN
pxPOU->ADD_INT_VAR.IN1 = 1;
pxPOU->ADD_INT_VAR.IN2 = pxPOU->var1;
PLC_F_ADD_INT( &pxPOU->ADD_INT_VAR );
FLUX = pxPOU->ADD_INT_VAR.ENO;
pxPOU->var1 = pxPOU->ADD_INT_VAR.OUT;
Si bien, debido a mi desconocimiento sobre Pharo, no pude modificar el programa PLC_UserPrograms.c en su origen, a manera de prueba hice una modificación a dicho programa incorporándole a la asignación directa de la variable de salida (Por ej. pxPOU->var11 = pxPOU->SUB_INT_VAR.OUT; ) una condición para que asigne la salida de un bloque a la variable correspondiente solo cuando la entrada EN (Aunque también podría ser la salida ENO) esté habilitada (Por ej. if (pxPOU->SUB_INT_VAR.EN) {pxPOU->var11 = pxPOU->SUB_INT_VAR.OUT;} )
Seguramente esta no es la solución mas prolija pero sirvió para probar que era una posible solución.
PLC_IL_LD( &(FLUX), sizeof(FLUX), BOOL, NullModifier); // LD FLUX
PLC_IL_LD( &(pxPOU->TEC_1), sizeof(pxPOU->TEC_1), BOOL, NullModifier); // LD TEC_1
PLC_IL_ST( &(pxPOU->SUB_INT_VAR.EN), sizeof(pxPOU->SUB_INT_VAR.EN), NullModifier); // ST SUB_INT_VAR.EN
pxPOU->SUB_INT_VAR.IN1 = pxPOU->var11;
pxPOU->SUB_INT_VAR.IN2 = 1;
PLC_F_SUB_INT( &pxPOU->SUB_INT_VAR );
FLUX = pxPOU->SUB_INT_VAR.ENO;
if (pxPOU->SUB_INT_VAR.EN) {
pxPOU->var11 = pxPOU->SUB_INT_VAR.OUT;}
A continuación describo algunos casos con mas detalle.
Ejemplo 1
En este ejemplo se simplifica el nombre de los objetos. Por ejemplo, en lugar de SUB_INT_VAR.OUT se pone SUB.OUT.
Cuando se pulsa TEC_1 se enciende LED_1 y se mantiene encendido hasta que se pulsa TEC_2
Si se pulsa TEC_1, var1=1 (en pto 3). Cuando TEC_1 se suelta var1 sigue teniendo el mismo valor porque el valor que tomó ADD.OUT en (3) sigue teniendo el mismo valor.
Al pulsar TEC_2, ADD.OUT toma el valor 6 (en 1), cuando pasa por (3), aunque TEC_1 no esté pulsado var1 = ADD.OUT que es 6.
Ejemplo 2
En este ejemplo se simplifica el nombre de los objetos. Por ejemplo, en lugar de SUB_INT_VAR.OUT se pone SUB.OUT.
Cuando se pulsa TEC_1 se enciende LED_2, cuando TEC_1 no está pulsado se enciende LED_1.
Cuando TEC_1 esta pulsado :
En (1) ADD.OUT=1 y var11=1
En (2) SUB.OUT=4 y var1=4
En (3) si TEC_1 esta pulsado SUB.OUT y var11 = var11 -1, es decir var11=0
Cuando TEC_1 no esta pulsado :
En (1) ADD.OUT=1 y var11=1
En (2) SUB.OUT=4 y var1=4
En (3) si TEC_1 no está pulsado SUB.OUT sigue con el último valor (es decir 4), entonces var11 = 4
Si TEC_1, var11 es igual a 0
Si no TEC_2, var11 es igual a 4
Otros ejemplos
El siguiente circuito funciona bien (al mantener pulsado TEC 1, LED 1 se enciende y cuando se suelta TEC 1, LED 1 se apaga). Pero si se reemplaza el primer bloque ADD por otras opciones para poner la variable var1 en cero (por ejemplo un bloque SUB con entradas 0, por un bloque MUL con entradas 0, por un bloque DIV con entradas 0 y 1, por un bloque MOD con entradas 10 y 2, por un bloque MOV con entrada 0, etc) el circuito responde distinto; al pulsar TEC 1, el LED 1 queda encendido y no se apaga.
El siguiente circuito, como se ve, debería encender el LED 1 cuando se pulsa TEC 1 y cuando se suelta TEC 1 LED 1 debe apagarse. TEC 2 no debería tener ninguna influencia sobre LED 1.
Si bien lo anterior es lo que debería hacer, lo que hace es : cuando se pulsa TEC 1 el LED 1 se enciende y se mantiene encendido hasta que se pulsa TEC 2. Por el comportamiento es como si la entrada EN quedaría seteado o faltaría alguna inicialización en la estructura de datos.