TBLLC

Omron PLC cs / cj2 read / write data over Python

17 posts in this topic

Hi I am looking for a way to read and write data from PLC omron words, bits via FINS or EtherNet/IP protocol using python programming lang.

Does anyone have any results in this? I really want to see your work, because all my attempts have failed. Thanks.

Share this post


Link to post
Share on other sites

Good day, i am testing this script and have a simle relesult:

but I can’t read the memory of the plc
bits and words.

i am use this manual for experements:

https://github.com/pjkundert/cpppo/files/1088579/EIP21.omron.pdf

 

import sys
import time

from cpppo.server.enip.get_attribute import proxy_simple
from cpppo.server.enip import poll
from cpppo.server.enip.get_attribute import proxy_simple as device

product_name, = proxy_simple ("192.168.135.60") .read ([('@ 1/1/7', 'SSTRING')])
var1 = product_name
print(product_name)
if var1 == ['CJ2M-EIP21']:
	print('connection comp.')

data2, = proxy_simple ("192.168.135.60") .read ([('@ 196/0/100', 'INT')])
var2 = data2

if var2 == [4]:
	print('CPU in execution mode')
if var2 == [2]:
	print('CPU in monitoring mode')
if var2 == [1]:
	print('CPU in stop mode')

Share this post


Link to post
Share on other sites

These are always interesting and fun projects to play around with. By today's standards, you can get HMIs, SCADA and/or PC drivers to accomplish what you are trying to do. The costs will vary.

You can communicate with Omron PLCs in a few different methods depending upon the PLC hardware. Almost any programming language will work. I've done a few in the old days using BASIC language and Omron's Host Link commands (RS232C).

You are using Ethernet so you have found the options are FINS and Ethernet/IP. Ethernet/IP will prove to be very difficult. Unless you are well versed in EtherNet/IP protocol, it will consume your time in understanding it, deciding on the type of EIP method use, then establishing communications with the PLC. 

FINS will be your best bet if you wish to pursue your quest. There are several examples using DotNet and ActiveX in the downloads section here at MrPLC. https://forums.mrplc.com/index.php?/files/category/48-utilities/ It should be easy enough to see exactly what the programming is sending the PLC. You'll just need to change your code to Python.

Along with the examples, you'll also want to use the FINS Command Reference Manual W227 to better understand what these programs are doing.

Share this post


Link to post
Share on other sites
16 hours ago, IO_Rack said:

These are always interesting and fun projects to play around with. By today's standards, you can get HMIs, SCADA and/or PC drivers to accomplish what you are trying to do. The costs will vary.

You can communicate with Omron PLCs in a few different methods depending upon the PLC hardware. Almost any programming language will work. I've done a few in the old days using BASIC language and Omron's Host Link commands (RS232C).

You are using Ethernet so you have found the options are FINS and Ethernet/IP. Ethernet/IP will prove to be very difficult. Unless you are well versed in EtherNet/IP protocol, it will consume your time in understanding it, deciding on the type of EIP method use, then establishing communications with the PLC. 

FINS will be your best bet if you wish to pursue your quest. There are several examples using DotNet and ActiveX in the downloads section here at MrPLC. https://forums.mrplc.com/index.php?/files/category/48-utilities/ It should be easy enough to see exactly what the programming is sending the PLC. You'll just need to change your code to Python.

Along with the examples, you'll also want to use the FINS Command Reference Manual W227 to better understand what these programs are doing.

Thank you very mutch for your answer, i will try your suggestion.

Share this post


Link to post
Share on other sites
15 hours ago, Michael Walsh said:

A colleague of mine has done extensive work with Python and communicating with Omron PLCs.  

Here is some FINS Python stuff that might be useful:

https://aphyt.com/index.php/projects

Thank you very mutch for your answer, i will try it, and writing result test.

Share this post


Link to post
Share on other sites
2 hours ago, TBLLC said:

Thank you very mutch for your answer, i will try it, and writing result test.

mem_area = fins_instance.memory_area_read(fins.FinsPLCMemoryAreas().CIO_WORD,b'\x00\x64\x00')

CIO reading great worked, thank you very mutch, but how to read D memory? do you have example? Thanks.

Where can I find a description of the library?

Share this post


Link to post
Share on other sites

good news im have a result read D (DM) area memory, use this request:

mem_area_dm_word = fins_instance.memory_area_read(FinsPLCMemoryAreas().DATA_MEMORY_WORD,b'\x00\x03\x00')
print(mem_area_dm_word)

DATA_MEMORY_WORD,b'\x00\x03\x00') = D00003

but it's impossible read D > 100 D1234 for an example, how to create a request? for read D > 100 where to find the author of the library?

Edited by TBLLC

Share this post


Link to post
Share on other sites

I received a reply from the author of the library (his email is also in the source code and on the contact page at the link provided above):

It is all hex according to the memory address designation of FINS so 1234 would be \x04\xd2 and since it is a DM, the bit designation is \x00, so it would be:

 

mem_area_dm_word = fins_instance.memory_area_read(FinsPLCMemoryAreas().DATA_MEMORY_WORD,b'\x04\xd2\x00')

print(mem_area_dm_word)

Share this post


Link to post
Share on other sites
13 hours ago, Michael Walsh said:

I received a reply from the author of the library (his email is also in the source code and on the contact page at the link provided above):

It is all hex according to the memory address designation of FINS so 1234 would be \x04\xd2 and since it is a DM, the bit designation is \x00, so it would be:

Thank you very mutch for your fast feedback and and special thanks to the author for support, some more one question please:

When i read dm data for example dm3 register (2 characters) i get correct result

request:

mem_area_dm_word = fins_instance.memory_area_read(FinsPLCMemoryAreas().DATA_MEMORY_WORD,b'\x00\x03\x00')

answer:

b'\xc0\x00\x02\x00\x19\x00\x00\x01\x00`\x01\x01\x00\x00\x00\x11'

PLC memory table have result: 0011

if i read a value more than 2 characters:

request:

mem_area_dm_word = fins_instance.memory_area_read(FinsPLCMemoryAreas().DATA_MEMORY_WORD,b'\x00\x06\x00')

answer:

b'\xc0\x00\x02\x00\x19\x00\x00\x01\x00`\x01\x01\x00\x00%U'

PLC memory table have result: 2557

Using this request format if answer data < 1000 result is correct accordingly if answer > 1000 result is incorrect

calculated by checking different DM registers as a result there is such a dependence

 

 

Edited by TBLLC

Share this post


Link to post
Share on other sites

From the author:

The print statement is printing raw bytes as that is the response from the PLC. By default Python’s print will format any printable characters as ASCII, which you can detect by the fact that they are not preceded by the \x statement indicating they are hex. With this in mind the % character is ASCII value hex \x25 and U is ASCII value hex \x55, which leads me to believe it is a process value and the least significant byte is noise (hence the 55 vs 57 difference from the memory table). Normally the programmer would slice the bytes that they read off the response and format them the way that the intend to use them (FINS doesn’t know if that hex value is an integer, unsigned integer, real, etc.). If you always want the response in hex, you can use the binascii.hexlify library.

Share this post


Link to post
Share on other sites
On 02.12.2020 at 6:34 PM, Michael Walsh said:

From the author:

The print statement is printing raw bytes as that is the response from the PLC. By default Python’s print will format any printable characters as ASCII, which you can detect by the fact that they are not preceded by the \x statement indicating they are hex. With this in mind the % character is ASCII value hex \x25 and U is ASCII value hex \x55, which leads me to believe it is a process value and the least significant byte is noise (hence the 55 vs 57 difference from the memory table). Normally the programmer would slice the bytes that they read off the response and format them the way that the intend to use them (FINS doesn’t know if that hex value is an integer, unsigned integer, real, etc.). If you always want the response in hex, you can use the binascii.hexlify library.

 

 

Thank you wery mutch for your answer this is very important for me.

Share this post


Link to post
Share on other sites
On 11/30/2020 at 10:41 PM, Michael Walsh said:

A colleague of mine has done extensive work with Python and communicating with Omron PLCs.  

Here is some FINS Python stuff that might be useful:

https://aphyt.com/index.php/projects

Hi, do you happen to have an example for reading and writing Boolean IO via FINS? I tried using the examples that was in the link attached but ran into several errors:
1. My python compiler was not able to recognize "memory_area.write" 
2. For "CIO_WORD", my compiler says Unresolved attribute reference 'CIO_WORD' for class 'FinsPLCMemoryAreas'. For this, based on my understanding it is because the example was made for words and bits, correct me if I'm wrong. I hope there is some solutions or examples to my errors and problems. Thanks in advance

fins_instance.memory_area_write(fins.FinsPLCMemoryAreas().CIO_WORD,b'\x00\x64\x00',b'\x00\x1f',1)

Share this post


Link to post
Share on other sites

Hi there. I'm trying to communicate to a CJ1M-CPU11 PLC using this Python FINS library. I've copied the sample program but I don't write in CIO memory nor read it. Is there any other configuration beside IP addresses? I don't know if this parameters are default or I should change something else: 

fins_instance.dest_node_add=1

fins_instance.srce_node_add=25

Thanks a lot!

 

Edit: Alright I solved it. Didn't know node number was last IP address digit until I researched a bit :-1

Edited by Robror

Share this post


Link to post
Share on other sites

I'm using a CJ2M CPU33. I used the same python library with success. Here is a sample of code i used to put results in excel. 

import time
import fins.udp


fins_instance = fins.udp.UDPFinsConnection()
fins_instance.connect('192.168.0.14')
fins_instance.dest_node_add=14
fins_instance.srce_node_add=249


for i in range(1):
     
    mem_area = fins_instance.memory_area_read(fins.FinsPLCMemoryAreas().DATA_MEMORY_WORD,b'\x00\x64\x00')
    time.sleep(1)
    mem_area = int.from_bytes(mem_area,'big')
    mem_area = bin(mem_area)
    print(mem_area)
    

from openpyxl import load_workbook
wb = load_workbook(filename = 'bin2hex.xlsm',keep_vba=True)
ws1 = wb.active
ws1['H1'] = mem_area
wb.save('bin2hex.xlsm')
    

Share this post


Link to post
Share on other sites

Hi there! So i've been messing around with the library Michael shared in order to send/receive data from a CJ1M CPU. My only question regarding the use of this library is: is it possible to disconnect and connect again? I've been trying to, but whenever I try to connect again I get "[WinError 10022] An invalid argument was supplied" error. I tried calling __del__ method of UDPFinsConnection class with no result. 

I've been reading about sockets in Pyton, but my knowledge on the subject is very limited and I was wondering if someone knew something about this connections in Python.

Thanks in advance!

Share this post


Link to post
Share on other sites

I have not experienced that issue using that module. If you disconnect the cable and plug back in it will that a second for the pc to reestablish the lan connection.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now