Reading and writing of string variables with Delphi

Task

A .Net application should read a string from the PLC and write a string to the PLC.

Description

The PLC contains the string: MAIN.text.

In the MainForm_Load event method a new instance of the class TcAdsClient is created. Then the method TcAdsClient.Connect of the TcAdsClient object is called to establish a connection to the port 801. Finally the method  TcAdsClient.CreateVariableHandle is used to fetch the handle of the PLC variable . When the program finishes, the Dispose method of the TcAdsClient object is called. When the user clicks the "Read" button on the form, the string is read by means of the TcAdsClient.Read method and is displayed in the text box. When the user clicks the "Write" button ont the form, the string is wirtten to PLC and is displayed in the text box.

 

TwinCAT.Ads.NET version < 1.0.0.10:

The length of the AdsStream must be equal to size of the string in the PLC plus 1 (inclusive the terminating zero character). The parameter System.Text.Encoding.ASCII has to be passed to constructor of the BinaryReader class. This is necessary for the BinaryReader to be able to convert the ANSI characters to the char type.

 

TwinCAT.Ads.NET version >= 1.0.0.10:

The classes AdsBinaryReader and AdsBinaryWriter can be used to read and write strings ( see commented section in sample program ). These classes derive from the BinaryReader/Writer classes. To read a string from the stream one has to call the method AdsBinaryReader.ReadPlcString. To write a string to the stream one has to call the method AdsBinaryWriter.WritePLCString. The length of the AdsStream must be equal to size of the string in the PLC (without terminating zero character). The length is passed to this method and must be equal to the length of the string in the PLC (without the terminating zero character).

 

Delphi Prism (Embarcadero Prism XE2, Oxygene for .NET) program

namespace Sample04;

interface

uses
  System.Drawing,
  System.Collections,
  System.Collections.Generic,
  System.Windows.Forms,
  System.ComponentModel, System.IO, TwinCAT.Ads, System.Text;////////////////////////////////////////////////////////////////////////
// Define OLD_ADSNET_INTF only if you are using Ads.NET version < 1.0.0.10
// From Ads.NET version >= 1.0.0.10 and higher the classes 
// AdsBinaryReader and AdsBinaryWriter can be used to read and write strings 
// {$DEFINE OLD_ADSNET_INTF} 
////////////////////////////////////////////////////////////////////////

type
  /// <summary>
  /// Summary description for MainForm.
  /// </summary>
  MainForm = partial class(System.Windows.Forms.Form)
  private
    adsClient   : TcAdsClient;
    varHandle   : Integer;
    method MainForm_Load(sender: System.Object; e: System.EventArgs);
    method MainForm_FormClosing(sender: System.Object; e: System.Windows.Forms.FormClosingEventArgs);
    method btnRead_Click(sender: System.Object; e: System.EventArgs);
    method btnWrite_Click(sender: System.Object; e: System.EventArgs);
  protected
    method Dispose(disposing: Boolean); override;
  public
    // text : STRING[30] := 'hello';
    // Byte length of the PLC string (without terminating zero character)
    const MAX_TEXT_LENGTH  = 30;
    constructor;
  end;

implementation

{$REGION Construction and Disposition}
constructor MainForm;
begin
  //
  // Required for Windows Form Designer support
  //
  InitializeComponent();

  //
  // TODO: Add any constructor code after InitializeComponent call
  //
end;

method MainForm.Dispose(disposing: Boolean);
begin
  if disposing then begin
    if assigned(components) then
      components.Dispose();

    //
    // TODO: Add custom disposition code here
    //
  end;
  inherited Dispose(disposing);
end;
{$ENDREGION}

method MainForm.MainForm_Load(sender: System.Object; e: System.EventArgs);
begin
  try
    // Create instance of class TcAdsClient
    adsClient := new TcAdsClient();
    // Create connection with Port 801 on local PC
    adsClient.Connect(801);
    // Create PLC variable handle
    varHandle := adsClient.CreateVariableHandle('MAIN.text');
  except
    on err: Exception do
      MessageBox.Show(err.Message, err.Source);
  end;
end;

method MainForm.MainForm_FormClosing(sender: System.Object; e: System.Windows.Forms.FormClosingEventArgs);
begin
  try
    // Release PLC variable handle
    adsClient.DeleteVariableHandle(varHandle);
  except
    on err: Exception do
      MessageBox.Show(err.Message, err.Source)
  end;
  // Close connection
  adsClient.Dispose();
end;

{$IFNDEF OLD_ADSNET_INTF} // Ads.NET version >= 1.0.0.10 (new)
method MainForm.btnRead_Click(sender: System.Object; e: System.EventArgs);
begin
  try
    // Create stream to hold the data. Length of the stream = Length of string in PLC
    var dataStream := new AdsStream(MAX_TEXT_LENGTH);
    // Create AdsBinaryReader. Encoding is set to ASCII, to read strings
    var reader := new AdsBinaryReader(dataStream);
    // Read string characters from PLC to the stream
    adsClient.Read(varHandle, dataStream);
    // Read stream characters from stream
    textBox1.Text := reader.ReadPlcString(MAX_TEXT_LENGTH)
  except
    on err : Exception do
      MessageBox.Show(err.Message, err.Source)
  end;
 end;

method MainForm.btnWrite_Click(sender: System.Object; e: System.EventArgs);
begin
  try
    // Create stream to hold the data. Length of the stream = Length of string in PLC
    var dataStream := new AdsStream(MAX_TEXT_LENGTH);
    // Create AdsBinaryWriter. Encoding is set to ASCII, to read strings
    var writer := new AdsBinaryWriter(dataStream);
    // Add string characters to the stream
    writer.WritePlcString(textBox1.Text, MAX_TEXT_LENGTH);
    // Write stream to the PLC
    adsClient.Write(varHandle, dataStream)
  except
    on err : Exception do
      MessageBox.Show(err.Message, err.Source)
  end;
end;


{$ELSE} // OLD_ADSNET_INTF defined => Ads.NET version < 1.0.0.10
method MainForm.btnRead_Click(sender: System.Object; e: System.EventArgs);
begin
  try
    // Length of the stream = Length of string in PLC + 1
    var dataStream := new AdsStream(MAX_TEXT_LENGTH + 1);
    // Create BinaryReader. Encoding is set to ASCII, to read strings
    var reader := new BinaryReader(dataStream, System.Text.Encoding.ASCII);
    // Read string characters from PLC to the stream
    var length := adsClient.Read(varHandle, dataStream);
    // Read stream characters from stream
    var text := new String(reader.ReadChars(length));
    // Search for terminating zero character and cut at found position
    // Necessary if you want to compare the string to other strings
    text := text.Substring(0,text.IndexOf(Char(0)));
    textBox1.Text := text
  except
    on err: Exception do
      MessageBox.Show(err.Message, err.Source)
  end;
end;

method MainForm.btnWrite_Click(sender: System.Object; e: System.EventArgs);
begin
  try
    // Length of the stream = Length of string in PLC + 1
    var dataStream := new AdsStream(MAX_TEXT_LENGTH + 1);
    // Create BinaryWriter. Encoding is set to ASCII, to read strings
    var writer := new BinaryWriter(dataStream, System.Text.Encoding.ASCII);
    // Add string characters to the stream
    writer.Write(textBox1.Text.ToCharArray());
    // Add terminating zero to the stream
    writer.Write(Char(0));
    // Write stream to the PLC
    adsClient.Write(varHandle, dataStream)
  except
    on err: Exception do
      MessageBox.Show(err.Message, err.Source)
  end;
end;
{$ENDIF}


end.

 

PLC program

PROGRAM MAIN
VAR
    text : STRING[30] := 'hello';
END_VAR
;

 

Download

Language / IDE

Unpack the sample program

Delphi Prism (Embarcadero Prism XE2, Oxygene for .NET)

Sample04.exe

Delphi for .NET (Borland Developer Studio 2006)

Sample04.exe