Welcome to our new forum
All users of the legacy CODESYS Forums, please create a new account at account.codesys.com. But make sure to use the same E-Mail address as in the old Forum. Then your posts will be matched. Close

DUT (Struct) Property in einem FB Änderungen abfangen

paho
2023-03-13
2023-03-14
  • paho - 2023-03-13

    Hallo,

    ich wende mich mit der doch nicht so trivialen Frage an euch: wie fange ich am besten Änderungen an Variablen von einer Struktur in einem Funktionsblock ab?

    Beispiel DUT:

    TYPE DUT_Test :
        STRUCT
            index: INT := -1;
            interval: INT := 10;
            state: INT := 0;
            enable: BOOL := FALSE;
        END_STRUCT
    END_TYPE
    

    Beispiel FB:

    FUNCTION_BLOCK TestFb
    VAR_INPUT
        CFG: DUT_Test;
    END_VAR
    VAR_OUTPUT
        OUT_RUN: BOOL;
    END_VAR
    
    IF CFG.enable THEN
        IF CFG.state > 0 AND CFG.index > -1 THEN
            OUT_RUN:=TRUE;
        ELSE
            OUT_RUN:=FALSE;
        END_IF
    ELSE
        OUT_RUN:=FALSE;
    END_IF
    

    Beispiel PRG:

    PROGRAM Test
    VAR
        xTest: TestFb;
    END_VAR
    
    xTest(OUT_RUN=>DO01);
    

    Die CFG-Struktur der xTest-Instanz ist in der Symbolkonfiguration für einen OPC-UA Zugriff freigegeben (R+W).
    Wie kann ich nun auf Veränderungen der CFG-Struktur reagieren, wenn z.B. über OPC-UA die Variablen geändert werden?

    xTest.CFG.enable:=1;
    xTest.CFG.index:=1;
    xTest.CFG.state:=1;
    

    Bei wenigen Variablen würde der Weg mittels Eigenschaften (Getter/Setter) funktionieren, aber ich habe auch sehr komplexe DUTs und suche nach einer einfachen Lösung :)

    Grundsätzlich brauche ich diese Funktion nicht für jede Variable, sondern nur ob sich eine Variable in der CFG-Struktur geändert hat, um dann eine Funktion zu starten (abspeichern eines Rezeptes mit den aktuellen Konfigurationswerten).
    Die CFG-Struktur enthält immer alle Konfigurationsparameter für diesen FB, welche immer nach jeder Änderung, Up-to-date mit dem "Runtime-Rezept" sein müssen.

    Danke schon mal für die Hilfe,
    LG, PAHO

     

    Last edit: paho 2023-03-13
  • dkugler - 2023-03-14

    holst dir als pointer die Startadresse der jeweiligen struct und machst einen Speichervergleich über die Größe der struct.
    Stresst die Steuerung minimalst, da extrem hardwarenah.
    VAR
    pstruct1: POINTER TO BYTE;
    pstruct2: POINTER TO BYTE;
    xValuesChanged: BOOL;
    END_VAR

    pstruct1 := ADR(struct1);
    pstruct2 := ADR(struct2);

    xValuesChanged := DINT_TO_BOOL(sysmemcmp(pstruct1,pstruct2, SIZEOF(struct1))

    So lösche ich z.b. auch ganze Arrays oder Arrays of STRUCT ab: Startadresse ermitteln und dann SysMemSet... über den Speicherbereich!

     
    👍
    1
    • paho - 2023-03-14

      Hi,
      ja genau so mache ich das im Moment. Dachte mir aber, vielleicht gibt es noch elegantere Lösungen (wie eben bei Properties Get/Set). Auch wenn dieses Beispiel nicht wirklich komplex ist, habe ich Strukturen mit weit über 100 Variablen (diverse Datentypen).

      Meine Hardware (Linux IPC mit Codesys Runtime) packt das locker, aber ich habe immer zwei komplette Strukturen im Speicher (alt und aktuell) um vergleichen zu können. Vom Aufwand aber eh total überschaubar.

      Danke trotzdem für die Hilfe!

       

Log in to post a comment.