Device diagnosis ( EtherCAT IO card )

andre-luis
2025-02-06
2025-02-06
  • andre-luis

    andre-luis - 2025-02-06

    Hi,

    In our project, it is not rare to have I/O cards issues.
    I wanted to have a way to check their statuses ( Eg. INIT, OP, PREOP, etc.. )

    I was trying to use the GetDeviceDiagnosisInfo method from the IoConfig_Globals, but there is no info available on the Web with a simple example; does someone have a link to some tutorial or anything else ?

    Kind Regards,
    Andre.

     
  • TimvH

    TimvH - 2025-02-06

    You can get the state by just using the name of your node (same name as in device tree):

    VAR
        etcState: IoDrvEthercatDriverLib.ETC_SLAVE_STATE;
    END_VAR
    
    etcState := EJ1100.wState;
    

    Alternatively, you can iterate through the device tree to get the status of all (Ethercat) nodes. See here an example (no guarantee it works, just give as suggestion):

    PROGRAM P_IO_State
    VAR CONSTANT
        uiMAX_NR_OF_TERMINALS : UINT := 100;
    END_VAR
    VAR
        // general device diagnosis
        // can only be used when the Device - PLC Settings - Advanced settings - enable diagnosis for devices is enabled
        // this will add the DED library
        coupler: DED.INode;
        terminal: DED.INode;
        aDeviceState: ARRAY[0..uiMAX_NR_OF_TERMINALS - 1] OF DED.DEVICE_STATE;
    
        uiTerminalCount : UINT;
        uiIndex : UINT;
    
        // for each terminal check if it implements device diagnostics
        xQueryResult: BOOL;
        itfDevice : DED.IDevice2;
        xDiagAvailable: BOOL;
        eError: DED.ERROR;
    
        xEverythingOK: BOOL;
    END_VAR
    
    uiTerminalCount := 0;
    // start at the top of the device tree with the first EtherCAT coupler
    coupler := EtherCAT_Master.FirstChildNode;
    WHILE coupler <> 0 DO
        // for each coupler that is found start at the first terminal
        terminal := coupler.FirstChildNode;
        WHILE terminal <> 0 AND uiTerminalCount < uiMAX_NR_OF_TERMINALS - 1 DO
            // for each terminal that is found get the status through the device diagnosis interface
            xQueryResult := __QUERYINTERFACE(terminal, itfDevice);
            IF xQueryResult THEN
                aDeviceState[uiTerminalCount] := itfDevice.GetDeviceState(xDiagnosisInfoAvailable => xDiagAvailable, eError => eError);
                uiTerminalCount := uiTerminalCount + 1;
            END_IF
            terminal := terminal.NextSiblingNode;
        END_WHILE
        coupler := coupler.NextSiblingNode;
    END_WHILE
    
    uiIndex := 0;
    xEverythingOK := TRUE;
    WHILE uiIndex < uiTerminalCount DO
        IF aDeviceState[uiIndex] <> DED.DEVICE_STATE.RUNNING THEN
            xEverythingOK := FALSE;
            EXIT;
        END_IF
        uiIndex := uiIndex + 1;
    END_WHILE
    
     
  • andre-luis

    andre-luis - 2025-02-06

    Hi @TimvH,

    In the meantime, I did some experiments and could find a way to achieve similar result.
    I made some tests, removing the last card from the array, seeing the change on status.

    PROGRAM P_IOS_STATUSES
    VAR
        devStateInput               :   DEVICE_STATE;
        devStateOutput              :   DEVICE_STATE;
        devStateEncoder             :   DEVICE_STATE;
    END_VAR
        devStateInput   :=  IoConfig_Globals.EL1819.GetDeviceState();
        devStateOutput  :=  IoConfig_Globals.EL2809.GetDeviceState();
        devStateEncoder :=  IoConfig_Globals.EL5151.GetDeviceState();
    
        GVL.bInputCardOK        :=  ( devStateInput = DEVICE_STATE.RUNNING );
        GVL.bOutputCardOK       :=  ( devStateOutput = DEVICE_STATE.RUNNING );
        GVL.bEncoderCardOK      :=  ( devStateEncoder = DEVICE_STATE.RUNNING );
    

    Many thanks for your quick and extensive reply.

     

Log in to post a comment.