Ereignisgesteuertes Lesen (mit Konvertierung in einen anderen Typ)

Ab TwinCAT 2.8 Build > 743 und höher

Aufgabe

In der SPS befinden sich 4 Variablen vom unterschiedlichen Typ. Die Variablen sollen auf möglichst effektive Weise ausgelesen und die Werte auf einer Visual Basic Form dargestellt werden. Mit einer Checkbox kann zwischen zwei Verbindungsmodi (ADSTRANS_SERVERCYCLE oder ADSTRANS_SERVERONCHA) umgeschaltet werden. Mit zwei Buttons kann die Verbindung zu den SPS-Variablen aufgebaut oder abgebaut werden. 

Bei den SPS-Variablen handelt es sich um strukturierte Datentypen. Diese werden z. B. von der SPS als ein Datenblock an den AdsOcx-Client gesendet. Das AdsOcx kann aber an die VB-Ereignisroutine nur Variablen vom bestimmten Datentyp als Parameter übergeben, darunter den Variant-Typ. Mit der Methode AdsReadVarConvertConnect kann der Typ der Variant-Variablen in der VB-Ereignisroutine vom Benutzer vorher festgelegt werden. Die Ereignisdaten werden dann vom AdsOcx in die Variant-Variable kopiert und so an die VB-Ereignisroutine übergeben. Ein Variant-Array kann auch eine komplexe Struktur in der SPS abbilden. Wieviele Daten in die einzelnen Variant-Elemente kopiert werden, wird durch den Typ der einzelnen Elemente festgelegt. Einige Ausnahmen z. B. bei Strings (die Stringlänge muss vorher entsprechend gesetzt werden)  und boolschen Variablen (aus 1 Byte Daten wird ein 2 Byte VB-Boolean ) sind dabei zu beachten. 

Folgende SPS-Variablen sollen auf der Form angezeigt werden:

Die SPS-Applikation

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-Ansicht der SPS-Daten:

die Definition des Aufzählungstyps:

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

Die Definition der Struktur mit 4 boolschen Variablen:

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

Die Definition des Strukturierten-Datentyps:

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

Dieser besitzt wiederum 2 Unterstrukturen:

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 Programm

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

Beim Laden der Form wird eine Verbindung zum ersten SPS-Laufzeitsystem aufgebaut:

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

Bei einem Mausklick auf den AdsReadVarConvertConnect - Button wird eine Verbindung zu den SPS-Variablen aufgebaut. Beim Erfolg liefert die Methode AdsReadVarConvertConnectein Handle zurück. Nur über dieses Handle wird die Verbindung identifiziert und kann später abgebaut werden.  

1. Der Aufzählungstyp in der SPS belegt nur 2 Byte Speicher. Diese 2 Byte werden in eine Long-Variable (4 Byte) eingelesen und in der Ereignisfunktion zurückgeliefert. Man könnte aber genauso gut den VB Integer-Datentyp verwenden.

2. Die 4 boolschen Werte der Strukturvariablen belegen in der SPS 4 einzelne Bytes SPS-Speicher. Diese werden in eine Long-Variable eingelesen und in der Ereignisfunktion als eine Long-Variable zurückgeliefert.

3. Die Strings in dem Array belegen in der SPS insgesamt 243 Byte Speicher (Definierte Stringlänge + 1 Byte für die Nullterminierung) *3. Die Länge der einzelnen VB-Strings muss der Länge der SPS-Strings entsprechen, um die einzelnen Strings trennen zu können. Besitzt der String die Länge Null, werden keine Ereignisdaten in eine Stringvariable hineinkopiert. 

4. Die Strukturvariable kann in ein eindimensionales Variant-Array eingelesen werden. Die einzelnen Arrayelemente können vom unterschiedlichen Typ sein. Vor dem Aufbau der Verbindung müssen aber die einzelnen Arrayelemente mit entsprechendem Typ initialisiert werden. 

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

Bei einem Mausklick auf AdsDisconnectEx - Button werden die Verbindungen zu den SPS-Variablen getrennt:

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

Die Ereignisroutine AdsReadConvertConnectUpdate. Diese Ereignisroutine wird zyklisch (wenn ADSTRANS_SERVERCYCLE ausgewählt) oder immer nur dann aufgerufen, wenn sich der Wert der SPS-Variablen geändert hat (bei ADSTRANS_SERVERONCHA). Der hUser Parameter kann dafür benutzt werden, um die Ereignisdaten dem passenden Control (Label, CheckBox, ListBox ) zuordnen zu können.

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

Sprache / IDE

Beispielprogramm auspacken

Visual Basic 6

ADS-OCX Sample09.exe