Communication ports are the way used by the protocol drivers to send and receive data. One communication port can be used by one or more protocol drivers, simultaneously.

Communication ports aren’t implemented together with protocol drivers to allow more flexibility to the system. An real application that can be done using this architecture, is the association of a TTCP_UDPPort with a COMServer (devices that acts as a gateway of RS-232/485/422 to TCP/IP), to by example, communicate with a Modbus RTU device that is far, over the Internet. Another advantage of this design is to put two or more different protocols using the same communication port simultaneously, both on the same application. This is possible because all PascalSCADA ports comes with mechanism that only allows one protocol to use communication port. That is, an application can communicate with multiple devices, these devices with different communication protocols and all connected to the same RS-485 network. It is possible, though not recommended.

All port classes that exists on PascalSCADA descend from TCommPort class, that implements the methods to open and close the port, read and write data, and clean the buffers when a communication error occurs. But if a new port is being written, these methods should be specialized to handle the new port being implemented.


The TSerialPort class, descendant of TCommPort class, has been created to allow the protocol drivers to exchange data over serial ports, regardless of the physical layer used by serial port.

On Windows, this class need of a serial port with name between COM1 and COM255.

Running over Linux, any device where the name starts with tty<number>, ttyUSB<number> or ttyACM<number> is valid.

On FreeBSD, any device where the name starts with cuad<number> is accepted by the class.

Both Linux and FreeBSD (or another Unix) should be added the user that will run the application on the group owner of the serial port and the group must have permission of read/write on the desired serial port. The name of this group can vary depending of the operating system.

Independent of operating system, the TSerialPort class has the following properties that configure the operation of the serial port:

  • COMPort: defines the name of serial port to be used. If the application has been configured with one serial port and it is disconnected of the system (by example, a USB <-> serial converter) and the application is started, a exception will be raised. If this exception occurs on the application load (initialization), your application will be not loaded, even if Active=false.
  • Baudrate: communication speed in bits per second that will be used on the configured serial port while it’s in use. Baud rates between 110 bps and 115200 bps are accepted.
  • DataBits: Defines the word length in bits that will be used when communicating with the serial port. Only the size of 7 or 8 bits are accepted, the default is 8 bits. Some protocols requires the value of this property set to 7 bits, like Modbus ASCII. Others requires the word size of 8 bits, like Mobus RTU.
  •  StopBits: Configure how many bits will be used to mark start and the end of each word transmitted or received in the serial communication. Valid values are 1 or 2 stop bits. The default is 1 stop bit.
  • Paridade: configures if each word received word will have a parity error check, and if error check exists, this defines if it will be even or odd.
  • Timeout: defines the maximum time that the serial port will wait for reading a certain amount of data. This time is set in milliseconds. In cases of timeout overflow, a clean up of the read and write buffers is performed.
  • AcceptAnyPortName: if this property is enabled on a Unix system (Linux, FreeBSD, etc), makes the TSerialPort accept any device name on the COMPort property. Very useful when some some drivers create devices with names that don’t matches the patterns described above.
  • WriteReadDelay: Delay in milliseconds between write and read commands.
  • Active: This property controls when the port will be opened or closed. The serial port should not be open by another process when this property goes to true, otherwise the value of this property come back to false. In the development time, Active = true only checks if everything is OK to open the serial port, but don’t open it.

The class TTCP_UDPPort, descendant of TCommport, has been created to allow the protocol drivers exchange data over TCP (tested) or UPD (not tested) over IPv4, independent of physical and link layer being used by the port.

This class has no operating system dependent properties, and the following properties configures its operation:

  • Host: The IPv4 address of the host to connect. Host names are not accepted, only IPv4 address.
  • Port: Port number on the destination host to connect. Only port numbers between 1 and 65535 are accepted.
  • PortType: Sets the socket type that will created when connected with the host. It can be a TCP or UDP.
  • ExclusiveDevice: If true, don’t opens the socket when in the development time. Useful when the destination host has a few numbers of available connections.
  • EnableAutoReconnect: If true and if the socket is disconnected (problem on the physical layer or on the host) enables the timer that tries to reconnect the socket. In this case the invalid socket is closed while Active property remains true.
  • ReconnectRetryInterval: This property defines the interval in milliseconds to attempt to reconnect lost connections. This property is only valid if both EnableAutoReconnect and Active are true.
  • Timeout: Sets the maximum time to wait to complete a reading or writing of a certain amount of data. This time is set in milliseconds. If any operation exceeds this time limit, the buffers are cleaned up, the socket is verified and if some trouble is detected, the current socket will be closed and if EnableAutoReconnect is true, a attempt to connect a new socket will be made.
  • Active: This property controls the opening and closing of the socket. At development time, Active = true will open the socket and communicate with your device unless ExclusiveDevice is set to true.

Bellow is listed a example of how exchange data using the PascalSCADA communication ports directly on the source code, in other words, without use a protocol driver. As all the communication ports are descendants of TCommPort class, the example below also applies if you want to implement something using TTCP_UDPPort.

70 thoughts on “Communication ports

  1. Sergey Reply

    Hi! My name is Sergey, I from Russia. Wanted to install the latest version of Pascalscada, but failed , installed for Delphi 7. Now using version 0.7.2

  2. Maks Reply

    I can’t send or recieve data with SerialPortDriver in Win64 and Win32. I see examples, but i can’t to repaet them. Maybe there is some solution. Lazarus 1.8.0 scada 0.7.4.

  3. Maks Reply

    I did not find any examples, but I figured out the system’s work. But still, I did not have a definite mistake. When I add a few tags and connect to the HMI component, it displays some kind of nonsense if I do not use the built-in method of auto-reading, and I use the timer then it works.

    • Fabio Luis Girardi Post authorReply

      Hi @Marks!

      What are you trying to do? Please give some details about your hardware, protocols and network of your application.

  4. AJAY KUMAR Reply

    hi sir good afternoon, am ajay kumar from india. i started learning of HMI’s . my question is ” HMI having two ports COM0, COM1. while COM0 in connected with PLC to pass Modbus commands over TCP . While that is happening I want to read HMI registers from another COM port on the same HMI. How can we do that?

  5. AJAY KUMAR Reply

    hi , my name is AJAY from INDIA. i need some answer regarding below question. please review on this question
    basically HMI having 2 ports vise COM0 & COM1. now am connected COM0 to passed Modbus commands over TCP to PLC while HMI was master.
    While that is happening I want to read HMI registers from another COM port on the same HMI. How can we do that? Can you implement and show?

    • Fabio Luis Girardi Post authorReply

      Hi Mr. Ajay!

      Why not read and write using the same port (COM0)?

      I don’t understand if your slave is Modbus RTU or TCP. If your slave is Modbus RTU you can’t put your application using COM0 and COM1 communicating with the same PLC port, because Modbus RTU don’t alloos two masters on the same bus.

      But if:
      you are using Modbus RTU AND have two ports on your PLC


      you are using Modbus TCP

      You should put two:

      ** Two serial ports and two Modbus RTU protocolo driver, one for read other writing operations

      ** Two TCP_Udpport and two Modbus TCP driver, one for read other writing operations.

      For both cases:

      ** tags linked with with port dedicated for read, should autowrite set to false

      ** tags linked with port dedicated to write should autoread set to false

      ** Modbus driver linked with the port dedicated for read should have ReadOnly property set to true.

      I don’t what you want to do, but I hope this helps.

      The best regards from Brazil,


      • AJAY KUMAR Reply

        thnaks Fabio for valuable information . may i use this information to solve my problem , but still i confused.
        if any issues made during my working process i will ask questions , please give some guidance for me. i want to learn good HMI knowledge. i needed this . thank you sir.
        best regards AJAY KUMAR

  6. Rafael Reply

    Boa tarde!
    Fábio, é possível utilizando o pascalsacada trocar dados entres aplicações diferentes, tipo uma aplicação ser mestre e a outra escravo?

  7. Rafael Reply

    Gostaria de comunicar com Logo v8, poderia me dar um exemplo de configuração do pascalscada e se possível mostrar como configuro o logo.

  8. fozkan Reply

    Hello from Turkey. First of all thank you for this perfect project.
    I would like some update about baudrate list. As you know nowadays it is common to use upper baudrates. Could you add the following rates to TSerialPort.
    128000, 153600, 230400, 256000, 460800, 921600.

    P.S. : I am not sure if this is a right place for such kind of request.

    Thanks in advance.


    • Fabio Luis Girardi Post authorReply

      Hi Fatih!

      I’ll find the baudrates common to all supported OSes and keep you updated. If I’m right, these low baudrates are a Windows limitations. I will keep you updated.

      • fozkan Reply

        Hi Fabio,

        I have already tested in lab for modbus rtu protocol by adding extra baudrates above. Of course mentioned limits depend on the capability of hardware, our adapter works up to 2 Mbits.
        As I said I can make the modifications on code but in order to use up-to-date code without editing, it would be better, it also helps other people as well. I have just test it in Windows, but in next week, I can test in Linux .


        • Fabio Luis Girardi Post authorReply

          Hi Fatih!

          Can you check if these baud rates are available on Windows, installing your hardware on that? I’m reading into docs, and Windows appears to support only 128kbps baud rate… sad!

          Can you send me your modifications to merge into current code base?

    • sadik acar Reply

      fatih kardes benim pascalscada ile ilgili bir problemim var yardimci olabilirmisin

      iki ayri delphi programi ile plc ye baglaniyorum. birinciyi baglayinca sorun yok ama ikinciyi bagladigimda prg kitleniyor. diger tcp kompenantlarda denedim sorun yok

  9. Rafael B. Pimentel Reply

    Bom dia!
    Estou montando uma rede de PLCs via ethernet TcpIP e gostaria de saber se o PascalScada pode se comunicar com mais de um equipamento com uma unica porta.

    • Fabio Luis Girardi Post authorReply

      Bom dia Rafael!

      Não. E não é uma limitação do PascalSCADA e sim do design das conexões (UDP,TCP)/IP que são 1:1, ou seja, em qualquer sistema de supervisão vc terá esta limitação. A única excessão é se na outra ponta, você tem um equipamento que desempenha a função de gateway, como um gateway ModbusTCP => Modbus RTU. Ai neste caso sim, um unica conexão TCP pode ser usada para “conectar-se” com vários equipamentos Modbus RTU, mantendo a conexão TCP 1:1.

      Para solucionar seu problema no PascalSCADA, será necessário uma porta TCP/IP para cada equipamento que vc precisa comunicar.

      • Rafael B. Piementel Reply

        Certo… Quando você fala uma porta para cada equipamento você esta se referindo a uma porta física ou uma porta componente do Pascalscada, se for a componente, você teria algum exemplo de como gerenciar essa portas? Sei que a pergunta é simples, mas acontece que só havia tido experiencias com portas seriais.
        Ahhh… outra coisa, eu gostaria também de parabeniza-lo Fabio, com certeza sei q não se lembra de mim, mas a uns 7 ou 8 anos eu fiz meu primeiro contato contigo, eu ainda morava em Vitória ES, agora estou em Petrolina PE e fico muito feliz de ver que seu trabalho permanece em desenvolvimento e ajudando dessa maneira. Desenvolvi algumas soluções usando o PascalScada, como prensas, sistemas de pesagem e o maior foi desenvolvido a uns 3 anos, um sistema de gerenciamento de 60 medidores de grandezas elétricas da Schneider Electric, PM1200, usando a serial RS232->RS485 direto nos equipamentos de shopping aqui da região.

        • Fabio Luis Girardi Post authorReply

          Boa tarde Rafael!

          Lembro de ti sim, você me enviou screenshots de algumas de suas aplicações a alguns anos (que estão publicados na pagina de screenshots). Se quiser mandar mais alguns screenshots das suas aplicações, me ajuda bastante.

          Bom respondendo sua pergunta, são necessário vários componentes TCP_UDPPort do PascalSCADA inseridos na sua aplicação. Este componente representa um socket tcp/ip (que é uma das várias conexões lógicas que um equipamento pode ter) que correm sobre uma porta física, que geralmente é ethernet. Então sua solução terá um PC com uma porta ethernet ligada a um switch, e deste sairá a conexão física (leia cabos) para todos os seus equipamentos. Neste PC seu PC com uma porta ethernet (porta fisica) estará rodando uma aplicação feita no PascalSCADA com vários componentes TCP_UDPPort representando várias conexões lógicas, cada uma endereçada para um equipamento, todas saindo pela mesma porta ethernet do seu PC.

          Espero ter conseguido explicar a lógica de funcionamento de uma aplicação com multiplas conexões TCP/IP.

  10. Rafael B. Pimentel Reply

    Boa noite Fabio,

    Olha eu aqui de novo… quando desabilitamos o AutoRead e o AutoWrite, o comando para ler é simples de usar… mas na hr de usar o de escrita ele pede algumas informações que eu não soube decifra. Quanto ao prints… vou organizar e mandar tudo já com essa nova aplicação!!!

          • Fabio Luis Girardi Post authorReply

            TPLCTagNumber voce pode utilizar:

            TPLCBlock vc tem que fazer:
            setLength(values,2); //2 é o tamanho do bloco

  11. alk859 Reply

    Hi, Fabio! Thanks for your great work!
    I am trying to use SerialPortDriver to connect Modbus RTU via MOXA 5110 tcp NPort (Win32). Everything works fine, but after the program is completed, the process remains in memory, and the virtual COM port remains blocked. How to complete the process and release the port? My code OnFormClose:
    Thank you in advance!

  12. Rodrigo Reply

    Bom dia a todos , alguem sabe como fazer uma listagem de portas disponiveis com o combobox usando o serial do pascalscada

    atualmente utilizo uma “gambiarra” com o ” comcombobox” do modulo ” tcomport” no qual ele já vem programado para listagem das portas

    simplesmente faço o seguinte

    serialPortDriver1.COMport := comcombobox.Caption;

    como ele ja faz a listagem automatica da porta com ( com1, com2 com…) apenas comolo para ler o que está escrito nele.

    ele está funcionado perfeitamente essa “gambiarra” porem o Tcomport só funciona no windows , e futuramente pretendo migrar algumas coisas para ser utilizado no linux tambem .

    • Fabio Luis Girardi Post authorReply

      Bom dia Rodrigo!

      Você pode usar o editor da propriedade TSerialPortDriver.COMPort. A classe responsável por fazer a edição desta propriedade tem o seguinte nome: TPortPropertyEditor e está definida na unit scadapropeditor.pas, do pacote pascalscada.lpk (pascalscada_dsng.lpk se você estiver usando a versão trunk). É só criar um instancia desta classe chamar o metodo TPortPropertyEditor.GetValues(@ProcedimentoQueIraAdicionarAPortaEncontradaNoSeuCombobox); Depois de usá-lo, basta destruir.

  13. Сергей Александрович Reply

    Good day Fabio! How can pascalscada connect to a controller that is located on a different network?

  14. bill kang Reply

    Hello. I’m from China, bill.kang. I want to ask. Can I modify the code of SCADA according to my functional requirements through code modification?

  15. Paulo Portugal Reply

    Hi Fábio,

    I have a question about how asynchronous read requests can be sent on ModbusTCP.

    My problem is the following: I have a TPLCBLOCK_1 that is using function 16 (WriteMultiple registers) to update some Modbus registers on the server. I use the following TPLCBLOCK_1 method to do this. TPLCBLOCK_1.Write (…). Right after that I want to read another TPLCBLOCK_2 that is using function 3 (Read input registers) to read other set of Modbus registers. This function works cyclically. However, I intend to read immediately after TPLCBLOCK_1. Write (…). That is, I want to make an asynchronous reading (i.e. at that moment) of TPLCBLOCK_2. For this I used the method TPLCBLOCK_2.Read ().

    Things are working, but it was kind of a trial-error-trial because there is no documentation abut it and I had to analyze the source code to try to found the methods. I ask if this is the correct procedure?

    Paulo Portugal

    • Fabio Luis Girardi Post authorReply

      Hi Paulo!

      Sorry for taking too much time to reply. I’m having e-mail issues on this website, that doesn’t notify me about new comment messages.

      Tag.Read and Tag.Write are synchronous functions. They will stop the protocol scanner to do their job, and depending of your application, they can freeze it by a small time to complete the operation. To “do” asynchronous read after write your values, you have some options:

      1) watch the value of ValuesTimestamp and/or CommReadsOK, together with LastAsyncReadStatus, something like this:

      lastValueTimestamp := Tag.ValuesTimestamp;
      lastCommReadsOK := Tag.CommReadsOK;
      application.processMessages; //don’t remove this line.
      until (lastValueTimestamp < Tag.ValuesTimestamp) and (lastCommReadsOK < Tag.CommReadsOK) and (tag.LastAsyncReadStatus=ioOk); 2) use TPLCBLOCK_2.OnUpdate to know when the tag was updated by the protocol scanner, and check if the last update was successful. If successful, set a flag to allow your process to continue. 3) After write, use application.QueueAsyncCall to queue procedure to check your TPLCBLOCK_2 status. If the tag TPLCBLOCK_2 wasn't updated, queue the procedure, again, again and again. Similar to approach number 1, but without repeat ... until loop.

  16. Peter Reply

    Hi Fabio,

    i am trying to read holding registers from my Kostal Plenticore Inverter by using the laz_modbus_tcp_example from sourceforge but without success.
    I have double checked the IP Adress, Port Number and can open the port without error, but requesting a register from the inverter ends up with no result.

    There do i adjust the slave id of the inverter ?

    Thanks for your help in advance

  17. Miguel Reply

    Hi Fabio.

    I’m trying to send a command to a control board for a emergency generator.
    I’m success reading operation parameters. Not same story in write or send command.

    Board documentation indicate to write (in single command) to register 4104 and 4105 the values 35701 and 29835, respectively.
    This should set the board to AUTO Mode.

    On the side of the programming. Did you see this correct?


    Feb-16 08:42:32.107, iocWriteRead, Result=iorOK, Written: 00 00 00 00 00 09 00 10 10 08 00 01 02 00 00
    Feb-16 08:42:32.107, iocWriteRead, Result=iorOK, Received: 00 00 00 00 00 03 00 90 02
    Feb-16 08:42:35.200, iocRead , Result=iorTimeOut, Received: 00

    The registers are:
    – Write only.
    – Min. Value = 0
    – Max Value = 65535

    – Windows 10 (64bits).
    – Lazarus 2.0.10 (32bits)

    Thank you.

    • Miguel Reply

      Problems were in my side:
      1. Change from TPLCTagNumber.Write to TPLCBlock.ScanWrite. This change was made after better understanding of PascalSCADA by reading from documentation. Also reading from users questions and author answers (Fabio).
      2. Others issues not related to PascalSCADA.

      Works like a charm!

      • Fabio Luis Girardi Post authorReply

        The difference between that ScanWrite and Write, is that ScanWrite will queue the write command to be executed after other possible write commands queued before, while write command stops the read/write queue to execute your command. So if you need to do a emergency stop tag.write should be your choice.

  18. Rodrigo Hernandes Reply

    Olá bom dia.
    Aceita sugestões de novas funções em versões futuras ?

    Eu sei que minha parte é a mais fácil ( o pedir é fácil ). E sei também que é possível fazer , porem começa a exigir um pouco mais de conhecimento da linguagem.

    Mas são funções que para quem não programa comumente (delphi / Lazarus) ajudaria essa pessoa.

    Geralmente quem chega aqui pode ser a pessoa ( como eu ) que não conhece profundamente programação em pascal , e o seu software ajuda muito neste sentido.

    Tem alguns itens que fizeram falta por não está na lista de componentes , pessoalmente consegui fazer com outros meios para chegar no resultado, porem para quem está a muito pouco tempo vai encontrar muita dificuldade.

    A primeira coisa que senti muita falta foi um “Seletor de Porta COMM” “no estilo combobox” no qual seleciona as portas existentes , antigamente nos Pcs as portas com era bem fixas raramente mudava o numero , e poderiam deixar fixadas no programa , porem com o advento das USB/Serial , dependendo do modelo do adaptador, da porta USB e de quantas portas já existem a porta COM muda seu numero. fora que quando você tira o numero some.
    Atualmente estou usando um recurso do Tcomport ( um combobox já preparado para buscar as portas COMM existentes) para fazer essa seleção.

    Aproveitando este item poderia também fazer uns seletores dos outros itens de porta de comunicação (data bit,paridade,stopbit) apesar destes serem muito mais fácil adaptar um combobox, pois sempre vão ter disponível e fixo estas opções e são poucas.

    Como recentemente estava testando os CRC , outro item que seria interessante colocar seria uma informação em formato de texto(string) dos erros que está acontecendo , eu vi que já tem isso no “LastAsyncReadStatus” e existe vários erros , porem por exemplo o erro de CRC está como “IOCOMMERROR”
    ( não testei ainda só vi visualizando o código). fica muito genérico e não ajuda a quem está procurando o erro que está acontecendo.

  19. Rodrigo Hernandes Reply

    Um outro item que esqueci de mencionar que também ajudaria seria um visualizador de bytes recebidos/enviados , eu vi que no texto de log ele mostra os bits recebidos e enviados ….
    Seria legal ter isso em um MEMO para poder visualizar em nível de bytes ( EX: 01 03 05 00 00 …..CRC) isso tambem ajudaria a pessoa fazer um debug do seu sistema ……

  20. Reid Reply

    I am new on Pascalscada with Lazarus. I got Pascalscada on Lazarus. I have two buttons and two texts and set them as “OFF” on the Lazarus form. I want to be able to click the first button from Lazarus form to turn on the LED from the first slave Arduino. Click the second button from Lazarus form to turn on the LED from the second slave Arduino. Also, the first slave Arduino has a button, push the button which makes the first text from Lazarus Form to set as “ON”. Push the button again to change from “ON” to “OFF” Same with the button on the second slave Arduino. I just want a simple to get two Arduino working. They are connected with RS485. I just need to code for Lazarus, first slave Arduino, and second slave Arduino. Do you know where I can find the example code?

  21. Koen Reply

    I have a timeout problem using rtu in a simple test project connected via a virtual serial port (ST-LINK)) to a STM32 Nucleo board.
    Using ModScan64.exe I get this correct communication:
    XMT: [02][04][75][30][00][02][6b][fb]
    RCV: [02][04][07][88][00][88][00][c1][24]

    Using PascalScada (SerialPortDriver with Timeout=1000, ModBusRTUDriver, PLCTagNumber with refreshTime=2000 and TagType pttDWord ) I get this result:
    Jan-03 16:27:08.831, iocWriteRead, Result=iorOK, Written: 02 04 75 31 00 02 3A 3B
    Jan-03 16:27:08.831, iocWriteRead, Result=iorOK, Received: 02 04 07
    Jan-03 16:27:14.199, iocRead , Result=iorTimeOut, Received: 88 00 88 00 C1 24 00 00 00
    Jan-03 16:27:14.231, iocWriteRead, Result=iorOK, Written: 02 04 75 31 00 02 3A 3B
    Jan-03 16:27:14.231, iocWriteRead, Result=iorOK, Received: 02 04 07
    Jan-03 16:27:19.517, iocRead , Result=iorTimeOut, Received: 88 00 88 00 C1 24 00 00 00
    Jan-03 16:27:19.541, iocWriteRead, Result=iorOK, Written: 02 04 75 31 00 02 3A 3B
    Jan-03 16:27:19.541, iocWriteRead, Result=iorOK, Received: 02 04 07

    Any hint as where this 5 to 6 seconds “delay” comes from?
    Windows 10, Lazarus 2.2.6
    Thanks in advance for any help!

    • Fabio Luis Girardi Post authorReply

      I never used the Modbus function $04. I’m looking at the sources and to communication packets to understand what’s happening.

    • Fabio Luis Girardi Post authorReply

      In the Modbus RTU documentation, is wrote that the reply of function 0x04 is similar to the function 0x03.

      So, looking to exchanged Modbus RTU Packets, I saw

      Jan-03 16:27:08.831, iocWriteRead, Result=iorOK, Received: 02 04 07

      So, the Modbus RTU driver expects 7 more data bytes plus 2 bytes of CRC to be read on next request. But only 6 bytes are available. The missing 3 bytes are zero filled. Timeout happens and CRC checks fails.

      I’ll try to simulate this function soon as possible.

  22. Koen Reply

    Hello Fabio. thank you!
    We should have noticed that ourself.
    But I have another issue.
    I noticed that setting the ProtocolDriver in a PLCTagNumber during design results in a high (25%) CPU-load for Lazarus.
    Without setting the ProtocolDriver it is near 0%.
    My workaround is setting the ProtocolDriver in FormCreate. No problem for me.
    Is this a wanted behavior?
    Thanks again!

  23. Koen Reply

    Set the property ReadSomethingAlways of your modbus rtu driver to false.
    I tried. It makes no difference in CPU usage.

  24. Koen Reply

    “In the other hand send this application that reproduces this to be analyzed.”
    ==> send by answering your mail

Leave a Reply

Your email address will not be published. Required fields are marked *