Click here to Skip to main content
Click here to Skip to main content

Omron PLC Serial Interface

, 1 Aug 2011 CPOL
Rate this:
Please Sign up or sign in to vote.
Surpass Omron OCX OPC Component and use a user friendly .NET based class to interface Omron PLC Series


If you're tired of using some complex non-realtime COM/COM+ components (as I'm ;D) that force you to connect Omron PLC series and are interested in an easy understanding, open source, real real-time .NET based object, you've just selected the right article.

This article introduces a purely code-based Host link protocol implementation, what you can easily add into your project ensures you a safe reliable RS232/485 PC-PLC communication.


OOP programming and using an accurate implementation in realtime hardware dependant is something I've done once in DeltaDTB PID Controller. You can refer to it from here.

Using the Code

1. Wiring

With no doubt, the most confusing matter one may face, after reading the PDF file reduced from Omron describing the Host Link attributes, is physical connection (cable wiring). After first perusing, I made some wiring hoping it would work, but there was no success despite all my efforts. Finally, the old popular RS232 (2-2, 3-3, 5-5) was the thing answered properly (look at the below picture).


2. Communication Protocol

2.1 Basic Definitions

  • Host Computer

    In host link communication protocol, the host computer (please note Omron refers to "computer" for its PLC series, please don’t mix up!) has the transition priority, but for the case of peer to peer connection (e.g. you directly connected to a PLC via RS232 physical layer) noting this matter is not very important, but if you’re very sensitive and scrupulous about, due to Omron definition "Data transfer between the host computer and the Host Link System is, therefore, initiated when the computer sends a command to a PC in the Host Link System." (part 3-2, Communication Protocol, page 62), the PC which runs the application assumed as Host Computer.

  • Block

    A set of data in a transmission is called a block.

  • Command Block

    The data block sent from the host computer to the Host Link System is called a command block.

  • Response Block

    The block sent from the Host Link System to the computer is called a response block.

  • Multiplex Communication versus Single Link Communication

    In a multiple-link communications system, each block starts with a unit number and a header, and ends with a Frame Checksum (FCS) code and a terminator (* and CR). In a single-link system, however, each block starts with only a header, and ends with only a terminator.

  • Termination

    The terminator in the command block enables the PC to send a response. The terminator in the response block enables the host computer to send another command.

2.2 Block Formation

Below is a scheme of a formal data block. A block is usually made up of one unit called a frame, but long blocks of data (over 131 characters) must be divided into more than one frame before transmission. In a multiple-link system, the first frame can have up to 131 characters, and subsequent frames can have up to 128 characters.

In a single-link system, however, every frame (the first included) has up to 128 characters. The data must then be divided into more than one frame when there is a block consisting of more than 131 characters in a multiple-link system and of more than 128 characters in a single-link system. In this case, the beginning and intermediate blocks end with a delimiter (CR), instead of a terminator (* CR).


Note: In this project, Multiple-link System is assumed as in-use method, so, inserting "@" and unit number is mandatory and done automatically when requests for reading/writing is demanded.

2.2.1 Block Formation with more than one frame in Multi-Link System

First Frame (131 characters or less)


Intermediate Frame(s) (128 Characters or less)


Last Frame (128 characters or less)


2.3 Sending Commands

To send a command block with more than one frame from the computer (host computer), initially send only the first frame in the block. We must wait for sending the next frame until the host computer has received the delimiter which should have been sent back from the PC.

Note: Do not separate data from a single word into different frames for any write command.


The best place of use is when you try to write a long stream of data in a sequence of registers (although I don't advice this matter).

        str_in = str_in & Link.ReadExisting
    Loop While ((str_in.Length < length_predicted) And _
	((DateAndTime.Now.Ticks - tmr_indicator) < lng_length))
    'Checking FCS code
    'Checking PLC Response code (No Command Error)
    'Assume we're waiting for frame(s)
    'The matter that must be checked is the penultimate and the last
    'character received from PLC.
    if mid$(str_in,str_int.length - 1,1)<>"*" then 	'Means some frame(s) 
						'are ready to be received
        'First Process Data 
        'Clear RS232 Input Buffer
        str_out = Link.readExisting
        'str_out = ""
        link.Write(vbCr)'Indicates Host Computer is ready to receive data
    end if
Loop While loop_condition

2.4 Receiving Commands

To receive a response block consisting of more than one frame from the PC, the host computer must send the carriage return code (delimiter) to the PC after receiving the delimiter from the PC. This enables the PC to send the next frame.


Its obvious usage is in Read method, where for example, the user's demanded reading a more 30 consequence registers. After making the string indicates from what address and how many register(s) user requested, we entered a loop waiting for PLC response. Don't forget it's essential to keep the requested numbers in a variable.

Dim loop_count As Integer = 0, count_predicted As Integer = 0, 
_As Long = 0, tmr_indicator As Long = 0, 
_As Integer = 0
Dim str_in As String = "", str_in_final As String = "" 
str_in = Link.ReadExisting()
str_in = "" 
    str_in = "" 
    count_predicted = IIf(count > 30, 30, count)
    If loop_count = 0 Then
        If count_predicted = count Then 
            length_predicted = count_predicted * 4 + 11
            length_predicted = count_predicted * 4 + 10
        End If 
        If count_predicted = count Then 
            length_predicted = count_predicted * 4 + 4
            length_predicted = count_predicted * 4 + 3
        End If
    End If 
    lng_length = (length_predicted * ByteTime * 1000) + delay_ms
    lng_length *= TimeSpan.TicksPerMillisecond
    tmr_indicator = DateAndTime.Now.Ticks
        str_in = str_in & Link.ReadExisting
    Loop While ((str_in.Length < length_predicted) And _
	((DateAndTime.Now.Ticks - tmr_indicator) < lng_length))
    If ((loop_count > 0) And (str_in.Length < length_predicted)) _
	Then Throw New OmronException("Error in Data line, Data corrupted!")
    If loop_count = 0 Then 'Indicates first frame
        p_response = Hex2Int(Mid$(str_in, 6, 2))
        If Mid$(str_in, str_in.Length, 1) <> vbCr Then _
	Throw New OmronException("Error in Data line, Data corrupted!")
        If Not (FCSCode_Get(str_in)) Then Throw New OmronException_
	("Comminucation Error, Please check the line!")If p_response <> _
	Omron_Response_Code.Command_Completed_Normally Then _
	Throw New OmronException(Response(p_response)(0))
        If count_predicted = count Then 'One block contains the whole response 
            str_in_final = str_in_final & Mid$(str_in, 8, str_in.Length - 11)
        Else 'It's the first block of a sequence of response blocks 
            str_in_final = str_in_final & Mid$(str_in, 8, str_in.Length - 10)
        End If
        If count_predicted = count Then 'Indicates last frame 
            str_in_final = str_in_final & Mid$(str_in, 1, str_in.Length - 4)
        Else 'Indicates intermediate frame 
            str_in_final = str_in_final & Mid$(str_in, 1, str_in.Length - 3)
        End If
    End If 
    str_in = Link.ReadExisting
    if count_predicted < count then Link.Write(vbCr)
    str_in = "" 
    count = IIf(count - 30 > 0, count - 30, 0)
    loop_count += 1

Loop While count > 0 

2.5 Data Representation

Unit Address, Register Address and number of registers to be read must be represented in Decimal format, Register contents which to be read/written must be presented in hexadecimal format and Boolean is represented as "1" (ASCII 49dec)(true) and "0" (ASCII 48dec)(false).

2.6 Frame CheckSum (FCS) Calculation

The Frame Checksum is 8-bit data converted into two ASCII characters. The 8-bit data is the result of an EXCLUSIVE OR sequentially performed between each character, from the first character in the frame to the last character of the text in that frame.

Dim [xor] As Integer = IIf(is_last, 0, 64) '@ascii code 
For I As Integer = 1 To Message.Length - 1
    [xor] = [xor] Xor Convert.ToInt32(Convert.ToChar(Message.Substring(I, 1)))
Return ([String].Format("{0:X}",[xor]))

The FCS generator piece of code is mentioned above.

3. Command Level

The tables on pages 60 to 62, give the commands and responses available for the Host Link Units, the command levels, and the modes in which they are applicable. Details of the command and response formats are given in Omron Document, Section 4 Commands and Responses.

Using the Demo, Step by Step

3.1 Running the program


3.2 Checking whether any PLC is connected or not


Program could not find any PLC (No response from PLC).


Program could find a PLC (Response is received).

3.3 Reading PLC Status and Errors


3.4 Reading 30 sequence Registers from PLC



It's my appreciation to thank Prof. Kamalaldin Farzaneh, who is not only my manager, but also my teacher who has let me test, fall and rise again.


  • Creation Time: Wednesday Apr 27 2011
  • First Release: Saturday Apr 30 2011
  • Updated: Tuesday May 03 2011
  • Updated: Sunday July 24 2011, Labview 7.0 Implementation added


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Mahdi Mansouri
Malaysia Malaysia
PhD Candidate in Biomedical Eng., Control
M.Eng Electronics, Control
B.Eng Computer, Hardware
That's all ;D !

Comments and Discussions

QuestionCommunicating with Omron CP1H PinmemberMember 113624158-Jan-15 13:04 
QuestionWrite() not behaving Pinmemberchriskat26-Oct-14 19:25 
AnswerRe: Write() not behaving Pinmemberchriskat28-Oct-14 18:54 
AnswerRe: Write() not behaving PinmemberMahdi Mansouri1-Dec-14 16:55 
QuestionWhat PLC Pinmemberfab4real23-Jan-13 1:45 
AnswerRe: What PLC Pinmemberfab4real23-Jan-13 4:03 
GeneralRe: What PLC PinmemberMahdi Mansouri25-Jan-13 2:32 
GeneralRe: What PLC PinmemberMr-H 201010-Jul-13 1:42 
QuestionHie Pinmembersajidconsultrics26-Nov-12 12:01 
AnswerRe: Hie PinmemberMahdi Mansouri25-Jan-13 2:25 
Questiondeny Pinmemberpoliku12-Sep-12 15:34 
AnswerRe: deny PinmemberMahdi Mansouri27-Oct-12 18:53 
GeneralMy vote of 5 PinmemberNeXoR.aT30-Jul-12 0:01 
GeneralRe: My vote of 5 PinmemberMahdi Mansouri27-Oct-12 19:41 
QuestionProgram could not find any PLC (No response from PLC). PinmemberCOl2nSheZz26-Jun-12 17:27 
AnswerRe: Program could not find any PLC (No response from PLC). PinmemberMahdi Mansouri27-Oct-12 18:50 
QuestionError (LabVIEW2010) : "This assembly contains no public controls" Pinmemberkanjoot10-Apr-12 22:57 
Hi Mr. Mahdi,
I would like to try the hostlink communication using LabVIEW. I am using LabVIEW2010. I have tried to follow the steps, and importing Omron.dll by "Tools>>Advanced>>.Net Assembly Reference" (in LabVIEW2010 by "Tools>>Import>>.NET Controls to Palette"). When I importing Omron.dll, I found error "This assembly contains no public controls".
Would you please to explain more aabout importing omron.dll?
AnswerRe: Error (LabVIEW2010) : "This assembly contains no public controls" PinmemberMahdi Mansouri12-Apr-12 0:32 
GeneralTransmission failed in progress Pinmemberqnguyen522-Mar-12 19:21 
AnswerRe: Transmission failed in progress PinmemberMahdi Mansouri23-Mar-12 1:23 
GeneralRe: Transmission failed in progress Pinmemberqnguyen524-Mar-12 19:15 
QuestionHost link protocol PinmemberFidel Naranjo2-Dec-11 5:40 
AnswerRe: Host link protocol PinmemberMahdi Mansouri2-Dec-11 15:28 
QuestionVB version, [modified] PinmemberFidel Naranjo1-Dec-11 4:57 
AnswerRe: VB version, PinmemberMahdi Mansouri1-Dec-11 14:44 
GeneralRe: VB version, PinmemberFidel Naranjo2-Dec-11 0:01 
QuestionThanks, 42 Pinmemberdeviker20-Sep-11 12:11 
Generalwiring PinmemberNuno Leitao3-May-11 1:59 
GeneralRe: wiring PinmemberMahdi Mansouri3-May-11 2:15 
Generalinteresting PinmemberYves2-May-11 15:23 
GeneralRe: interesting PinmemberMahdi Mansouri2-May-11 20:51 
GeneralVery interesting article PinmemberRoberto Guerzoni30-Apr-11 4:14 
AnswerRe: Very interesting article PinmemberMahdi Mansouri30-Apr-11 18:56 
GeneralRe: Very interesting article PinmemberRoberto Guerzoni1-May-11 7:58 
GeneralRe: Very interesting article PinmemberMember 40534241-May-11 13:12 
AnswerRe: Very interesting article PinmemberMahdi Mansouri1-May-11 22:36 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.150327.1 | Last Updated 2 Aug 2011
Article Copyright 2011 by Mahdi Mansouri
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid