Delphi – exchange data with Siemens PLC

Other interesting possibilities for using LibNoDave library is NoDave component for Delphi API. The Unit NoDaveComponent implements the class TNoDave, which encapsulates the access to the libnodave.dll. With TNoDave and libnodave.dll it is very easy to read and write data from and to a S7 PLC. TNoDave uses a worker-thread for asynchronous connecting with the PLC.

This source files which are necessary to connect PLC:

  • nodave.pas – that unit includes variables, conventions (where are name of function, name of file, where function is located and information on how it to use) and functions itself.
  • nodavecomponent.pas – NoDave component.
  • libnodave.dll – that is communication library itself.

Add nodave.pas file in the Delphi project and copy libnodave.dll file in the same directory. But nodavecomponent need to register. How to install a third-party Delphi component you can read in the site: Installing a single source Delphi component into an existing Package.

Structure of the application:

Source of the example of the Delphi application available for download.

Delphi_source

After the first glance is useful. Separate a worker-thread for asynchronous connecting with the PLC. Make a list of the required data, enabling the driver and you have a date. But if necessary to read data from different locations and of different types, then may be useful to use the DLL directly.

Example of using LibNoDave library directly.

This source files which are necessary to connect PLC:

  • nodave.pas
  • libnodave.dll

Usage of the functions connect, disconnect, read and write data:

– Connection


procedure TMainForm.Connect;
<pre>Var
  ComName:Array[0..20] of Char;
  Fds:_daveOSserialType;
  S:String;
  i:Integer;
begin
  S:=Trim(IPAddress);
  For i:=1 To Length(S) Do
    ComName[i-1]:=S[i];
  ComName[Length(S)]:=#0;
  fds.rfd:=openSocket(102,COMname);
  fds.wfd:=fds.rfd;

  verbinding := false;
  if (fds.rfd>0) then
  begin
    dcIn:=daveNewInterface(fds, 'IF1',0,ConnProtocol, MPISpeed);
    dcIn^.timeout:=IntfTimeout;
    if (daveInitAdapter(dcIn)=0) then
    begin
      dc :=daveNewConnection(dcIn,2, CPURack, CPUSlot);
      if (daveConnectPLC(dc)=0) then
      begin
        verbinding := true;
      end;
    end;
  end;
end;

procedure TMainForm.Disconnect;
begin
  if connected then
  begin
    daveDisconnectPLC(dc);
    daveDisconnectAdapter(dcIn);
    connected := false;
  end;
end;

– Write data to PLC

//Write S7 FLOAT
procedure TMainForm.WriteDouble(varR:single);
var
 Res:LongInt;
 VarD : longint;
begin
 VarD := daveToPLCfloat(varR);
 res := daveWriteBytes(dc, daveDB, ValueAdresDb, ValueAdresNum, 4, @varD);
end;

//write DINT, DWORD, INT, WORD
procedure TMainForm.WriteInt(varI : integer, type : boolean);
var
 varW : integer;
 varC, varD : word;
 Res:LongInt;
begin
 if  type = true then
 begin
   varW := daveSwapIed_32(varI);
   res := daveWriteBytes(dc, daveDB, ValueAdresDb, ValueAdresNum, 4, @varW)
 end else begin
   varC := varI;
   varD := daveSwapIed_16(varC);
   res := daveWriteBytes(dc, daveDB, ValueAdresDb, ValueAdresNum, 2, @varD)
 end;
end;

– Read data from PLC

procedure TMainForm.ReadData;
var
  Res:LongInt;
  i : integer;
  value1 : Array[0..3] of double;
Begin
  if verbinding then
  begin

    //Read 3x float values begin address DB110.DBD12
    res := daveReadBytes(dc, daveDB, 110, 0, 12, NIL);
    For i := 0 to 2 do
      value[i] := daveGetFloat(dc);
    Label1.Caption := Format('%f', [value1[0]]  );
    Label2.Caption := Format('%f', [value1[1]]  );
    Label3.Caption := Format('%f', [value1[2]]  );

    //Read BYTE
    res := daveReadBytes(dc, daveFlags, 0, 24, 1, NIL);
    Label4.Caption := IntToStr(daveGetU8(dc));

    //Read WORD
    res := daveReadBytes(dc, daveFlags, 0, 16, 2, NIL);
    Label5.Caption := IntToStr(daveGetU16(dc));

    //Read DWORD
    res := daveReadBytes(dc, daveFlags, 0, 2, 4, NIL);
    Label6.Caption := IntToStr(daveGetU32(dc));
 end
end;

During development of PLC control software often requires testing operation of the PLC software. Therefore necessary to simulate operation of the equipment controlled by PLC.
The purpose of the example, simulate and visualize the operation of devices connected to the PLC. Source of the example:

Delphi_source

The structure of Delphi example is very simple. First application reads communication settings, then connect to PLC via ISO on TCP protocol. If connection is successful, then timer periodically reads outputs data from PLC and update user interface of the application, makes manipulations with bits and writes inputs data to PLC.

Reading from PLC outputs, simulation, manipulation with bits and writing inputs to PLC.

Step 1. Reading digital outputs: With function DaveReadBytes(dc, daveOutputs, 0, 0, 4, nil) read data from outputs memory area of the PLC  in the buffer as a sequence of bytes and with function “daveGetU8(dc)” read out of the buffer, the data with the byte format.

Step 2, 3 and 4: Manipulation with bits. For manipulation of bits use MatBit8.pas unit. With functions “SetBit(i)” or “ClrBit(i)” write “1″ or “0″ in the appropriate bit in the byte of the “inputDG” array of bytes depending on the bit in the byte of output array.

Step 5. Writing digital inputs: With function DaveWriteBytes(dc, daveOutputs, 0, 0, 4, @inputsDG) write sequence of bytes (4) to PLC.

Simulation analog values and writing to PLC analog inputs.

varW : integer;

varW := daveSwapIed_32(value);
res := daveWriteBytes(dc, daveInputs, 0, Address, 4, @varW);

Example of the full simulations of Waste Water Purification Installation of the oil company in Rotterdam. Simulation van motors, pumps, valves, process, level of the tanks, engine electric current and speed, flow control. Connection with two Siemens 317 PLCs.

Delphi_source

Example of the full simulations of RSP Uniwax rotary printing machine of Vlisco company in Netherlands. Simulation of the HMI and inputs. Visualization of the outputs and control processes.

Delphi_source

33 Responses to “Delphi – exchange data with Siemens PLC”

  1. Luis Gonzalez Says:

    Hi Alex,
    Congratulations on your projects.
    I am testing your project Skidsim, but I get an error:
    ScommDll.dll missing, and without this file can not continue.
    What I can do? Can you help me?

    Thank you very much and I hope your answer.

    • alexsentcha Says:

      Hi Luis,
      Open page “Delphi, VB – SAIA PLC communication library” Download and install Scomm_SP1.4_130.zip library in the default directory “C:\Program Files\Saia-burgess\SAIA Communication Driver\1.4\”

      Next: you have two options:

      1. Open Delphi project options and set Output directory to “C:\Program Files\Saia-burgess\SAIA Communication Driver\1.4\”

      2. Or open directory “C:\Program Files\Saia-burgess\SAIA Communication Driver\1.4\” and copy all DLLs to the directory where your exe file is situated.

      Success.

  2. Luis Gonzalez Says:

    Hi Alex,
    Thank you very much for responding so quickly.
    I have followed the steps as you have told me, but I have another error:
    “Project raised exception class Exception SkidSim.exe with message ‘Can not open AVI”. Process stopped. Use Step or Run to continue. ”
    The. AVI I can see well with Video Player. I think this error is problem of my computer. I’ll try the project on another computer.
    Thank you very much and I’ll tell you how it went

    • alexsentcha Says:

      Hi Luis,

      No, problem is not with your computer, problem with location of the AVI file “Skid6.avi”. The location was identified as “common” directory in your computer, this file does not exist in this directory. Copy the file Skid6.avi to directory: “C: \ Program Files \ Common Files \ Skid \”

      or change variable CommonDir := PrBufReg.ReadString(‘Dir’,’CommonDir’,’C:\Program Files\Common Files\Skid\’);
      to
      CommonDir := PrBufReg.ReadString(‘Dir’,’CommonDir’,’YOUR DIRECTORY’);
      and copy a file Skid6.avi to the YOUR DIRECTORY.
      Enjoy.

  3. Luis Gonzalez Says:

    Now everything is fine and the application is running but I can not communicate with the PLC. I can not communicate with socker. I can not communicate with “PGU” (I guess “MPI”).
    My configuration in PLC:
    Rack = 0, slot = 2, Port = COM1, PLC Address = 2, Local = 0. IP = 192.168.1.50
    My settings in Skid-Sim:
    CPU Number = 2, S-Bus Station = 0, Port = COM2, Number of retry = 0, local = 0.

    Many combinations I’ve tried but nothing.
    With Simatic MPI and Ethernet works well.
    I really just want a small example to communicate with Delphi S7 protocol “MPI”. Could you help me?
    Thank you very much and hopefully you can help me.

    • alexsentcha Says:

      Hello Luis,
      I think you’re wrong example considered.

      SAIA has two kinds of PLCs:

      1. SAIA PCD. This PLC used PG5 software and for data exchange must use SAIA communication library. Skid example created for PCD PLC and not applicable for Siemens PLC. PCD PLC has SBUS Station, CPU Number… and not rack, slot, plc address….

      2. SAIA – Siemens. This PLC using Siemens Step 7 software and for data exchange must use LibNoDave communication library.
      For programming with LibNoDave driver you can use Delphi, Java or VB/C#.net programming languages. This PLC has rack, slot and not SBUS Station, CPU Number…

      If you using Siemens or Saia-Siemens PLC then take a look for RSP Uniwax rotary printing machine example for Delphi programming language or short example above on this page.
      Communication protocol with Siemens PLC:
      1. MPI COM – easy for implementing, but MPI-COM adapter need.
      2. MPI USB – difficult for implementing and very difficult with Microsoft USB. Need MPI-USB adapter.
      3. ISO Ethernet – easy for implementing, but hardware need CP 343/443 card.
      I recommended to you try ISO Ethernet:
      In the PC(step 7) –> Brodcom 440x protocol with IP = 192.168.1.51.
      In the PLC –> IP = 192.168.1.50
      In the PC(Delphi apl.) –> Rack = 0, slot = 2, IP = 192.168.1.50, COM is not important.
      Success.

  4. Luis Gonzalez Says:

    Hi Alex,
    The first thing I do is say thank you for your help and advice.
    You have reason to use TCP-IP, I know that is the future but now I need to make a small application in MPI.
    I´ll See the examples you tell me and I’ll tell you the results.

    Once again thank you.

  5. Luis Gonzalez Says:

    Hi Alex,
    How I can I download the whole project “RSP Uniwax rotary?”. When you click, so you can only download the files one by one (and some can not be downloaded).

    Thank you

  6. Matija Says:

    Hi Alex,
    I like your page. I found a lot of usefull information, but I have problem running your program. At line
    “fds.rfd:=openSocket(102,COMname);” I get result = 0 and connection to PLC is not made.
    I have also tried the program which come with LibNoDave – NoDaveDemo.exe which connect to my PLC and I can read data.
    Can you please give me some pointers what to look to overcome this problem. I use XE2 with Win7 and I try to connect to S7-300.
    Thank you for your help.
    Matija

    • alexsentcha Says:

      Hi Matija,
      I have zip file with source for Delphi 2005 added in the blog.
      Take a look.

      • Matija Says:

        Hi Alex,
        Thank you for your replay. Meanwhile I succesfully manage to connect to PLC.
        I replace your code:

        S:=Trim(IPAddress);
        For i:=1 To Length(S) Do ComName[i-1]:=S[i];
        ComName[Length(S)]:=#0;
        fds.rfd:=openSocket(102,COMname);

        with
        var Address : AnsiString;
        Address := IPNaslov + #0;
        Fds.Rfd := OpenSocket(Port, @Address[1]);

        and it works.
        Regards Matija

  7. Matija Says:

    Hi Alex,
    I have another question. Is it possible to read/write single bit into PLC. I see on your blog that libnodave has Readbits and Writebits, but all my attempts was unsuccessful. Right now I read byte, change bit and write back. Do you maybe have one real life example?
    Regards,
    Matija

    • alexsentcha Says:

      Hi Matija, Single bit into PLC is possible to read and write. I do not use Delphi anymore, because in many cases necessary, SimPLC instead of the real PLC. With Delphi advent of the Siemens S7 version 5.5 (SimPLC version 5.4) with the COM component SimPLC is not possible anymore.
      This is an example write bit in the PLC with VB.Net. Delphi and VB.Net uses the same LibNoDave.DLL eventually.

      Private Sub WriteInputConsole(ByVal InputNum As Byte, ByVal BitNum As Byte, ByVal Par As Boolean)
      Dim Adr As Integer
      Dim pData(1) As Byte
      If Par Then
      pData(0) = 255 ‘write 1
      Else
      pData(0) = 0 ‘write 0
      End If
      If Connection Then
      Adr = InputNum * 8 + BitNum
      res = dc.writeBits(libnodave.daveInputs, 0, Adr, 1, pData)
      Else
      MsgBox(“No connection with PLC!”)
      End If
      End Sub

      OR res = dc.writeBits(libnodave.daveFlags, 0, Adr, 1, pData)

      Regards,
      Alex

      • Matija Says:

        Hi Alex,
        Thank you for information. It was very usefull and now I manage to write single bit to PLC.
        Here is code for Delphi (Libnodave)

        Res := DaveWriteBits(DC, DaveDb, NrDB, (8 * StartByte + PosBit), 1, @DummyI);

        The difference from WriteByte is Adr structure which I get it from your code. Thank you for help and support.

        Kind Regards,
        Matija

  8. Sevdalin Shipkovenski Says:

    Dear Alex,
    I’m really impressed from your work. I need some help/advise. I’m trying to use delphi component that is part of the project. My task is to read different values from different DBs with different structure. As a base I used the demo , but I got “false values” only I manage to succeed when I read one by one the values in sequence of of 100ms. Other time I manage when I read whole DB, but only one. If i change to next db then I got wrong values.
    Can you help me?

    • alexsentcha Says:

      Hi Sevdalin,
      To read data from PLC you must know exactly contents of the data block and use appropriate functions for boolean, integer, double integer or real data.

  9. AndreFM Says:

    Hi Alex,
    Im new to the communication of Delphi and Siemens PLC and I would like to know some opinion from you and you have lot of experience.
    What is exactly the reason to use LibNoDave or any direct connection instead OPC? If im not wrong OPC is usefull when you have many applications conneting to same PLC, right? Otherwise Libnodave is the optimal solution also due to no costs compared with an OPC Server license?
    Do you know is there are advantages fro 3rd party libraries instead libnodave? For example there is AGlink from Deltalogic, but their price is very high. Thx for any feedback

  10. AndreFM Says:

    Hi Alex, just one more question. I saw that you use an old version of LIBNODAVE.DLL (back from 2005), is there any particular reason?

  11. Matija Says:

    Hi Alex,
    I have one situation. I have two PLC connected between with MPI connection. I have NL 50-MPI (Konverter Ethernet TCP/IP to S7-MPI).
    Can I connect to each one of them using ISO over TCP?
    Port is differrent 1099 instead 102 and I don’t know where to select from which PLC I am addressing?

    Thank you for your help, regards,
    Matija

    • alexsentcha Says:

      Hi Matija,
      You can connect 2 or more PLC with different IP addresses from the same application.
      Regards.

      • Matija Says:

        Hi Alex,
        Thank you for reply, your answer is correct, but in my situation where I have two PLC connected between with MPI connection, they don’t have IP addresses. On one of them I would like to use this NL 50-MPI (Converter Ethernet TCP/IP to S7-MPI). So this PLC will have IP address, but have to reach the second PLC over first using MPI connection?

        Thank you for your help, regards,
        Matija

  12. jose Says:

    Muy bueno, gracias…

  13. mohammaddesign Says:

    How Can I Communicate with S5 ?

  14. Paolo F. Says:

    Hi, your code and the nodave.h are not Delphi Unicode compatible. You must replace any reference to char and pchar with AnsiChar and pAnsiChar in nodave.h.
    Then this code can connect succesfully to a PLC (TCP/ISO):

    function TestConnection:boolean;
    var
    fds: _daveOSserialType;
    begin
    result:=false;
    fds.rfd:=openSocket(102, ‘192.168.1.100’);
    fds.wfd:=fds.rfd;

    if (fds.rfd<=0) then
    raise Exception.Create('Opensocket failed!');
    di :=daveNewInterface(fds, 'IF1',0,daveProtoISOTCP, daveSpeed187k);
    di^.timeout:=5000000;
    if (daveInitAdapter(di)0) then
    raise exception.Create(‘Init Adapter failed!!’);

    dc:=daveNewConnection(di, 2, 0, 2);
    if (daveConnectPLC(dc)0) then
    raise exception.Create(‘PLC Connect failed!’);

    result:=true;
    end;

    There is also a TNoDaveComponent that need to be updated.

  15. Manoj Says:

    HI,

    we have try to connect plc by com port but com is connected and PLC not connect with computer.

    fds.rfd = libnodave.setPort(“COM3”, “9600”, 8) ‘ (102, IP)

    fds.wfd = fds.rfd
    If fds.rfd > 0 Then ‘ if step 1 is ok
    di = New libnodave.daveInterface(fds, “IF1”, 0, libnodave.daveProtoISOTCP, libnodave.daveSpeed187k)
    di.setTimeout(1000000) ‘ Make this longer if you have a very long response time
    res = di.initAdapter

    If res = 0 Then ‘ init Adapter is ok
    dc = New libnodave.daveConnection(di, 0, rack, slot) ‘ rack amd slot don’t matter in case of MPI
    res = dc.connectPLC()
    If res = 0 Then
    Connection = True
    ToolStripStatusLabel1.Text = “Connected ” + IP
    End If
    End If
    End If

    res is display -1 values after res = dc.connectPLC()

    please help us

    Thanking you

  16. Yevgeniy Says:

    Hi Alex,
    Could you please clarify some questions.
    I downloaded component LibNoDave with http://sourceforge.net/projects/libnodave/.
    It has last update 2014-05-22.
    I tried to install component, but Delphi XE6 can’t find the nodave.pas file.
    How I can get this file?
    Also, I tried to convert nodave.h to nodave.pas, but it was not success.

    Thank you for your help!
    Best Regards
    Yevgeniy.

  17. Yevgeniy Says:

    I found solution for this problem.
    Need to take nodave.pas from folder pascal and to change type of variables. According rule below.

    from char to ansichar
    from string to ansistring
    from pchar to pansichar

    Thanks,
    Best Regard
    Yevgeniy.

  18. Matija Says:

    Hi Alex,
    I have a problem with disconnecting from PLC.
    I use your code to do it:

    procedure TMainForm.Disconnect;
    begin
    if connected then
    begin
    daveDisconnectPLC(dc);
    daveDisconnectAdapter(dcIn);
    connected := false;
    end;
    end;

    With a program I create a connection to PLC, then I disconnect.
    I repeat this two more times with success (together 3 times), but the fourth attempt to connect failed. If I close the program and open it again I can connect and disconnect again 3 times.

    I also try to add
    DaveDisconnectPLC(dc);
    CloseSocket(Port);
    ClosePort(Port);
    with no success.

    Do you have any idea how to solve this.

    Thanks,
    Best Regards,
    Matija

  19. Matija Says:

    Hello

    I find the solution.
    I add at the end

    CloseSocket(Port);
    ClosePort(fds.rfd);

    and it works.

    Regards,
    Matija

Leave a reply to alexsentcha Cancel reply