Example 1: Expanded ADS function blocks

In the example application, READ-Requests are sent from a VB application to the PLC task in order to increment/decrement or reset a PLC counter variable. If successful the value of the counter variables is sent back to the VB application and outputted on the form. In order to communicate with the PLC task the VB application uses the ActiveX control: AdsOcx.

Example 1: Expanded ADS function blocks 1:

Here you can unpack the complete sources relating to the example application: Example application with the expanded ADS function blocks

The VB application

A connection to the PLC task is constructed in the Form_Load-Routine (port 802 on the local computer). The required service in the PLC task is encoded in the index group parameter:

So that the requests can be routed to the PLC task, the highest value bit must be set in the index group parameter. The index offset parameter is zero.

Option Explicit
    
Dim tmpData(1) As Integer
Dim AdsResult    As Integer

Private Sub Command1_Click()
    
    AdsResult = AdsOcx1.AdsSyncReadReq(&H80000001, &H0, 2, tmpData)
    Label1.Caption = "Ads result:" & AdsResult & " PLC data:" & tmpData(0)
    
End Sub

Private Sub Command2_Click()
    AdsResult = AdsOcx1.AdsSyncReadReq(&H80000002, &H0, 2, tmpData)
    Label1.Caption = "Ads result:" & AdsResult & " PLC data:" & tmpData(0)

End Sub

Private Sub Command3_Click()
    AdsResult = AdsOcx1.AdsSyncReadReq(&H80000003, &H0, 2, tmpData)
    Label1.Caption = "Ads result:" & AdsResult & " PLC data:" & tmpData(0)

End Sub

Private Sub Form_Load()
    AdsOcx1.AdsAmsServerNetId = AdsOcx1.AdsAmsClientNetId
    AdsOcx1.AdsAmsServerPort = 802 'PLC task number'
End Sub

 

The PLC program

The requests are intercepted as indications in the PLC task by an instance of the ADSREADIND function block. Next the index group and index offset parameters and the required data length and validity are checked. In the CASE instruction the desired operation is implemented on the PLC variables. If successful a response is sent back by an instance of the ADSREADRES function block to the caller with the current value of the PLC variables. In the case of an error an appropriate error message. At the end the CLEAR and RESPOND flags are reset in order to be able to process further indications.

PROGRAM MAIN
VAR
    fbReadInd   : ADSREADIND;(* Indication function block instance *)
    fbReadRes   : ADSREADRES;(* Response function block instance *)

    sNetId      : T_AmsNetID;
    nPort       : T_AmsPort;
    nInvokeId       : UDINT;
    nIdxGrp     : UDINT;
    nIdxOffs    : UDINT;
    cbLength    : UDINT;(* Requested read data/buffer byte size *)
    
    cbRead      : UDINT;(* Returned read data/buffer byte size *)
    pRead       : POINTER TO BYTE;(* Pointer to returned read data/buffer *)
    nErrID      : UDINT;(* Read indication result error code *)
    
    nCounter    : INT;(* Server data *)
END_VAR

 

fbReadRes( RESPOND := FALSE );(* Reset response function block *)
fbReadInd( CLEAR := FALSE );(* Trigger indication function block *)
IF fbReadInd.VALID THEN(* Check for new indication *)

    sNetID := fbReadInd.NETID;
    nPort := fbReadInd.PORT;
    nInvokeID := fbReadInd.INVOKEID;
    nIdxGrp := fbReadInd.IDXGRP;
    nIdxOffs := fbReadInd.IDXOFFS;
    cbLength := fbReadInd.LENGTH;

    cbRead := 0;
    pRead := 0;
    nErrID  := 16#701;(* ADS error: Service not supported by server *)

    
    CASE nIdxGrp OF
        (*------------------------------------------------------------------------------------*)
        16#80000001:
            CASE nIdxOffs OF
                0:(* Increment counter value *)
                    IF cbLength >= SIZEOF(nCounter) THEN
                        nCounter := nCounter + 1;
                        cbRead := SIZEOF(nCounter);
                        pRead := ADR(nCounter);
                        nErrID := 0;
                    ELSE (* ADS error (example): Invalid size *)
                        nErrID := 16#705;
                    END_IF
            ELSE (* ADS error (example): Invalid index offset *)
                nErrID := 16#703;
            END_CASE
        (*------------------------------------------------------------------------------------*)
        16#80000002:
            CASE nIdxOffs OF
                0:(* Decrement counter value *)
                    IF cbLength >= SIZEOF(nCounter) THEN
                        nCounter := nCounter - 1;
                        cbRead := SIZEOF(nCounter);
                        pRead := ADR(nCounter);
                        nErrID := 0;
                    ELSE(* ADS error (example): Invalid size *)
                        nErrID := 16#705;
                    END_IF
            ELSE (* ADS error (example): Invalid index offset *)
                nErrID := 16#703;
            END_CASE
        (*------------------------------------------------------------------------------------*)
        16#80000003:
            CASE nIdxOffs OF
                0:(* Reset counter value *)
                    IF cbLength >= SIZEOF(nCounter) THEN
                        nCounter := 0;
                        cbRead := SIZEOF(nCounter);
                        pRead := ADR(nCounter);
                        nErrID := 0;
                    ELSE(* ADS error (example): Invalid size *)
                        nErrID := 16#705;
                    END_IF
            ELSE (* ADS error (example): Service is not supported by server *)
                nErrID := 16#701;(* ADS error: Service not supported *)
            END_CASE

    ELSE (* ADS error (example): Invalid index group *)
        nErrID := 16#702;
    END_CASE
    
    fbReadRes(      NETID := sNetID, 
                PORT := nPort, 
                INVOKEID := nInvokeID,
                LEN := cbRead, 
                DATAADDR := pRead,
                RESULT := nErrID, 
                RESPOND := TRUE );(* Send read response *)
                
    fbReadInd( CLEAR := TRUE ); (* Clear indication entry *)
END_IF

 

Here you can unpack the complete sources relating to the example application: Example application with the expanded ADS function blocks