Any idea how to access the Omron simulator?

strantor

Member
Join Date
Sep 2010
Location
katy tx
Posts
401
I wrote the PLC & HMI program for a subsea tool that we have developed (similar to an ROV but much simpler), and also the user's manual and now working on the training program. We want to have a 3D simulator for operator training. I have no prior experience in 3D animation, but being so deeply ingrained in the operation of the tool, I was chosen as "the guy" to make it happen. For the past weeks I have struggled with a 3D animation suite called Blender, and finally I have created all the geometry and textures and made some animated functions. I have created a very basic 3D video game, starring our tool, using Blender.

Now I would like to incorporate the HMI as part of the simulation, using a touchscreen PC monitor (or NS HMI, if I must). Rather than re-programming all the functions of the PLC and all of the functions of the HMI in Python (the native language of Blender) and recreating all of the graphics, I would like to use what I have already created in CX-Programmer and/or CX-Designer.

I am considering the following possibilities:
Run CX-Programmer and CX-Designer both in simulation mode, linked together. Have Blender inject sensor values and read DMs to/from the link.

Run CX-Designer in simulation mode, linked to blender (I trick CX-Designer to into thinking that Blender is CX-Programmer).

I buy another NS touchscreen and CJ PLC, link them together, and use OmronCSCJEthernetControl OCX to interface Blender with the physical setup. <- I would like to avoid this option.

Any other ideas?
Any thoughts on how to accomplish any of these options, specifically accessing ("hacking") the Omron simulator link?
 
UPDATE:
I have made some progress on this if anybody is interested. I have NOT found a way to hack the CX simulator or communicate with a simulated PLC by FINS commands. I am using an actual PLC and actual HMI (though I could simulate the HMI if wanted). I have created a video game in blender which reads from and writes to the PLC using FINS commands over TCP.

I started with this python 2 FINS code and converted it over to Python 3, which did not convert over gracefully. It took an unjustified amount of finagling to make it work.

Then I wrote an interface script to help it work with Blender. There are a few reasons why this interface script was necessary:

1. I'm a NOOB and couldn't figure out a sleeker way to do it.

2. Looping scripts cause Blender to crash, so the script must be run (repeated) each frame (@24FPS). BUT Blender runs a new instance of the script each time, so looping the original script over and over would result in a new socket connection 24 times per second, which causes the PLC to stop responding to FINS commands. So the original script must run in the background and connect only once, while a different script is executed @ 24FPS making calls to the original every frame.

3. The read/write functions provided in the original script [readMemC(), readFloat(), etc] are individual FINS commands and take about 40mS each to complete. So if you wanted to read 220 DMs, that's almost 9 seconds. In order to get fluid movements out of video game objects, ideally we want a position update every ONE frame, not every 200+ frames. So I wrote new read/write functions. The new read function reads all of memory-areas-of-interest as one single FINS command, and stores them in a library so that you can call them in any order anywhere in your script. The new write command gathers up all of your various "writes" within the script and arranges them into a single command frame and sends it at the end of the script. This cuts the comms time down from 8,800 mS to around 60mS (around every 3 frames - you won't notice it isn't fluid unless you're looking for it). That's 60mS for any number of memory areas up to 249.

4. The original script only allowed for read/write of 16bit UINTs and 32bit REALs. I added funtionality to read/write BCD(UNsigned, BIT signed, and DIGIT signed INTs, DINTs, and LINTs), BITs*, and 32bit and 64bit INTs (signed & unsigned). I may or may not add ASCII/String & HEX functions; I don't need them.

*my bit write function is a compromise. It writes as a word, not a single bit. Behind the scenes it reads a word in, modifies a single bit, and writes it back out. This method leaves room for unpleasant experience if writing a bit surrounded by other critical bits. Best to isolate bits written by python away from other bits used in PLC logic.

5. the original script had little error/exception handling. So errors were shown in cryptic python explanations on a crash screen. I have added a lot of error handling which points in logical directions for debugging.

Here is a sample Python script calling on functions in my Blender interface script (which calls on the original converted Python 2 FINS script):

Code:
import omrblend2

t0 = int(round(omrblend2.time.time() * 1000))
omrblend2.omron().connect("192.168.1.101",9600)

myplc_memD = omrblend2.MasterFetch()
myplc_memD.Fetch("d",300,1000)


#******************************BITS******************************
wbit = myplc_memD.writeBOOL
rbit = myplc_memD.readBOOL

#read/write Bits (16bit words)
MyBitX = "d437.1"
MyBitY = "D437.5"
MyBitZ = "D438.5"
x=rbit(MyBitX)
print("MyBitX ("+MyBitX+") read: " + str(x))
x =abs(1-x)
print("MyBitX ("+MyBitX+"), MyBitY ("+MyBitY+"), MyBitZ ("+MyBitZ+") written: " + str(x))
wbit(MyBitX, x)
wbit(MyBitY, x)
wbit(MyBitZ, x)


#******************************Float******************************
wf = myplc_memD.writeREAL
rf = myplc_memD.readREAL

#read/write FLOAT (32bit)
MyFloat = "d435"
x=rf(MyFloat)
print("MyFloat ("+MyFloat+") read: " + str(x))
x +=1
print("MyFloat ("+MyFloat+") written: " + str(x))
wf(MyFloat, x)



#******************************BCD******************************
wbcd = myplc_memD.writeINT_BCD
rbcd = myplc_memD.readINT_BCD

#read/write unsigned single BCD
MySingleUBCD = "d400"
x=rbcd(MySingleUBCD)
print("MySingleUBCD ("+MySingleUBCD+") read: " + str(x))
x +=1
print("MySingleUBCD ("+MySingleUBCD+") written: " + str(x))
wbcd(MySingleUBCD, x)

#read/write BIT signed single BCD
MySingleBSBCD = "d401"
x=rbcd(MySingleBSBCD,"b")
print("MySingleBSBCD ("+MySingleBSBCD+") read: " + str(x))
x +=1
print("MySingleBSBCD ("+MySingleBSBCD+") written: " + str(x))
wbcd(MySingleBSBCD, x,"b")

#read/write DIGIT signed single BCD
MySingleDSBCD = "d402"
x=rbcd(MySingleDSBCD,"d")
print("MySingleDSBCD ("+MySingleDSBCD+") read: " + str(x))
x +=1
print("MySingleDSBCD ("+MySingleDSBCD+") written: " + str(x))
wbcd(MySingleDSBCD, x,"d")

#read/write unsigned Double BCD
MyDoubleUBCD = "d403"
x=rbcd(MyDoubleUBCD, "u", length=2)
print("MyDoubleUBCD ("+MyDoubleUBCD+") read: " + str(x))
x +=1
print("MyDoubleUBCD ("+MyDoubleUBCD+") written: " + str(x))
wbcd(MyDoubleUBCD, x,"u",2)

#read/write BIT signed Double BCD
MyDoubleBSBCD = "d405"
x=rbcd(MyDoubleBSBCD, "b", 2)
print("MyDoubleBSBCD ("+MyDoubleBSBCD+") read: " + str(x))
x +=1
print("MyDoubleBSBCD ("+MyDoubleBSBCD+") written: " + str(x))
wbcd(MyDoubleBSBCD, x,"b",2)

#read/write DIGIT signed Double BCD
MyDoubleDSBCD = "d407"
x=rbcd(MyDoubleDSBCD, "d", 2)
print("MyDoubleDSBCD ("+MyDoubleDSBCD+") read: " + str(x))
x +=1
print("MyDoubleDSBCD ("+MyDoubleDSBCD+") written: " + str(x))
wbcd(MyDoubleDSBCD, x,"d",2)

#read/write unsigned Long BCD
MyLongUBCD = "d409"
x=rbcd(MyLongUBCD, "u", 4)
print("MyLongUBCD ("+MyLongUBCD+") read: " + str(x))
x +=1
print("MyLongUBCD ("+MyLongUBCD+") written: " + str(x))
wbcd(MyLongUBCD, x,"u",4)

#read/write BIT signed Long BCD
MyLongBSBCD = "d413"
x=rbcd(MyLongBSBCD, "b", 4)
print("MyLongBSBCD ("+MyLongBSBCD+") read: " + str(x))
x +=1
print("MyLongBSBCD ("+MyLongBSBCD+") written: " + str(x))
wbcd(MyLongBSBCD, x,"b",4)

#read/write DIGIT signed Long BCD
MyLongDSBCD = "d417"
x=rbcd(MyLongDSBCD, "d", 4)
print("MyLongDSBCD ("+MyLongDSBCD+") read: " + str(x))
x +=1
print("MyLongDSBCD ("+MyLongDSBCD+") written: " + str(x))
wbcd(MyLongDSBCD, x,"d",4)

#******************************INT******************************
wint = myplc_memD.writeINT
rint = myplc_memD.readINT

#read/write UNsigned single INT
MySingleUINT = "d421"
x=rint(MySingleUINT)
print("MySingleUINT ("+MySingleUINT+") read: " + str(x))
x +=1
print("MySingleUINT ("+MySingleUINT+") written: " + str(x))
wint(MySingleUINT, x)

#read/write signed single INT
MySingleSINT = "d422"
x=rint(MySingleSINT,"s")
print("MySingleSINT ("+MySingleSINT+") read: " + str(x))
x +=1
print("MySingleSINT ("+MySingleSINT+") written: " + str(x))
wint(MySingleSINT, x,"s")

#read/write UNsigned Double INT
MyDoubleUINT = "d423"
x=rint(MyDoubleUINT)
print("MyDoubleUINT ("+MyDoubleUINT+") read: " + str(x))
x +=1
print("MyDoubleUINT ("+MyDoubleUINT+") written: " + str(x))
wint(MyDoubleUINT, x, "u", 2)

#read/write signed Double INT
MyDoubleSINT = "d425"
x=rint(MyDoubleSINT,"s")
print("MyDoubleSINT ("+MyDoubleSINT+") read: " + str(x))
x +=1
print("MyDoubleSINT ("+MyDoubleSINT+") written: " + str(x))
wint(MyDoubleSINT, x,"s",2)

#read/write UNsigned Long INT
MyLongUINT = "d427"
x=rint(MyLongUINT)
print("MyLongUINT ("+MyLongUINT+") read: " + str(x))
x +=1
print("MyLongUINT ("+MyLongUINT+") written: " + str(x))
wint(MyLongUINT, x, "u", 4)

#read/write signed Long INT
MyLongSINT = "d431"
x=rint(MyLongSINT,"s")
print("MyLongSINT ("+MyLongSINT+") read: " + str(x))
x +=1
print("MyLongSINT ("+MyLongSINT+") written: " + str(x))
wint(MyLongSINT, x,"s",4)


myplc_memD.writeOutputValues()

t1 = int(round(omrblend2.time.time() * 1000))
tel = str(t1-t0)
print("time elapsed: " + tel + "mS")

and it outputs this:

Code:
D:\Python34\python.exe "D:/Users/chuck/My Documents/ANIMATION PROJECT/omron integrate/HMI test game/working as of 3.2.15/scratch3.py"
MyBitX (d437.1) read: 1
MyBitX (d437.1), MyBitY (D437.5), MyBitZ (D438.5) written: 0
MyFloat (d435) read: 16.0
MyFloat (d435) written: 17.0
MySingleUBCD (d400) read: 34
MySingleUBCD (d400) written: 35
MySingleBSBCD (d401) read: 34
MySingleBSBCD (d401) written: 35
MySingleDSBCD (d402) read: 34
MySingleDSBCD (d402) written: 35
MyDoubleUBCD (d403) read: 34
MyDoubleUBCD (d403) written: 35
MyDoubleBSBCD (d405) read: 34
MyDoubleBSBCD (d405) written: 35
MyDoubleDSBCD (d407) read: 34
MyDoubleDSBCD (d407) written: 35
MyLongUBCD (d409) read: 32
MyLongUBCD (d409) written: 33
MyLongBSBCD (d413) read: 32
MyLongBSBCD (d413) written: 33
MyLongDSBCD (d417) read: 32
MyLongDSBCD (d417) written: 33
MySingleUINT (d421) read: 24
MySingleUINT (d421) written: 25
MySingleSINT (d422) read: 23
MySingleSINT (d422) written: 24
MyDoubleUINT (d423) read: 22
MyDoubleUINT (d423) written: 23
MyDoubleSINT (d425) read: 22
MyDoubleSINT (d425) written: 23
MyLongUINT (d427) read: 19
MyLongUINT (d427) written: 20
MyLongSINT (d431) read: 19
MyLongSINT (d431) written: 20
Output string written: b'D400',[53, 53, 53, 53, 0, 53, 0, 53, 0, 51, 0, 0, 0, 51, 0, 0, 0, 51, 0, 0, 0, 25, 24, 23, 0, 23, 0, 20, 0, 0, 0, 20, 0, 0, 0, 0, 16776, 0, 0]
time elapsed: 66mS

Process finished with exit code 0
 
I am willing to share my work, but it is a work in progress and is pretty embarrassing at the moment (I'm really fumbling along - I'm not a computer programmer and this is my first experience with Python) hence why I'm not attaching it here and making it a matter of eternal online permanent record. If anyone would like to contribute or would like to obtain it for their own use, feel free to PM me and I would be happy to send it you what I have.

EDIT:

I just realized that I didn't post anything about where this project could use contribution.
It needs some love from someone who actually knows what they're doing in python.

1. I'd still MUCH rather access the Omron simulator link than use a physical PLC and be limited by network traffic/transmit times.

2. All my data conversions are done by converting UINTs to bit strings and then formatting the bit strings back to the proper format. I'm sure there's a better way.

3. It would be cool if the script could read/write bits directly instead of by modifying bits in a word.

4. From what I've read in Omron docs, I should be able to read/write up to 1900 bytes in one command frame, but for some reason I can only get 498.

5. It would be nice to be able to skip words when writing; as it stands, I have to write every word between the two words that I care about.

6. If I can't get at the simulator link, then some way of speeding up the network comms would be nice.

7. The script could stand to have some string/ASCII & hex function.

8. The script itself could be revamped and made to run faster. general optimization.

9. Maybe the interface script and the original script could be consolidated to simplify things.

10. There is no way I can find to close the connection when the Blender game is finished. So far it hasn't been a problem, but it seems like it should be closed.

11. It would be cool if I could read/write to multiple addresses in multiple memory areas (ex: H101, D450, CIO10, and W53-W86) within a single command frame instead of being limited to an array of addresses in a single memory area as I am now (D305-D415). I'm not sure if that's possible or not given the protocol.
 
Last edited:
The two Omron simulators work with each other with a few exceptions. What seems to be the issue?
 
The two Omron simulators work with each other with a few exceptions. What seems to be the issue?
Oh yes, they work just fine together. The issue is that I want to get my python program into the mix and read/write to simulated PLC with it. I want to be able to access the simulated PLC in the same way that CX-Designer accesses the simulated PLC with its simulated HMI.
 
Hi,

I've made some simulations with Blender too, but with Simatic Plcsim as virtual plc.

In my first version each object has readout the data from the plc by itself.
I've made a new concept, in which each object which has to read out data from the plc, or has to write back data has a special property. Then at the beginning there is a background job, which makes a list, reads out the values from the plc and writes it into the property, where you can do whatever you want with it.

The hardware layer which for siemens is placed in a separate dll, should be easily possible to replace by another vendor.

So you can create the 3d simulation objects independent of the plc hardware.

I've attached a schematic of my concept.

Blender-Plcsim-Neues-Konzept-Diagramm.jpg
 
Hi,

I've made some simulations with Blender too, but with Simatic Plcsim as virtual plc.

In my first version each object has readout the data from the plc by itself.
I've made a new concept, in which each object which has to read out data from the plc, or has to write back data has a special property. Then at the beginning there is a background job, which makes a list, reads out the values from the plc and writes it into the property, where you can do whatever you want with it.

The hardware layer which for siemens is placed in a separate dll, should be easily possible to replace by another vendor.

So you can create the 3d simulation objects independent of the plc hardware.

I've attached a schematic of my concept.

To make sure I got this correct.... Since you can't use Blender/Python to directly access the simulated PLC, and you can't use the proprietary Siemens Visual Studio OCX from Python, You make a program in Visual Studio employing the OCX, and this program feeds the sim data to a DLL. Then in python you write a program that accesses the DLL and feeds the data to another Python script running in Blender. Is that correct?
 
To make sure I got this correct.... Since you can't use Blender/Python to directly access the simulated PLC, and you can't use the proprietary Siemens Visual Studio OCX from Python, You make a program in Visual Studio employing the OCX, and this program feeds the sim data to a DLL. Then in python you write a program that accesses the DLL and feeds the data to another Python script running in Blender. Is that correct?

Yes.
You can use an OCX direct from python, but then you need to install the PythonWin extensions for win32com. This does only work with a separate python installation with the corresponding version to the blender version you are using. You can't use the with blender delivered python dll any more.

Encapsulating the OCX stuff in a separate C-dll makes life much easier, when you think of sharing your project with other people. It all runs out of the box without any additional installations.

Furthermore the PythonWin can't handle all variant type specialities (and the S7 OCX has some flaws too), so I had to read an integer bitwise and assemble the bits in python to an integer - not so good. This is only a problem with the S7 Prosim OCX.


If you want to do some action when the blender game is quit, you can add an object which has a keyboard sensor for the "ESC" key, and add also a "QuitGame" actuator. In the script you do what you want when the ESC is pressed, and then call the QuitGame actuator.

Also you can realise many things in the destructor, if you are using python classes instead of only functions.
 
Are you using the simulator built into CX-P, or the independent simulator application?
We have used the application version for SCADA comms simulation, so should work with your Python scripting.
 
Thank you for the information. I am going to call this issue SOLVED for now and barring any unforeseen bumps in the road, I won't need to simulate the PLC after all. Today i swapped out the CJ1M-CPU12-ETN that I was using for a CJ2M-CPU31. This allowed me to change the PLC <>HMI comms fron FINS to Ethernet/IP for improved comms time with PLC <>PC. Some minor changes to the Python script cut the new & improved comms time even more, by half. Now I'm cyclically reading & writing 498 DMs in under 20mS. Very acceptable for me, and the bonus is that with an actual PLC in the mix I will be able to utilize not only the real machine's HMI screens but also the real machine's physical operators (industrial joysticks, 30mm pushbuttons, etc) instead of cheesy PC gaming joysticks and USB keypad.
 

Similar Topics

I am trying to create an agnostic product queue builder using PLC ladder logic. I have a pallet conveyor and would like to be able to use a NO or...
Replies
18
Views
2,177
Hi all, I have been working on a tool for my company that handles a specific task our company runs into often related to PLC's. This is a tool I...
Replies
15
Views
2,854
I asked this question briefly in my previous post long post, I'm asking again here as the main point so it doesn't get buried. I am pretty new at...
Replies
3
Views
1,487
Everything worked fine until a program file was put in a box from another country, then I used it to fill in the gaps in the program, on my...
Replies
1
Views
998
Just wondering if anyone knows whose PLC this is?
Replies
40
Views
12,221
Back
Top Bottom