Ereignisgesteuertes Lesen von SPS Variablen
Voraussetzungen:
- Delphi 5.0 oder höher;
- TwinCAT 2.9 oder höher;
- Die Typbibliothek der TcAdsDll.dll muss importiert werden (TcAdsDll_TLB.pas Unit ). Abhängig von der Delphi-Version müssen teilweise manuelle Anpassungen gemacht werden um diese fehlerfrei übersetzen zu können.
In der FormCreate-Ereignisfunktion wird mit CoTcClient.Create eine Verbindung zum Server auf dem lokalen System aufgebaut. Mit Hilfe der Methode Connect wird dann eine Verbindung zum ersten Laufzeitsystem der SPS (port 801) auf dem lokalen Rechner (netid = '0.0.0.0.0.0') hergestellt. Beim Betätigen des Start-Buttons wird mit der Methode AddDeviceNotification eine Verbindung zu den SPS-Variablen hergestellt. Bei einer Änderung der SPS-Variablen wird von dem Server die Funktion DeviceNotification der _ITcAdsSyncEvents-Schnittstelle aufgerufen. Damit Events an den Client gesendet werden können, muss diese Schnittstelle von dem Client implementiert werden. Ausserdem muss der Server über deren existenz informiert werden. Dies geschieht durch den Aufruf der InterfaceConnect-Prozedur. Beim Betätigen des Stop-Buttons werden die Verbindungen mit der Methode DelDeviceNotification wieder aufgehoben.
Das Delphi Programm
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls, StdCtrls, TcAdsDll_TLB, OleServer, ComObj,activex, Math;
type
TForm1 = class( TForm, IUnknown, _ITcAdsSyncEvents )
Label1: TLabel;
Label2: TLabel;
Button1: TButton;
Button2: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
TcClient : ITcClient;
TcAdsSync : ITcAdsSync;
dwCookie : integer;
hInteger, hDouble : integer;
serverAddr : AmsNetId;
function DeviceNotification(var pTime: TimeStamp; hNotification: Integer; cbLen: Integer; var pData: Byte): HResult; stdcall;
end;
type
PINT = ^Smallint;
PLREAL= ^Double;
var
Form1: TForm1;
implementation
{$R *.DFM}
/////////////////////////////////////////////////////////////////////////
procedure TForm1.FormCreate(Sender: TObject);
begin
serverAddr.b[0] := 0;
serverAddr.b[1] := 0;
serverAddr.b[2] := 0;
serverAddr.b[3] := 0;
serverAddr.b[4] := 0;
serverAddr.b[5] := 0;
Button1.Enabled := True;
Button2.Enabled := False;
try
TcClient := CoTcClient.Create();
try
OleCheck(TcClient.Connect( serverAddr, 801,TcAdsSync));
InterfaceConnect(TcAdsSync ,IID__ITcAdsSyncEvents,self as IUnknown, dwCookie);
except
ShowMessage('TcClient.Connect() failed!');
end;
except
ShowMessage('CoTcClient.Create() failed!');
end;
end;
/////////////////////////////////////////////////////////////////////////
procedure TForm1.FormDestroy(Sender: TObject);
begin
if hInteger <> 0 then
OleCheck(TcAdsSync.DelDeviceNotification(hInteger));
if hDouble <> 0 then
OleCheck(TcAdsSync.DelDeviceNotification(hDouble));
InterfaceDisconnect(TcAdsSync,IID__ITcAdsSyncEvents, dwCookie);
end;
/////////////////////////////////////////////////////////////////////////
procedure TForm1.Button1Click(Sender: TObject);
begin
hInteger := 0;
hDouble := 0;
try
OleCheck(TcAdsSync.AddDeviceNotification($4020, 2, sizeof(Smallint), ADSTRANS_SERVERONCHA, 0, 1000000, hInteger ));
OleCheck(TcAdsSync.AddDeviceNotification($4020, 12, sizeof(Double), ADSTRANS_SERVERONCHA, 0, 1000000, hDouble ));
Button1.Enabled := False;
Button2.Enabled := True;
except
ShowMessage('TcAdsSync.AddDeviceNotification() failed!');
end;
end;
/////////////////////////////////////////////////////////////////////////
procedure TForm1.Button2Click(Sender: TObject);
begin
try
OleCheck(TcAdsSync.DelDeviceNotification(hInteger));
OleCheck(TcAdsSync.DelDeviceNotification(hDouble));
Button1.Enabled := True;
Button2.Enabled := False;
except
ShowMessage('TcAdsSync.DelDeviceNotification() failed!');
end;
hInteger := 0;
hDouble := 0;
end;
/////////////////////////////////////////////////////////////////////////
function TForm1.DeviceNotification(var pTime: TimeStamp; hNotification: Integer; cbLen: Integer; var pData: Byte): HResult; stdcall;
var
SystemTime, LocalTime : _SYSTEMTIME;
TimeZoneInformation : _TIME_ZONE_INFORMATION;
stamp : TDateTime;
begin
FileTimeToSystemTime(_FILETIME(pTime), SystemTime);
GetTimeZoneInformation(TimeZoneInformation);
SystemTimeToTzSpecificLocalTime(@TimeZoneInformation, SystemTime, LocalTime);
stamp := SystemTimeToDateTime(LocalTime);
if hNotification = hInteger then
Label1.Caption := Format( 'PLCIntVar, %s %s, hNot:%d, cbLen:%d, data:%d',[DateToStr(stamp), TimeToStr(stamp), hNotification, cbLen, PINT(Addr(pData))^] )
else
Label2.Caption := Format( 'PLCLRealVar, %s %s, hNot:%d, cbLen:%d, data:%f',[DateToStr(stamp), TimeToStr(stamp), hNotification, cbLen, PLREAL(Addr(pData))^] );
Result := S_OK;
end;
initialization
IsMultiThread := True;
end.
SPS-Programm
PROGRAM MAIN
VAR
PLCBoolVar AT %MX0.0 : BOOL := TRUE;
PLCIntVar AT %MB2 : INT := 75;
PLCDIntVar AT %MB4 : DINT := 43234532;
PLCRealVar AT %MB8 : REAL := 3.1415;
PLCLRealVar AT %MB12 : LREAL := 3.141592654;
END_VAR
PLCLRealVar := PLCLRealVar +1;
PLCIntVar :=PLCIntVar +1;
Sprache / IDE | Beispielprogram auspacken |
---|---|
Delphi XE2 | |
Delphi 5 oder höher (classic) |