Beispiel 2: ADSWRITE-Indication/-Response

Die VB-Applikation sendet ein Array mit 10 Integer-Werten zu der SPS-Task eines Buscontrollers BC9000. In der SPS-Task des Buscontrollers sollen die empfangenen Daten in eine Array-Variable zur weiteren Verarbeitung kopiert werden. Um mit dem Buscontroller kommunizieren zu können, benutzt die VB-Applikation das ActiveX Control: AdsOcx. Der Buscontroller muss als Remote-PC im TwinCAT-System-Menü eingetragen werden um die Anfragen der VB-Applikation zu dem Buscontroller übers Ethernet routen zu können. Hier können Sie die kompletten Sourcen zu der Beispielapplikation entpacken.

BC9000 als Remote-PC im TwinCAT System Menü eintragen

Beispiel 2: ADSWRITE-Indication/-Response 1:

Das TwinCAT Systemmenü kann mit einem Mausklick auf das TwinCAT Icon -> Eigenschaften in der Taskleiste erreicht werden. Auf dem AMS Router-Reiter wählen Sie Add. In dem Dialog geben Sie einen beliebigen Namen für den Remote-PC ein. Unter AMS Net Id wird die Netzwerkadresse eingetragen. Diese setzt sich aus der IP-Adresse des BC9000 und zwei weiteren Stellen zusammen.:"1.1". Unter Address wird noch mal die IP-Adresse des BC9000 eingetragen. Die IP-Adresse muss der Adresse entsprechen, die mit den DIP-Schaltern auf dem Buscontroller eingestellt wurde. 

Die VB-Applikation

Beispiel 2: ADSWRITE-Indication/-Response 2:

 

In der Form_Load-Routine wird eine Verbindung zu der SPS-Task des Buscontrollers BC9000 aufgebaut ( Port 800 und Netzwerkadresse: "172.16.17.63.1.1" ). Die ersten vier Stellen der Netzwerkadresse entsprechen der IP-Adresse des Buscontrollers. Der gewünschte Dienst in der SPS-Task wird in dem Index-Group und Index-Offset Parameter verschlüsselt. Z.B.:

Die VB-Applikation benutzt die Methode AdsSyncWriteReq um 20 Byte Daten an den Buscontroller zu senden. Die zuletzt gesendeten Werte werden zur Kontrolle einer Liste hinzugefügt.  

Beispiel 2: ADSWRITE-Indication/-Response 3:

Damit die Requests an die SPS-Task weiter geleitet werden, muss in dem Index-Group-Parameter das höchstwertige Bit gesetzt werden. Die Werte der Index-Group und Index-Offset Parameter können frei definiert werden. In unserem Beispiel erkennt der Buscontroller anhand der Index-Group und Index-Offset-Parameter, dass er die empfangenen Daten in ein Array kopieren soll.

Option Explicit
    
Dim AdsResult     As Integer
Dim arrData(0 To 9)   As Integer

Private Sub cmdWrite_Click()
    Call List1.Clear
    
    Dim i As Long
    For i = LBound(arrData) To UBound(arrData)
    arrData(i) = arrData(i) + 1 'change values
    Call List1.AddItem("arrData(" & i & ") = " & arrData(i))
    Next i
    
    'calculate the byte length parameter
    Dim cbWriteSize As Long
    cbWriteSize = (UBound(arrData) - LBound(arrData) + 1) * LenB(arrData(LBound(arrData)))
    
    AdsResult = AdsOcx1.AdsSyncWriteReq(&H80000005, &H7, cbWriteSize, arrData) 'send data to PLC
    Label1.Caption = "Ads result: " & AdsResult
    
End Sub

Private Sub Form_Load()
    AdsOcx1.AdsAmsServerNetId =  "172.16.17.63.1.1"   
    AdsOcx1.AdsAmsServerPort = 800 'PLC task number of the BC9000 buscontroller'
    
    Dim i As Long
    For i = LBound(arrData) To UBound(arrData)
    arrData(i) = i    'init data
    Next i
End Sub

Das SPS Programm

Erstellen Sie ein neues SPS-Projekt für den Buscontroller. Unter Bibliotheksverwaltung müssen folgende SPS-Bibliotheken für den Buscontroller eingebunden werden: Standard.lb6, PlcHelperBC.lb6 und TcAdsBC.lb6. 

In der SPS-Task des Buscontrollers wird eine Instanz von dem ADSWRITEIND-Funktionsbaustein benutzt um die Daten zu empfangen und eine Instanz von dem ADSWRITERESBC-Funkstionbaustein um den Empfang der Daten zu quittieren. Die Anfragen werden in der SPS-Task von dem ADSWRITEIND-Funktionsbaustein als sogenannte Indications abgefangen. Danach werden die Parameter Index-Group, Index-Offset und die gesendete Datenlänge auf Gültigkeit überprüft und die empfangenden Daten in eine Array-Variable kopiert. Als Nächstes wird ein Response von einer Instanz des ADSWRITERESBC-Funktionsbausteins an den Aufrufer (eventuell mit einem Fehlercode) zurückgesendet. Damit wird der VB-Applikation mitgeteilt, daß die gesendeten Daten erfolgreich empfangen wurden. 

Beispiel 2: ADSWRITE-Indication/-Response 4:

Mit der steigenden Flanke am CLEAR-Eingang des ADSWRITEIND-Funktionsbausteins wird der Adresspointer auf die zuletzt gesendeten Daten ungültig ( == NULL ). Aus diesem Grund werden die gesendeten Daten zuerst in die SPS-Variable kopiert und dann der CLEAR-Eingang auf TRUE gesetzt. Zum Schluss werden die Flags CLEAR und RESPOND rückgesetzt, um weitere Indications verarbeiten zu können.

PROGRAM MAIN
VAR
    fbWRITEIND              : ADSWRITEIND;
    fbWRITERESBC            : ADSWRITERESBC;

    szNetId             : STRING(23);
    Port                : UINT;
    InvokeId                : UDINT;
    idxGrp              : UDINT;
    idxOffs             : UDINT;
    cbLength                : UDINT;
    ErrorNumber             : UDINT;

    arrInt              : ARRAY[0..9] OF INT;
END_VAR

 

fbWRITEIND( );
fbWRITERESBC( );

IF ( fbWRITEIND.VALID ) THEN
    szNetId         := fbWRITEIND.NETID;
    Port        := fbWRITEIND.PORT;
    InvokeId        := fbWRITEIND.INVOKEID;
    idxGrp      := fbWRITEIND.IDXGRP;
    idxOffs         := fbWRITEIND.IDXOFFS;
    cbLength        := fbWRITEIND.LENGTH;
    ErrorNumber     := 0;


    CASE idxGrp OF
        16#80000005:

            CASE idxOffs OF
                16#00000007:
                    IF  cbLength <= SIZEOF( arrInt ) THEN
                        IF ( MEMCPY( ADR( arrInt ), fbWRITEIND.DATAADDR, UDINT_TO_INT(cbLength) ) =  0 ) THEN
                            ErrorNumber := 4000; (*MEMCPY fail*)
                        END_IF
                    ELSE
                        ErrorNumber := 1798;  (* ADS error: invalid parameter value(s)*)
                    END_IF
            ELSE
                ErrorNumber := 1795;    (*ADS error: Invalid index offset*)
            END_CASE

    ELSE
        ErrorNumber := 1794; (*ADS error: invalid index group*)
    END_CASE


    fbWRITEIND(  CLEAR := TRUE );       (*clear indication entry*)


    fbWRITERESBC.NETID := szNetId;
    fbWRITERESBC.PORT := Port;
    fbWRITERESBC.INVOKEID := InvokeId;
    fbWRITERESBC.RESULT := ErrorNumber;
    fbWRITERESBC( RESPOND :=  TRUE );       (*send response*)

END_IF

(*reset fb's*)
IF NOT fbWRITERESBC.BUSY THEN
    fbWRITEIND( CLEAR := FALSE );
    fbWRITERESBC( RESPOND := FALSE );
END_IF

Hier können Sie die kompletten Sourcen zu der Beispielapplikation entpacken: Beispielapplikation mit den erweiterten ADS-Funktionsbausteinen