Liste der deklarierten Variablen eines ADS-Gerätes auslesen
Systemvoraussetzungen:
- Delphi 5.0 oder höher;
- TwinCAT v2.9 oder höher;
Aufgabe
Das Beispielprogramm zeigt, wie mit den Methoden: AdsReadSymbolInfo und AdsEnumSymbols die Liste der deklarierten Variablen eines ADS-Gerätes ausgelesen werden kann. Bei einem Mausklick auf den Read Symbol Info-Button sollen die Symbolinformationen des ersten SPS-Laufzeitsystems (Port 801) oder einer zusätzlichen Task im TwinCAT System Manager (Port 301) gelesen und in einer Tabelle dargestellt werden.
Beschreibung
Symbolkonfiguration für das SPS-Laufzeitsystem
Um auf die Symbolinformationen eines SPS-Laufzeitsystems zugreifen zu können, muss die Symbolgenerierung für die SPS-Variablen oder Strukturen aktiviert werden und die Symbolinformationen während des Projekt-Downloads in das SPS-Laufzeitsystem geladen werden. In der TwinCAT PLC Control können die notwendigen Einstellungen für den Symbol-Download über den Optionsdialog der Kategorie TwinCAT vorgenommen werden. Das erste Laufzeitsystem der SPS wird über die Portnummer 801 angesprochen.
Symbolkonfiguration der zusätzlichen Task im TwinCAT System Manager
Im TwinCAT System Manager kann eine zusätzliche Task eingefügt und konfiguriert werden. Die Variablen der zusätzlichen Task können mit anderen Variablen (z. B. mit den SPS-Variablen oder IO-Variablen eines Busklemmen-Controllers) verknüpft werden. Um auf die Symbolinformationen der zusätzlichen Task zugreifen zu können, muss die Checkbox für die Symbolgenerierung in dem Konfigurationsdialog der Task-Einstellungen aktiviert werden. Das zusätzliche Task wird über die Portnummer 301angesprochen.
Delphi 5 Programm
In der OnFormCreate-Eventfunktion wird die Verbindung zu dem ersten Laufzeitsystem der SPS (Port 801) auf dem lokalen PC hergestellt. Gleichzeitig wird die ListView-Komponente und die benötigten Variablen initialisiert. Bei einem Mausklick auf den Read Symbol Info-Button wird die Methode ReadSymInfoButtonClick aufgerufen. In dieser Methode wird zuerst über den Methodenaufruf: AdsReadSymbolInfo die Anzahl der verfügbaren Symbole ermittelt und dann in einer For-Schleife die Symbolinformationen für jede einzelne Symbolvariable gelesen. Die Werte werden dann über eine Hilfs-Prozedur AddListViewItem in die ListeView-Komponente eingefügt. Die Methode AdsEnumSymbols besitzt einen booleschen Flag: bNext. Ist dieser Flag auf FALSE gesetzt, dann werden die Symbolinformationen des ersten Symbols und bei bNext=TRUE aller weiteren Symbole gelesen. Um die Symbolinformationen der zusätzlichen Task im TwinCAT System Manager lesen zu können, muss die AdsAmsServerPort -Eigenschaft der AdsOcx-Komponente auf 301 gesetzt werden. Die Portnummer können Sie zur Laufzeit über die Eigenschaften-Seite der AdsOcx-Komponente setzen. Die Eigenschaften-Seite kann in der Beispielapplikation über das Menü: AdsOcx->Properties aufgerufen werden.
unit SampleUnit;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, OleCtrls, ADSOCXLib_TLB, ExtCtrls, ComCtrls, Menus;
type
TForm1 = class(TForm)
AdsOcx1: TAdsOcx;
MainMenu1: TMainMenu;
File1: TMenuItem;
Exit1: TMenuItem;
AdsOcx2: TMenuItem;
Properties1: TMenuItem;
About1: TMenuItem;
ReadSymInfoButton: TButton;
ListView1: TListView;
StatusBar1: TStatusBar;
procedure OnFormCreate(Sender: TObject);
procedure Exit1Click(Sender: TObject);
procedure Properties1Click(Sender: TObject);
procedure About1Click(Sender: TObject);
procedure ReadSymInfoButtonClick(Sender: TObject);
private
{ Private declarations }
procedure CreateColumns(Sender: TObject);
procedure AddListViewItem(Sender: TObject; strSymbolName, strComment :WideString; nSymbolType, cbSymbolSize , nIndexGroup, nIndexOffset : integer);
public
{ Public declarations }
end;
var
Form1 : TForm1;
adsResult : integer; {Ads result}
nSymbols : integer;
nSymByteSize : integer;
implementation
{$R *.DFM}
procedure TForm1.CreateColumns(Sender: TObject);
var ListColumn :TListColumn;
begin
ListView1.ViewStyle := vsReport;
ListView1.Align := alBottom;
ListColumn := ListView1.Columns.Add();
ListColumn.Width := 50;
ListColumn.Caption := 'No';
ListColumn.Alignment := taLeftJustify;
ListColumn := ListView1.Columns.Add();
ListColumn.Width := 200;
ListColumn.Caption := 'Symbol name';
ListColumn.Alignment := taLeftJustify;
ListColumn := ListView1.Columns.Add();
ListColumn.Width := 100;
ListColumn.Caption := 'Type';
ListColumn.Alignment := taLeftJustify;
ListColumn := ListView1.Columns.Add();
ListColumn.Width := 100;
ListColumn.Caption := 'Size';
ListColumn.Alignment := taLeftJustify;
ListColumn := ListView1.Columns.Add();
ListColumn.Width := 100;
ListColumn.Caption := 'Comment';
ListColumn.Alignment := taLeftJustify;
ListColumn := ListView1.Columns.Add();
ListColumn.Width := 100;
ListColumn.Caption := 'Index Group';
ListColumn.Alignment := taLeftJustify;
ListColumn := ListView1.Columns.Add();
ListColumn.Width := 100;
ListColumn.Caption := 'Index Offset';
ListColumn.Alignment := taLeftJustify;
end;
procedure TForm1.OnFormCreate(Sender: TObject);
begin
nSymbols := 0;
nSymByteSize := 0;
StatusBar1.SimplePanel := true;
AdsOcx1.AdsAmsServerNetId := AdsOcx1.AdsAmsClientNetId; {Sets PLC server network adress}
AdsOcx1.AdsAmsServerPort := 801; {Sets the PLC run time system}
StatusBar1.SimpleText := AdsOcx1.AdsServerAdsState;
CreateColumns(Sender);
end;
procedure TForm1.ReadSymInfoButtonClick(Sender: TObject);
var
strSymbolName : WideString;
nSymbolType : Integer;
cbSymbolSize : Integer;
strComment : WideString;
nIndexGroup : Integer;
nIndexOffset : Integer;
bNext : WordBool;
nSymNo :Integer;
begin
ListView1.Items.Clear(); {clear old items}
adsResult := AdsOcx1.AdsReadSymbolInfo( nSymbols, nSymByteSize );
StatusBar1.SimpleText := Format('AdsReadSymbolInfo result:%d, nSymbols:%d, nSymByteSize:%d', [adsResult, nSymbols, nSymByteSize]);
if ( ( adsResult = 0 ) And ( nSymbols > 0 ) ) then
begin
bNext := false; {read first symbol info}
adsResult := AdsOcx1.AdsEnumSymbols( strSymbolName, nSymbolType, cbSymbolSize, strComment, nIndexGroup, nIndexOffset, bNext);
AddListViewItem(Sender, strSymbolName, strComment, nSymbolType, cbSymbolSize, nIndexGroup, nIndexOffset);
if adsResult > 0 then
StatusBar1.SimpleText := Format('AdsEnumSymbols result:%d', [adsResult]);
for nSymNo := 1 to nSymbols-1 do
begin
bNext := true;
adsResult := AdsOcx1.AdsEnumSymbols( strSymbolName, nSymbolType, cbSymbolSize, strComment, nIndexGroup, nIndexOffset, bNext);
AddListViewItem(Sender, strSymbolName, strComment, nSymbolType, cbSymbolSize, nIndexGroup, nIndexOffset);
if (adsResult > 0) then
StatusBar1.SimpleText := Format('AdsEnumSymbols result:%d', [adsResult]);
end;
end;
end;
procedure TForm1.AddListViewItem(Sender: TObject; strSymbolName, strComment :WideString; nSymbolType, cbSymbolSize , nIndexGroup, nIndexOffset : integer);
var ListItem :TListItem;
strAdsType :String;
begin
ListItem := ListView1.Items.Add();
ListItem.Caption := Format('%d',[ListView1.Items.Count]);
ListItem.SubItems.Add(strSymbolName);
case nSymbolType of
0: strAdsType := 'ADST_VOID';
16: strAdsType := 'ADST_INT8';
17: strAdsType := 'ADST_UINT8';
2: strAdsType := 'ADST_INT16';
18: strAdsType := 'ADST_UINT16';
3: strAdsType := 'ADST_INT32';
19: strAdsType := 'ADST_UINT32';
20: strAdsType := 'ADST_INT64';
21: strAdsType := 'ADST_UINT64';
4: strAdsType := 'ADST_REAL32';
5: strAdsType := 'ADST_REAL64';
65: strAdsType := 'ADST_BIGTYPE';
30: strAdsType := 'ADST_STRING';
31: strAdsType := 'ADST_WSTRING';
32: strAdsType := 'ADST_REAL80';
33: strAdsType := 'ADST_BIT';
34: strAdsType := 'ADST_MAXTYPES';
end;
ListItem.SubItems.Add(Format('%s',[strAdsType]));
ListItem.SubItems.Add(Format('0x%x (%d)',[cbSymbolSize, cbSymbolSize]));
ListItem.SubItems.Add(strComment);
ListItem.SubItems.Add(Format('0x%x (%d)',[nIndexGroup, nIndexGroup]));
ListItem.SubItems.Add(Format('0x%x (%d)',[nIndexOffset, nIndexOffset]));
end;
procedure TForm1.Exit1Click(Sender: TObject);
begin
Close();
end;
procedure TForm1.Properties1Click(Sender: TObject);
begin
AdsOcx1.BrowseProperties();
StatusBar1.SimpleText := AdsOcx1.AdsServerAdsState;
end;
procedure TForm1.About1Click(Sender: TObject);
begin
AdsOcx1.AboutBox();
end;
Initialization
IsMultiThread := True;// Setting this system variable makes Delphi's memory manager thread-safe
end.
SPS Programm
PROGRAM MAIN
VAR
REAL32_1 AT %MB0 : REAL; (* 1 *)
REAL32_2 AT %MB4 : REAL; (* 2 *)
REAL32_3 AT %MB8 : REAL; (* 3 *)
REAL32_4 AT %MB12: REAL; (* 4 *)
REAL32_5 AT %MB16: REAL; (* 5 *)
REAL64_1 AT %MB20 : LREAL; (* 6 *)
REAL64_2 AT %MB28 : LREAL; (* 7 *)
REAL64_3 AT %MB36 : LREAL; (* 8 *)
REAL64_4 AT %MB44 : LREAL; (* 9 *)
REAL64_5 AT %MB52 : LREAL; (* 10 *)
INT32_1 AT %MB60 : DINT; (* 11 *)
INT32_2 AT %MB64 : DINT; (* 12 *)
INT32_3 AT %MB68 : DINT; (* 13 *)
INT32_4 AT %MB72 : DINT; (* 14 *)
INT32_5 AT %MB76 : DINT; (* 15 *)
UINT32_1 AT %MB80 : UDINT; (* 16 *)
UINT32_2 AT %MB84 : UDINT; (* 17 *)
UINT32_3 AT %MB88 : UDINT; (* 18 *)
UINT32_4 AT %MB92 : UDINT; (* 19 *)
UINT32_5 AT %MB96 : UDINT; (* 20 *)
INT16_1 AT %MB100 : INT; (* 21 *)
INT16_2 AT %MB102 : INT; (* 22 *)
INT16_3 AT %MB104 : INT; (* 23 *)
INT16_4 AT %MB106 : INT; (* 24 *)
INT16_5 AT %MB108 : INT; (* 25 *)
UINT16_1 AT %MB110 : UINT; (* 26 *)
UINT16_2 AT %MB112 : UINT; (* 27 *)
UINT16_3 AT %MB114 : UINT; (* 28 *)
UINT16_4 AT %MB116 : UINT; (* 29 *)
UINT16_5 AT %MB118 : UINT; (* 30 *)
INT8_1 AT %MB120 : SINT; (* 31 *)
INT8_2 AT %MB121 : SINT; (* 32 *)
INT8_3 AT %MB122 : SINT; (* 33 *)
INT8_4 AT %MB123 : SINT; (* 34 *)
INT8_5 AT %MB124 : SINT; (* 35 *)
UINT8_1 AT %MB125 : USINT; (* 36 *)
UINT8_2 AT %MB126 : USINT; (* 37 *)
UINT8_3 AT %MB128 : USINT; (* 38 *)
UINT8_4 AT %MB129 : USINT; (* 39 *)
UINT8_5 AT %MB130 : USINT; (* 40 *)
BOOL_1 AT %MX131.0 : BOOL; (* 41 *)
BOOL_2 AT %MX131.1 : BOOL; (* 42 *)
BOOL_3 AT %MX131.2 : BOOL; (* 43 *)
BOOL_4 AT %MX131.3 : BOOL; (* 44 *)
BOOL_5 AT %MX131.4 : BOOL; (* 45 *)
ARRAY_1 : ARRAY[1 .. 10] OF SINT; (* 46 *)
ARRAY_2 : ARRAY[1 .. 10] OF INT; (* 47 *)
ARRAY_3 : ARRAY[1 .. 10] OF DINT; (* 48 *)
ARRAY_4 : ARRAY[1 .. 10] OF LREAL;(* 49 *)
ARRAY_5 : ARRAY[1 .. 10] OF BOOL; (* 50 *)
END_VAR
Sprache / IDE | Beispielprogramm auspacken |
---|---|
Delphi XE2 | |
Delphi 5 oder höher (classic) |