Omron NJ and NX write strings

443 views
Skip to first unread message

Attila Bogadi

unread,
Aug 31, 2023, 7:35:56 AM8/31/23
to libplctag
Hi,
First of all thank you for all the hard work!
I am testing reading and writing strings with the .NET wrapper and while reading is working with no problems (can read strings up to 255 chars), I have  some problems writing them.

As far as I can tell the underlying code returns an enumeration: ErrorBadConfig.

Not quite sure where to look and how to resolve.
Any help would appreciated!

A

Jürgen Walter

unread,
Aug 31, 2023, 8:12:10 AM8/31/23
to libplctag
Hi Attila,

(sry, not related to your problem)

but could you tell me what names your are using when reading a tag? I am having problems reading any tags from OMRON PLC at all.

If you could share (maybe a few) tags names and how you read them in libplctag? like name (including hierarchy/path in OMRON PLC project) and what (full) tag name you use in libplctag?

Many thanks in advance!!

Jürgen
> --
> You received this message because you are subscribed to the Google Groups "libplctag" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to libplctag+...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/libplctag/4b1653b2-bfa3-4b2b-b19e-84821618098an%40googlegroups.com.

Attila Bogadi

unread,
Aug 31, 2023, 8:51:45 AM8/31/23
to libplctag
Helge!
Thanks for the quick reply .
Network Publish attribute is set to "Input", which works with any other type of variable, can read and write too. It is just the strings that do not seem to write.

Jurgen!

A simple example I am using is as follows:
            var stringTag = new Tag<StringPlcMapper, string>( ) // should match the data type you trying to access
            {
                Name = "testString",
                Gateway = "192.168.250.1",
                Path = "18,192.168.250.1",  // 18 means you are trying to access on ethernet port 1, for ethernet port 2 use 19
                Protocol = Protocol.ab_eip,
                PlcType = PlcType.Omron,
                Timeout = TimeSpan.FromMilliseconds(5000),             

            };

            stringTag.Read(  );  // initializes connection and reads the variable
            Debug.WriteLine( stringTag.Value.ToString());
            stringTag.Value = "42";
            stringTag.Write(); // should write the value to the plc

Where "testString" is a global variable of 255 chars and the Network Publish attribute is set to "Input".
If you were using a structure variable  the Name would be "yourstructure.yourSubStructure.member

You could also download the example project from github, which is full of examples.
Cheers,
Attila

Attila Bogadi

unread,
Aug 31, 2023, 11:15:43 AM8/31/23
to libplctag

Ok, in addition to the above I discovered that if the string to be sent is equal or less then 7 characters it throws an exception with  ErrorBadConfig and if the string has more than 7 characters it throws an exception with ErrorToLarge message.

Any ideas?

tim...@gmail.com

unread,
Aug 31, 2023, 7:45:12 PM8/31/23
to libplctag
You may need to do more configuration relating to strings: https://github.com/libplctag/libplctag/wiki/API#handling-strings
I'm not sure how to configure for Omron string access, and it looks like there are a few open issues on the github that relate to this: https://github.com/search?q=org%3Alibplctag+omron+string&type=issues

There is currently a shortcoming in the Mapper system that doesn't allow mappers to configure these properties but you can still access them with the non-generic Tag.
There is an outstanding pull request to allow this to happen: https://github.com/libplctag/libplctag.NET/issues/211

Attila Bogadi

unread,
Sep 4, 2023, 12:26:40 PM9/4/23
to libplctag
Hi Tim,

Thanks for the pointers.

Anyone should have similar problems, there is a snippet below showing how I ended up using it. The code is probably not perfect but works, just remember that I am coming from a plc world. 
Also, if there is a way I can help the development please let me know, I have constant access to Omron PLCs.

 var tagHandle =
     plctag.plc_tag_create("protocol=ab-eip&gateway=192.168.250.1&path=18,192.168.250.1&plc=omron-njnx&name=testString", 500);

 // read
 plctag.plc_tag_read(tagHandle, 500);
 int length = plctag.plc_tag_get_string_length(tagHandle, 0);
 byte[ ] rBytes = new byte[ length+2 ];
 plctag.plc_tag_get_raw_bytes(tagHandle, 0, rBytes, length+2);
 string plcString = Encoding.ASCII.GetString(rBytes.TakeLast(length).ToArray(  ));
 Debug.WriteLine(plcString);

 // write
 string myText =
     "This is a 255 character long string xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxT";
 List<byte> bytes = Encoding.ASCII.GetBytes(myText).ToList( );
 int charCount = (int)Math.Round((double)(bytes.Count / 2), MidpointRounding.AwayFromZero) * 2;
 byte[ ] charCountAry = BitConverter.GetBytes(charCount);
 bytes.Insert(0, charCountAry[ 0 ]);
 bytes.Insert(1, charCountAry[ 1 ]);
 plctag.plc_tag_set_size(tagHandle, charCount + 2);
 int intSizeStatus = plctag.plc_tag_set_raw_bytes(tagHandle, 0, bytes.ToArray( ), charCount + 2);
 libplctag.Status sizeStatus = (libplctag.Status)Enum.ToObject(typeof(libplctag.Status), intSizeStatus);
 int intWriteStatus = plctag.plc_tag_write(tagHandle, 500);
 libplctag.Status writeStatus = (libplctag.Status)Enum.ToObject(typeof(libplctag.Status), intWriteStatus);

Kyle

unread,
Sep 6, 2023, 10:37:56 AM9/6/23
to libplctag
Strings are extremely annoying because they really are all some form of UDT but different PLCs use different definitions (sometimes many within the same PLC!).   I added a bunch of functions to libplctag (the C DLL) to try to support these as well as some defaults for common PLC types.

There are several string attributes that are used with these functions.   The function plc_tag_get_string_length() uses those to calculate the length of a string.   If the definitions/defaults are wrong, then the result coming from that function will be wrong.

Almost all strings in PLCs fall into two main categories:
  • strings with a leading count word.   This can be one byte, two bytes or four bytes.   A ControlLogix tag of the STRING type uses a 4 byte (DINT) count word.  A PLC/5, SLC, or Micrologix uses a count string of 2 bytes.
  • strings with a terminal sentinel value.  These are C-style strings and usually end with a NUL (zero value) byte.
Most PLC strings seem to fall in the first category.

If you don't know what the PLC does, try to read a tag that is just a single string.  Read the string tag, then dump out the raw bytes.  You can usually see the size of the count word and string data from that.  Then use that to set up the string attributes.  

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