libplctag testing without hardware.

582 views
Skip to first unread message

GBT

unread,
Sep 16, 2018, 8:49:02 AM9/16/18
to libplctag
My PLC hardware will not be available for sometime and once the system is delivered I will no longer have access to PLC hardware.  Is there a way I can test my program without hardware?  I looked for free PLC emulators or simulators without success.  I have also looked at the system protocol but I can't find an example using it.  Any help would be appreciated.

Kyle

unread,
Sep 16, 2018, 12:39:13 PM9/16/18
to libplctag
There are software emulators but they are definitely not free.

I am in the process of writing a small, very simple, emulator so that I can test the PLC library code without access to a PLC.  

You can find it on the 1.5_patch branch, but it is Linux-only and very, very rudimentary.  All it does is handle DINT arrays right now and they are hard coded.    Look in the src/tests/lgx_sim directory.   I have not made much of an attempt to make it cross platform or anything other than as simple as possible.  It does not check its arguments much at all.   It is just a quick prototype.

Eventually I hope to integrate it into the library so that a tag can be either a client tag or a server tag.   But, that comes after I get multiple requests packed into a single packet.

Best,
Kyle

GBT

unread,
Sep 24, 2018, 9:44:25 AM9/24/18
to libplctag
Thanks I have downloaded the lgx_sim directory.  Do you have a small example using lgx_sim?  When I build lgx_sim I get the follow errors about _Atomic in the session.c file.

error: expected '=', ',', ';' 'asm' or '_attribute_' before 'uint32_t'

I have removed the _Atomic in both lines and lgx_sim builds fine so that is where the issue is.

Thank you so much for your help.

GBT

unread,
Sep 27, 2018, 9:12:27 AM9/27/18
to libplctag
I was able to build the emulator but removing the _Atomic the static variable definitions and using __sync_add_and_fetch calls when using them.  Does anyone see issues with this solution?

Could someone give me a valid TAG_PATH define using the emulator?

#define TAG_PATH "protocol=ab_eip&gateway=10.206.1.28&cpu=PLC5&elem_size=4&elem_count=5&name=F8:10&debug=1"

Kyle

unread,
Sep 27, 2018, 10:59:46 PM9/27/18
to libplctag
The simulator code is written in C11, so the _Atomic is from that.  The replacements you did should work (I assume that this is GCC or Clang, but not a new version?).  What OS and compiler are you using?

The command I used for testing the simulator was this:

./tag_rw -t sint32 -p 'protocol=ab-eip&gateway=127.0.0.1&path=1,0&cpu=lgx&use_connected_msg=1&elem_size=4&elem_count=10&name=TestDINTArray&debug=4'

Notice that the cpu type is Logix, not PLC5.   There is a path (though it is only used to differentiate different connections in the simulator).   You can set the debug level lower if you want less output.

The tag used here, TestDINTArray, is defined in tags.c:

    tags[0].name = "TestDINTArray";
    tags[0].data_type[0] = 0xc4;
    tags[0].data_type[1] = 0x00;
    tags[0].elem_count = 10;
    tags[0].elem_size = 4;
    tags[0].data = (uint8_t *)calloc(tags[0].elem_size, tags[0].elem_count);


This defines the name of the tag, the type, 0xc4, 0x00, the element count (10) and size (4) in bytes of each element.

I hope that helps.

Again, a warning that the simulator is very, very basic.  I am sure you will find bugs!  Please let me know if you do.

Eventually I want to turn this into a tag type so that you can use the library to read tags from PLCs and to serve tags.

I have not tried to read or write a tag in the simulator from a real PLC.  

Best,
Kyle

GBT

unread,
Sep 28, 2018, 10:41:31 AM9/28/18
to libplctag
I am using Fedora12 64bit.  We have a complicated build environment which I am not to familiar with so I was happy I could built it without changing our scripts.  


I am new to PLCs and not too Linux savvy.  So here are the steps I am doing to try and run a test.

I start up lgx_sim in one command window.

I start up  tag_rw in a new command window

./tag_rw -t sint32 -p 'protocol=ab-eip&gateway=<my Linux's IP address>&path=1,0&cpu=lgx&use_connected_msg=1&elem_size=4&elem_count=10&name=TestDINTArray&debug=4'

[adi@veiltail Debug]$ ./run.sh
Arg[0]=./tag_rw
Arg[1]=-t
Arg[2]=sint32
Arg[3]=-p
Arg[4]=protocol=ab-eip&gateway=192.168.3.152&path=1,0&cpu=lgx&use_connected_msg=1&elem_size=4&elem_count=10&name=TestDINTArray&debug=4
thread(0002) 2018-08-28 10:35:14.511 INFO find_tag_create_func:88 Matched protocol=ab-eip
thread(0001) 2018-08-28 10:35:14.511 DETAIL request_handler_func:1011 Starting.
thread(0002) 2018-08-28 10:35:14.511 INFO ab_tag_create:192 Starting.
thread(0002) 2018-08-28 10:35:14.511 INFO rc_alloc_impl:99 Starting, called from ab_tag_create:199
thread(0002) 2018-08-28 10:35:14.511 INFO rc_alloc_impl:131 Done
thread(0002) 2018-08-28 10:35:14.511 DETAIL rc_alloc_impl:136 Returning memory pointer 0x111ba30
thread(0002) 2018-08-28 10:35:14.511 DETAIL ab_tag_create:207 tag=0x111ba30
thread(0002) 2018-08-28 10:35:14.511 INFO match_dhp_node:112 Bad syntax in DH+ route.  Expected DH+ channel identifier (A/2 or B/3)
thread(0002) 2018-08-28 10:35:14.511 DETAIL cip_encode_path:212 Found regular routing. Conn path length=1
thread(0002) 2018-08-28 10:35:14.511 INFO match_dhp_node:112 Bad syntax in DH+ route.  Expected DH+ channel identifier (A/2 or B/3)
thread(0002) 2018-08-28 10:35:14.511 DETAIL cip_encode_path:212 Found regular routing. Conn path length=2
thread(0002) 2018-08-28 10:35:14.511 DETAIL cip_encode_path:300 ioi_size before 6
thread(0002) 2018-08-28 10:35:14.511 DETAIL session_find_or_create:254 Starting
thread(0002) 2018-08-28 10:35:14.511 DETAIL session_find_or_create:266 Creating new session.
thread(0002) 2018-08-28 10:35:14.511 INFO session_create_unsafe:455 Starting
thread(0002) 2018-08-28 10:35:14.511 DETAIL session_create_unsafe:457 Warning: not using passed port 44818
thread(0002) 2018-08-28 10:35:14.511 INFO rc_alloc_impl:99 Starting, called from session_create_unsafe:459
thread(0002) 2018-08-28 10:35:14.511 INFO rc_alloc_impl:131 Done
thread(0002) 2018-08-28 10:35:14.511 DETAIL rc_alloc_impl:136 Returning memory pointer 0x111bd70
thread(0002) 2018-08-28 10:35:14.511 DETAIL add_session_unsafe:309 Starting
thread(0002) 2018-08-28 10:35:14.511 DETAIL add_session_unsafe:324 Done
thread(0002) 2018-08-28 10:35:14.511 INFO session_create_unsafe:515 Done
thread(0002) 2018-08-28 10:35:14.511 INFO session_init:531 Starting.
thread(0002) 2018-08-28 10:35:14.511 INFO session_connect:561 Starting.
thread(0002) 2018-08-28 10:35:14.511 DETAIL socket_create:714 Starting.
thread(0002) 2018-08-28 10:35:14.511 DETAIL socket_create:728 Done.
thread(0002) 2018-08-28 10:35:14.511 DETAIL socket_connect_tcp:747 Starting.
thread(0002) 2018-08-28 10:35:14.511 DETAIL socket_connect_tcp:796 Found numeric IP address: 192.168.4.157
thread(0002) 2018-08-28 10:35:14.511 DETAIL socket_connect_tcp:844 Attempting to connect to 192.168.4.157
thread(0002) 2018-08-28 10:35:14.511 DETAIL socket_connect_tcp:852 Attempt to connect to 192.168.4.157 failed, errno: 111
thread(0002) 2018-08-28 10:35:14.511 ERROR socket_connect_tcp:859 Unable to connect to any gateway host IP address!
thread(0002) 2018-08-28 10:35:14.511 WARN session_connect:574 Unable to connect socket for session!
thread(0002) 2018-08-28 10:35:14.511 WARN session_init:535 session connect failed!
thread(0002) 2018-08-28 10:35:14.511 DETAIL rc_dec_impl:274 Starting, called from session_find_or_create:291 for 0x111bd70
thread(0002) 2018-08-28 10:35:14.511 DETAIL rc_dec_impl:300 Ref count is 0 for 0x111bd70.
thread(0002) 2018-08-28 10:35:14.511 DETAIL rc_dec_impl:304 Calling cleanup functions due to call at session_find_or_create:291 for 0x111bd70.
thread(0002) 2018-08-28 10:35:14.511 INFO refcount_cleanup:317 Starting
thread(0002) 2018-08-28 10:35:14.511 INFO session_destroy:592 Starting.
thread(0002) 2018-08-28 10:35:14.511 DETAIL remove_session_unsafe:348 Starting
thread(0002) 2018-08-28 10:35:14.511 DETAIL remove_session_unsafe:377 Done
thread(0002) 2018-08-28 10:35:14.511 INFO session_destroy:651 Done.
thread(0002) 2018-08-28 10:35:14.511 INFO refcount_cleanup:342 Done.
thread(0002) 2018-08-28 10:35:14.511 DETAIL session_find_or_create:302 Done
thread(0002) 2018-08-28 10:35:14.511 INFO ab_tag_create:366 Unable to create session!
thread(0002) 2018-08-28 10:35:14.511 INFO plc_tag_create:311 Returning mapped tag 0x4001
INFO: Got tag 0x4001
INFO: tag status -10
ERROR: tag creation error, tag status: PLCTAG_ERR_CREATE
thread(0002) 2018-08-28 10:35:14.511 INFO plc_tag_destroy:518 Starting.
thread(0002) 2018-08-28 10:35:14.511 INFO plc_tag_destroy_mapped:465 Starting.
thread(0002) 2018-08-28 10:35:14.511 DETAIL plc_tag_destroy_mapped:484 Releasing tag mapping.
thread(0002) 2018-08-28 10:35:14.511 DETAIL release_tag_to_id_mapping:1649 Starting
thread(0002) 2018-08-28 10:35:14.511 DETAIL release_tag_to_id_mapping:1668 Releasing tag 0x111ba30(16385) at location 1
thread(0002) 2018-08-28 10:35:14.511 DETAIL release_tag_to_id_mapping:1672 Done.
thread(0002) 2018-08-28 10:35:14.511 INFO plc_tag_abort_mapped:403 Starting.
thread(0002) 2018-08-28 10:35:14.511 INFO plc_tag_abort_mapped:416 Done.
thread(0002) 2018-08-28 10:35:14.511 DETAIL rc_dec_impl:274 Starting, called from plc_tag_destroy_mapped:506 for 0x111ba30
thread(0002) 2018-08-28 10:35:14.511 DETAIL rc_dec_impl:300 Ref count is 0 for 0x111ba30.
thread(0002) 2018-08-28 10:35:14.511 DETAIL rc_dec_impl:304 Calling cleanup functions due to call at plc_tag_destroy_mapped:506 for 0x111ba30.
thread(0002) 2018-08-28 10:35:14.511 INFO refcount_cleanup:317 Starting
thread(0002) 2018-08-28 10:35:14.511 INFO ab_tag_destroy:518 Starting.
thread(0002) 2018-08-28 10:35:14.511 DETAIL ab_tag_destroy:545 Getting ready to release tag session (nil)
thread(0002) 2018-08-28 10:35:14.511 WARN ab_tag_destroy:551 No session pointer!
thread(0002) 2018-08-28 10:35:14.511 INFO ab_tag_destroy:574 Finished releasing all tag resources.
thread(0002) 2018-08-28 10:35:14.511 INFO ab_tag_destroy:576 done
thread(0002) 2018-08-28 10:35:14.511 INFO refcount_cleanup:342 Done.
thread(0002) 2018-08-28 10:35:14.511 INFO plc_tag_destroy_mapped:508 Done.
thread(0002) 2018-08-28 10:35:14.511 INFO plc_tag_destroy:531 Done.
thread(0002) 2018-08-28 10:35:14.511 INFO ab_teardown:163 Releasing global AB protocol resources.
thread(0002) 2018-08-28 10:35:14.511 INFO ab_teardown:165 Terminating IO thread.
thread(0002) 2018-08-28 10:35:14.511 DETAIL thread_join:598 Starting.
thread(0002) 2018-08-28 10:35:14.512 DETAIL thread_join:610 Done.
thread(0002) 2018-08-28 10:35:14.512 DETAIL thread_destroy:639 Starting.
thread(0002) 2018-08-28 10:35:14.512 DETAIL thread_destroy:650 Done.
thread(0002) 2018-08-28 10:35:14.512 INFO ab_teardown:173 Freeing global session mutex.
thread(0002) 2018-08-28 10:35:14.512 INFO ab_teardown:177 Removing the read group vector.
thread(0002) 2018-08-28 10:35:14.512 INFO ab_teardown:180 Done.
thread(0002) 2018-08-28 10:35:14.512 INFO lib_teardown:118 Tearing down library.
thread(0002) 2018-08-28 10:35:14.513 INFO lib_teardown:129 Destroying global library mutex.
thread(0002) 2018-08-28 10:35:14.513 INFO lib_teardown:135 Done.

Kyle

unread,
Sep 29, 2018, 4:11:45 PM9/29/18
to libplctag
It looks like the error below is the problem.   What this boils down to is this defintion for that errno value (at least for Linux):

#define ECONNREFUSED    111     /* Connection refused */


So, something is refusing the connection.   

Ah, I am doing it wrong :-(  The code was not correctly binding to all network interfaces.   For some reason it only worked for localhost.

OK, I fixed the code and tested it remotely.  Apparently I had never checked the simulator remotely!

Please pull the latest 1.5_patch branch and try that.  Sorry about that!

GBT

unread,
Oct 1, 2018, 7:35:14 AM10/1/18
to libplctag
Kyle,

Thanks! I can now read and write a tag using  the tag_rw and lgx_sim.  It does seem like every call to tag_rw for a read ends with:

read() failed!
client handler thread terminating

tag_rw call
./tag_rw -t sint32 -p 'protocol=ab-eip&gateway=192.168.4.157&path=1,0&cpu=lgx&use_connected_msg=1&elem_size=4&elem_count=10&name=TestDINTArray&debug=1'

GBT

unread,
Oct 1, 2018, 8:37:09 AM10/1/18
to libplctag
I think I figured out why I am getting the read error.  I am getting an error 104 unable to read socket.  My guess is tag_rw is closing the socket then shortly after that lgx_sim tries to read the closed socket.

Kyle

unread,
Oct 1, 2018, 7:48:40 PM10/1/18
to libplctag
Yes, that is probably it.  There is almost no error checking the simulator.  A closed socket would cause a read error when the simulator tries.

Best,
Kyle

ori...@gmail.com

unread,
Dec 7, 2020, 6:42:24 AM12/7/20
to libplctag
Hi, I saw that you write about software emulators that are not free. 
 maybe do you have recommendation about emulator like that?
Thank you

ב-יום שלישי, 2 באוקטובר 2018 בשעה 02:48:40 UTC+3, Kyle כתב/ה:

Kyle

unread,
Dec 7, 2020, 9:57:27 AM12/7/20
to libplctag
Hi, thanks for reaching out. 

The code includes a small tag simulator (just tags) in /src/tests/ab_server.   You can set up a few tag types.  If you run it without any arguments it will output some help text.

It is only used for the CI tests currently. 

It may be a place to start if you do not have any hardware yet.  It will simulate Logix, Micro800 and Omron.   There is not much error checking though :-(

I hope that helps.

Best,
Kyle

ori...@gmail.com

unread,
Dec 20, 2020, 9:47:17 AM12/20/20
to libplctag
do you have any recommendation about paid simulator that I can connect to with Ip?


ב-יום שני, 7 בדצמבר 2020 בשעה 16:57:27 UTC+2, Kyle כתב/ה:

Kyle

unread,
Dec 21, 2020, 12:04:57 AM12/21/20
to libplctag
Hi,

Thanks for using the library.

The SoftLogix emulator may work.  I know that some people were trying it at one point.  There are two emulators from Allen-Bradley.

Alternatively, there are some cheaper real PLCs that will speak some dialect of AB's protocol.   Omron and Koyo both appear to have models that will support the protocol.   A user of the library contributed code to support Omron NJ/NX PLCs using a dialect of AB's protocol.  That might be cheaper than buying a full emulator from AB!

If you are not picky, there is used equipment on eBay.

It looks like SoftLogix is going to be sunset at some point.   They have stopped updating it.   It is still available:


I have not used it but the documentation claims that you can add a virtual Ethernet/IP module to it so I think you should be able to make it function as if it was a full PLC.

I hope that helps!

Best,
Kyle
Reply all
Reply to author
Forward
0 new messages