Synchron/Asynchron/Connected auf SPS-Variablen zugreifen
Systemvoraussetzungen:
- Delphi 5.0 oder höher;
- TwinCAT v2.9 oder höher;
Aufgabe
Das Beispielprogramm zeigt, wie Methoden und Events des AdsOcx in einer Delphi-Anwendung benutzt werden können. Dabei werden die unterschiedlichsten Zugriffsarten (Synchron/Asynchron/Connected) auf die SPS-Variablen vorgestellt. In dem SPS-Programm wurde eine Integer-Variable auf der Adresse 100 im Merkerbereich der Prozessdaten der SPS definiert. Auf die SPS-Variable soll über die unterschiedlichsten Zugriffsarten schreibend oder lesend aus der Delphi-Applikation zugegriffen werden.
Beschreibung
Auf die SPS-Variablen ist über das AdsOcx ein Synchroner-, Asynchroner- oder Connected-Zugriff möglich. Bei einem synchronen Zugriff wird die Applikation so lange angehalten, bis die angeforderten Daten vorliegen. Bei einem asynchronen Zugriff wird eine Anforderung (Request) an die SPS gesendet und die Ausführung der Windows-Applikation fortgesetzt. In der Windows-Applikation wird dann eine Callback-Funktion aufgerufen, wenn die angeforderten Daten vorliegen. Bei dem Connected-Zugriff kann in der Windows-Applikation eine Event-Funktion aufgerufen werden, wenn sich der Wert der SPS-Variablen geändert hat.
Delphi 5 Programm
In der Event-Funktion OnFormCreate wird über die Methode AdsCreateVarHandle ein Handle für den Sysmbolnamen der SPS-Variablen angefordert. Das Handle wird dann in der Beispielapplikation für den schreibenden oder lesenden Zugriff auf die SPS-Variable benutzt. In der Event-Funktion OnDestroy wird das Handle beim Beenden der Applikation mit der Methode AdsDeleteVarHandle freigegeben.
var
Form1 : TForm1;
varName :WideString; {PLC variable symbol name}
varValue :Smallint; {PLC variable value}
varHandle :integer; {PLC variable handle}
hConnect :integer; {PLC variable connection handle}
adsResult :integer; {Ads result}
implementation
{$R *.DFM}
procedure TForm1.OnFormCreate(Sender: TObject);
begin
AdsOcx1.AdsAmsServerNetId := AdsOcx1.AdsAmsClientNetId; {Sets PLC server network adress}
AdsOcx1.AdsAmsServerPort := 801; {Sets the PLC run time system}
varName := 'MAIN.VARINT16';
varValue := 0;
varHandle := 0;
hConnect := 0;
adsResult := AdsOcx1.AdsCreateVarHandle( varName, varHandle ); {creates variable handle}
if adsResult = 0 then
LabelVarHandle.Font.Color := clBlue
else
LabelVarHandle.Font.Color := clRed;
LabelVarHandle.Caption := Format( 'AdsCreateVarHandle adsResult:%d varName:%s Handle:%d',[adsResult, varName, varHandle] );
end;
procedure TForm1.OnFormDestroy(Sender: TObject);
begin
adsResult := AdsOcx1.AdsDeleteVarHandle( varHandle );
end;
Synchroner Zugriff
Bei einem Mausklick auf einen der Buttons in der Gruppe SYNCHRONOUS wird der Wert der SPS-Variablen synchron gelesen bzw. geschrieben und als Text auf der Form ausgegeben. Es kann auf zweifache Weise auf die SPS-Variable zugegriffen werden: Über den Variablen-Namen oder über die Variablen-Adresse.
Zugriff über die Variablen-Adresse
procedure TForm1.OnSyncReadByAddrClick(Sender: TObject);
begin
adsResult := AdsOcx1.AdsSyncReadIntegerReq( $00004020, 100, 2, varValue );
LabelSyncRetData.Caption:=Format( 'adsResult:%d Value:%d',[adsResult, varValue] );
end;
procedure TForm1.OnSyncWriteByAddrClick(Sender: TObject);
begin
varValue := 100;
adsResult := AdsOcx1.AdsSyncWriteIntegerReq( $00004020, 100, 2, varValue );
LabelSyncRetData.Caption:=Format( 'adsResult:%d', [adsResult] );
end;
Zugriff über den Variablen-Namen
Bei einem Zugriff über den Variablen-Namen wird das entsprechende Handle der SPS-Variablen als Parameter in der Methode AdsSyncReadIntegerVarReq bzw. AdsSyncWriteIntegerVarReq benutzt. Das Handle der SPS-Variablen wurde in der OnCreate Event-Funktion beim Applikationsstart angefordert.
procedure TForm1.OnSyncReadByNameClick(Sender: TObject);
begin
adsResult := AdsOcx1.AdsSyncReadIntegerVarReq( varHandle, 2, varValue );
LabelSyncRetData.Caption:=Format( 'adsResult:%d Value:%d', [adsResult, varValue] );
end;
procedure TForm1.OnSyncWriteByNameClick(Sender: TObject);
begin
varValue := 200;
adsResult := AdsOcx1.AdsSyncWriteIntegerVarReq( varHandle, 2, varValue );
LabelSyncRetData.Caption:=Format( 'adsResult:%d', [adsResult] );
end;
Asynchroner Zugriff
Über die Methoden AdsReadIntegerReq und AdsWriteIntegerReq kann auf die SPS-Variable asynchron zugegriffen werden.
procedure TForm1.OnAsyncReadByAddrClick(Sender: TObject);
var varInvokeId :integer;
begin
varInvokeId := 33;
adsResult := AdsOcx1.AdsReadIntegerReq( varInvokeId, $00004020, 100, 2 );
LabelAsyncRetData.Caption:=Format( 'adsResult:%d', [adsResult] );
end;
procedure TForm1.OnAsyncWriteByAddrClick(Sender: TObject);
var varInvokeId :integer;
begin
varInvokeId := 44;
varValue := 300;
adsResult := AdsOcx1.AdsWriteIntegerReq( varInvokeId, $00004020, 100, 2, varValue );
LabelAsyncRetData.Caption:=Format( 'adsResult:%d', [adsResult] );
end;
Die Ausführung der Delphi-Applikation wird nach einem asynchronen Zugriff fortgesetzt und beim Vorliegen der Rückgabeparameter eine Event-Funktion in der Windows-Applikation aufgerufen. In unserem Beispiel wird beim Lesen der SPS-Variablen die Event-Funktion AdsReadIntegerConf und beim Schreiben der SPS-Variablen die Event-Funktion AdsWriteConf aufgerufen.
procedure TForm1.AdsOcx1AdsReadIntegerConf(Sender: TObject; nInvokeId,
nResult, cbLength: Integer; var pData: Smallint);
begin
LabelAsyncEventData.Caption :=Format('nInvokeId:%d nResult:%d cbLength:%d pData:%d',
[nInvokeId, nResult, cbLength, pData]);
end;
procedure TForm1.AdsOcx1AdsWriteConf(Sender: TObject; nInvokeId,
nResult: Integer);
begin
LabelAsyncEventData.Caption :=Format('nInvokeId:%d nResult:%d', [nInvokeId, nResult]);
end;
Connected Zugriff
Bei dem Connected-Zugriff wird eine "Verbindung" zu der SPS-Variablen aufgebaut. In Abhängigkeit von den Parametern (ADSTRANS_SERVERCYCLE oder ADSTRANS_SERVERONCHA) werden die Event-Funktionen zyklisch, oder bei einer Änderung der SPS-Variablen aufgerufen.
In der Beispielapplikation wird bei einem Mausklick auf den Button Connected read by address die Methode AdsReadIntegerConnect aufgerufen und bei einem Mausklick auf den Button Connected read by variable name die Methode AdsReadIntegerVarConnect aufgerufen.
procedure TForm1.OnConReadByAddrClick(Sender: TObject);
begin
adsResult := AdsOcx1.AdsReadIntegerConnect( $00004020, 100, 2, ADSTRANS_SERVERCYCLE, 220, varValue );
LabelConRetData.Caption:=Format( 'adsResult:%d', [adsResult] );
end;
procedure TForm1.OnConReadByNameClick(Sender: TObject);
begin
adsResult := AdsOcx1.AdsReadIntegerVarConnect( varName, 2, ADSTRANS_SERVERCYCLE, 220, varValue );
LabelConRetData.Caption:=Format( 'adsResult:%d', [adsResult] );
end;
Bei Erfolg wird in der Delphi-Applikation die Event-Funktion AdsReadConnectUpdate aufgerufen, unabhängig davon welche der beiden Methoden für den Verbindungsaufbau benutzt wurde.
procedure TForm1.AdsOcx1AdsReadConnectUpdate(Sender: TObject; nIndexGroup,
nIndexOffset: Integer);
begin
LabelConEventData.Caption := Format('nIndexGroup:%d nIndexOffset:%d Value:%d',
[nIndexGroup, nIndexOffset, varValue]);
end;
Über die Methode AdsReadIntegerDisconnect kann die Verbindung zu der SPS-Variablen abgebaut werden.
procedure TForm1.OnDisconnectReadClick(Sender: TObject);
begin
adsResult := AdsOcx1.AdsReadIntegerDisconnect( varValue );
LabelConRetData.Caption:=Format( 'adsResult:%d', [adsResult] );
end;
ConnectEx-Methoden (Connected-Zugriff mit einem Benutzer-Handle)
Mit der Hilfe der ConnectEx-Methoden kann ähnlich wie bei den Connect-Methoden ein Connected-Zugriff zu den SPS-Variablen aufgebaut werden. Die ConnectEx-Methoden haben den Vorteil, dass bei dem Verbindungs-Aufbau ein benutzerdefiniertes Handle als Parameter in der Connect-Methode übergeben werden kann. Dieses Handle kann dann in der Event-Funktion ausgewertet und dazu benutzt werden, um die SPS-Variablen zu identifizieren, für die die Event-Funktion aufgerufen wurde.
Bei einem Mausklick auf den Button ConnectEx wird in der OnConnectExClick-Routine die Methode AdsReadVarConnectEx2 aufgerufen.
procedure TForm1.OnConectExClick(Sender: TObject);
var hUser :integer;
begin
{disconnect old connection}
if hConnect <> 0 then
begin
adsResult := AdsOcx1.AdsDisconnectEx( hConnect );
if adsResult = 0 then
hConnect := 0;
end;
hUser := 7; {create user handle}
adsResult := AdsOcx1.AdsReadVarConnectEx2( varName, ADSTRANS_SERVERCYCLE, 220, hConnect, hUser );
LabelConExRetData.Caption:=Format( 'adsResult:%d hConnect:%d', [adsResult, hConnect] );
end;
Wurde die Verbindung erfolgreich aufgebaut, dann werden in der Event-Funktion AdsReadConnectUpdateEx2 die Parameter als Text auf der Form ausgegeben.
procedure TForm1.AdsOcx1AdsReadConnectUpdateEx2(Sender: TObject;
dateTime: TDateTime; nMs, hConnect: Integer; var data,
hUser: OleVariant);
begin
LabelConExEventData.Caption :=Format('Date/Time:%s nMs:%d hConnect:%d data:%d hUser:%d',
[ TimeToStr(dateTime), nMs, hConnect, integer(data), integer(hUser)]);
end;
Bei einem Mausklick auf den Button DisconnectEx wird die Methode AdsDisconnectEx aufgerufen und die Verbindung zu der SPS-Variablen abgebaut.
procedure TForm1.OnDisconnectExClick(Sender: TObject);
begin
adsResult := AdsOcx1.AdsDisconnectEx( hConnect );
if adsResult = 0 then
hConnect := 0;
LabelConExRetData.Caption:=Format( 'adsResult:%d', [adsResult] );
end;
Bemerkung:
Bei der Einbindug des ADS-OCX in Delphi-Applikationen wurde festgestellt, dass von der Entwicklungsumgebung von Delphi fehlerhafte Prototypen (genauer: fehlerhafte Parameterübergabe bei den OleVariant-Typen) der Event-Funktion AdsReadConnectUpdateEx generiert wurde. Aus diesem Grund wurde das ADS-OCX um eine neue Methode AdsReadVarConnectEx2 und eine dazugehörende Event-Funktion AdsReadConnectUpdateEx2 ergänzt. In der neuen Event-Funktion werden die OleVariant-Parameter per Referenz statt per Wert übergeben.
Other
procedure TForm1.Exit1Click(Sender: TObject);
begin
Close();
end;
procedure TForm1.Properties1Click(Sender: TObject);
begin
AdsOcx1.BrowseProperties();
end;
procedure TForm1.About1Click(Sender: TObject);
begin
AdsOcx1.AboutBox();
end;
Initialization
IsMultiThread := True;// Setting this system variable makes Delphi's memory manager thread-safe
SPS Programm
PROGRAM MAIN
VAR
VARINT16 AT%MB100:INT;
END_VAR
Sprache / IDE | Beispielprogramm auspacken |
---|---|
Delphi XE2 | |
Delphi 5 oder höher (classic) |