Event-driven reading (with conversion to another type)

From TwinCAT 2.8 Build > 743 and above

Task

There are 4 variables of different types in the PLC. The variables are to be read out in the most effective way and the values are to be displayed on a Visual Basic form. A checkbox can be used to switch between two different connection modes (ADSTRANS_SERVERCYCLE or ADSTRANS_SERVERONCHA). Two buttons can be used to establish or break the connection to the PLC variables. 

The PLC variables are structured data types. The PLC sends these as a data block, for instance, to the AdsOcx client. However, the AdsOcx can pass to the VB event routine only variables of the specific data type as parameters, including the variant type. With the method AdsReadVarConvertConnect the type of the variant variable in the VB event routine can be set by the user beforehand. The event data is then copied into the variant variable by AdsOcx, and so passed to the VB event routine. A variant array can also represent a complex structure in the PLC. How much data can be copied into the individual variant elements depends on the type of the individual elements. A few exceptions need to be considered, such as occur with strings (the string length must be appropriately set beforehand) and boolean variables (where a 2-byte VB boolean is formed from 1 byte of data). 

The following PLC variables are to be displayed on the form:

The PLC application

VAR_GLOBAL
    eColors         : E_Colors := cWhite;
    st4Switches     : ST_4Switches;
    arr3Strings     : ARRAY[1..3] OF STRING :=1('First'), 1('Second'),1('Third');
    stBigStruct     : ST_BigStruct;
END_VAR

Online display of the PLC data:

The definition of the enumeration type:

TYPE E_Colors :
(
    cUnknown,
    cWhite := 1,
    cBlue := 2,
    cRed := 3,
    cBlack
);
END_TYPE

The definition of the structure with four boolean variables:

TYPE ST_4Switches :
STRUCT
    bLevel1 : BOOL;
    bLevel2 : BOOL;
    bLevel3 : BOOL;
    bLevel4 : BOOL;
END_STRUCT
END_TYPE

The definition of the structured data type:

TYPE ST_BigStruct :
STRUCT
    single : REAL;
    long : DINT;
    boolean : BOOL;
    stSub1 : ST_Sub1;
    counter : DINT;
    datetime : DT := DT#2003-01-20-15:12:44;
END_STRUCT
END_TYPE

This, in turn, has two substructures:

TYPE ST_Sub1 :
STRUCT
    bFirst : BOOL;
    bSecond : BOOL;
    bThird : BOOL;
    stSub2 : ST_Sub2;
END_STRUCT
END_TYPE
TYPE ST_Sub2 :
STRUCT
    integer : INT;
    double : LREAL;
    string20 : STRING(20) := 'Unknown';
END_STRUCT
END_TYPE

 

Visual Basic 6 program

Option Explicit
Dim adsErr As Long
Dim hConnect_EnumVar As Long
Dim hConnect_4Switches As Long
Dim hConnect_StringArray As Long
Dim hConnect_BigStruct As Long

The connection to the first PLC runtime system is established as the form is loaded:

Private Sub Form_Load()
    AdsOcx1.AdsAmsServerNetId = AdsOcx1.AdsAmsClientNetId
    AdsOcx1.AdsAmsServerPort = 801
    AdsOcx1.EnableErrorHandling = True
End Sub

A mouse click on the AdsReadVarConvertConnect button establishes a connection to the PLC variables. When successful, the AdsReadVarConvertConnect method returns a handle. Only via this handle the connection is identified and can be terminated later.  

1. The enumeration type in the PLC only occupies 2 bytes of memory. These two bytes are read into a long variable (four bytes) and are returned in the event function. Using the VB integer data type would be just as effective.

2. The 4 boolean values in the structure variable occupy 4 individual bytes of PLC memory in the PLC. These are read into a long variable, and returned as a long variable in the event function.

3. The strings in the array occupy a total of 243 bytes of memory in the PLC (defined string length + 1 byte for the null termination) *3. The length of the individual VB strings must correspond to the length of the PLC strings in order to be able to separate the individual strings. If the string has zero length, no event data is copied into a string variable. 

4. The structure variable can be read into a one-dimensional variant array. The individual array elements can be of different types. Before establishing the connection, however, the individual array elements must be initialized with the appropriate type. 

Private Sub cmdConnect_Click()
    Dim adsTransMode As ADSOCXTRANSMODE
    adsTransMode = IIf(chkTransMode.Value = vbChecked, ADSTRANS_SERVERCYCLE, ADSTRANS_SERVERONCHA)

    'Connects to enum var
    Dim convertedEnumVar As Long
    adsErr = AdsOcx1.AdsReadVarConvertConnect(".eColors", adsTransMode, 300, hConnect_EnumVar, convertedEnumVar, lblEnum)

    'Connects to struct with 4 boolean variables
    Dim converted4Switches As Long
    adsErr = AdsOcx1.AdsReadVarConvertConnect(".st4Switches", adsTransMode, 300, hConnect_4Switches, converted4Switches, chk4Switches)

    'Connects to array of strings
    Dim convertedStringArray(1 To 3) As String
    Dim i As Integer
    For i = LBound(convertedStringArray) To UBound(convertedStringArray)
        convertedStringArray(i) = String(81, "#")
    Next i
    adsErr = AdsOcx1.AdsReadVarConvertConnect(".arr3Strings", adsTransMode, 300, hConnect_StringArray, convertedStringArray, lstStringArray)


    'Connects to struct variable
    Dim convertedBigStruct(1 To 11) As Variant
    convertedBigStruct(1) = CSng(0)         'stBigStruct.single
    convertedBigStruct(2) = CLng(0)     'stBigStruct.long
    convertedBigStruct(3) = CBool(False)    'stBigStruct.boolean
    convertedBigStruct(4) = CBool(False)    'stBigStruct.stSub1.bFirst
    convertedBigStruct(5) = CBool(False)    'stBigStruct.stSub1.bSecond
    convertedBigStruct(6) = CBool(False)    'stBigStruct.stSub1.bThird
    convertedBigStruct(7) = CInt(0)     'stBigStruct.stSub1.stSub2.integer
    convertedBigStruct(8) = CDbl(0)     'stBigStruct.stSub1.stSub2.double
    convertedBigStruct(9) = CStr(String(21, "*"))'stBigStruct.stSub1.stSub2.string20
    convertedBigStruct(10) = CLng(0)        'stBigStruct.counter
    convertedBigStruct(11) = CDate(0)           'stBigStruct.datetime
    adsErr = AdsOcx1.AdsReadVarConvertConnect(".stBigStruct", adsTransMode, 300, hConnect_BigStruct, convertedBigStruct, lstBigStruct)

    cmdConnect.Enabled = False
    cmdDisconnect.Enabled = True
End Sub

A mouse click on the AdsDisconnectEx button will break the connections to the PLC variables:

Private Sub cmdDisconnect_Click()
    adsErr = AdsOcx1.AdsDisconnectEx(hConnect_EnumVar)
    adsErr = AdsOcx1.AdsDisconnectEx(hConnect_4Switches)
    adsErr = AdsOcx1.AdsDisconnectEx(hConnect_StringArray)
    adsErr = AdsOcx1.AdsDisconnectEx(hConnect_BigStruct)

    cmdConnect.Enabled = True
    cmdDisconnect.Enabled = False
End Sub

The AdsReadConvertConnectUpdate event routine. This event routine is called cyclically (if ADSTRANS_SERVERCYCLE is selected) or is only called when the value of the PLC variable has changed (if ADSTRANS_SERVERONCHA is selected). The hUser parameter can be used to be able to assign the event data to the appropriate control (label, checkbox, listbox).

Private Sub AdsOcx1_AdsReadConvertConnectUpdate(ByVal dateTime As Date, ByVal nMs As Long, ByVal hConnect As Long, data As Variant, Optional hUser As Variant)
    Dim i As Integer
    If TypeOf hUser Is CheckBox Then

        chk4Switches.Value = IIf(data = 0, vbUnchecked, vbChecked)
        chk4Switches.Caption = IIf(data = 0, "ALL disbled", "At least ONE enabled")

    ElseIf TypeOf hUser Is ListBox Then

        If hUser Is lstStringArray Then
            Call lstStringArray.Clear
            For i = LBound(data) To UBound(data)
                Call lstStringArray.AddItem("Type: " & TypeName(data(i)) & " Value: " & data(i))
            Next i
        ElseIf hUser Is lstBigStruct Then
            Call lstBigStruct.Clear
            For i = LBound(data) To UBound(data)
                Call lstBigStruct.AddItem("Type: " & TypeName(data(i)) & " Value: " & data(i))
            Next i
        End If

    Else 'lblEnum
        Dim objLabel As Label
        Set objLabel = hUser
        objLabel.Caption = "eColors: " & data
    End If
End Sub

Language / IDE

Unpack sample program

Visual Basic 6

ADS-OCX Sample09.exe