libplctag / libplctag.NET

A .NET wrapper for libplctag.

Home Page:https://libplctag.github.io/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Writing sting value from C# to AB compactlogix string_50 tag.

kaptindan opened this issue · comments

I am scratching my head. I can not write to a plc tag. Allen Bradley control logics. I have a string and the plc type is string. I've tried many different data types.

var myTag13 = new Tag<StringPlcMapper, string>()
{
Name = "Scanner_P502_3A_WCS.CMD",
//Name = "Program:P502.Scanner_WCS.TRIG",
Gateway = "192.168.11.1",
Path = "1,0",
PlcType = PlcType.ControlLogix,
Protocol = Protocol.ab_eip,
Timeout = TimeSpan.FromSeconds(5)
};
myTag13.Initialize();
myTag13.Value = txtScannerWCSTrig.Text;
myTag13.Write();

The string in txtScannerWCSTrig is 31200081420000437705

PLC tag is a STRING_50 its a sint 50 characters

The STRING_50 type is probably a struct type, not a SINT array.

Viewing the type in RsLogix is how you can get an understanding of that type.

If you view the raw buffer it can also give you a better idea of how the STRING_50 is encoded in memory:

using libplctag;

var myTag = new Tag()   // This is what I meant by non-generic Tag in https://github.com/libplctag/libplctag/issues/418#issuecomment-1448780436
{
    Name = "Scanner_P502_3A_WCS.CMD",
    Gateway = "192.168.11.1",
    Path = "1,0",
    PlcType = PlcType.ControlLogix,
    Protocol = Protocol.ab_eip,
    Timeout = TimeSpan.FromSeconds(5),
    ElementSize = 50    // Are you sure is a SINT array of length 50? What about a character count field, what about null-termination bytes??
};
myTag.Read();

var myTagValue = myTag.GetBuffer();
var myTagValueAsHexString = BitConverter.ToString(myTagValue);

Console.WriteLine(myTagValueAsHexString);

Your comment from the other issue shows that you're already expecting something like "31200081420000437705", so if we plug the buffer into a hexadecimal to ASCII converter we might see something interesting:
18-00-00-00-33-31-32-30-30-30-38-31-34-32-30-30-30-30-34-33-37-37-30-35-3A-34-32-38-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 -> "�31200081420000437705:428 "

Its already starting to look familiar.

Given that we know what the start of the string should be, we can play around with the buffer to see which parts of it match up with the expected string. I found that this "33-31-32-30-30-30-38-31-34-32-30-30-30-30-34-33-37-37-30-35" perfectly matches up with the string you expect.

So, what does the rest of the buffer do?
The first 4 bytes (18-00-00-00) are something else.
The 20 bytes (33-31-32-30-30-30-38-31-34-32-30-30-30-30-34-33-37-37-30-35) from your string.
There are another 4 bytes which look like ASCII (3A-34-32-38) which look like ":428" - are these part of the string????
The last 28 bytes (00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00) are something else.

If we interpret 18-00-00-00 as a 4 byte unsigned integer, we get the number "24", which happens to be how many ASCII characters there are - so probably this is some sort of character count.

So now we know that we have a 4 byte number that represents the character count, and we also know that the STRING_50 type can have up to 50 characters. That leaves the last 2 bytes for something else.

If we look at the API documentation we find that we can already fill in the values for a lot of the configuration.

  • str_count_word_bytes=4 -> we know that the character count is 4 bytes
  • str_is_byte_swapped=0 -> the string you expect seems to appear in the same order that the ASCII encoded bytes do, so it is not swapped
  • str_is_counted=1 -> yes, the first 4 bytes
  • str_is_fixed_length=1 -> yes, the string is a fixed size of 50
  • str_is_zero_terminated -- ???
  • str_max_capacity=50 -> the string can have 50 bytes of characters
  • str_pad_bytes -- ???
  • str_total_length -- ???

The last few paragraphs from the libplctag Strings and String Handling documentation should provide enough information to complete the other 3 attributes.


The STRING_50 type is a UDT that the PLC programmer has created, which is why libplctag.NET does not provide a mapper for it.

In one example you are using var sequenceArray = new Tag<SequencePlcMapper, Sequence[]>() To get the the UDT and write the array back out
for (int ii = 0; ii < 8; ii++)
sequenceArray.Value[ii].Command = ii * 2;

        sequenceArray.Write(); 

So when I try to use SequencePlcMapper Its not an available option.

https://github.com/libplctag/libplctag.NET/blob/master/src/Examples/CSharp%20DotNetCore/SequencePlcMapper.cs

I trust you're looking to use this information to configure the string tag?

@kaptindan - seems like you're onto new problems now, has the initial query about string tag writing been resolved?

I put that aside for now, I think I can write to it looping through and writing the Dint. We are considering just making the tags strings. Future project.

No probs - good luck!