Ereignisgesteuertes Lesen von SPS Variablen

Voraussetzungen:

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.

Ereignisgesteuertes Lesen von SPS Variablen 1:

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

Sample02.zip

Delphi 5 oder höher (classic)

Sample02.exe