Read a Siemens PLC s7 String in C# with S7netplus
Asked Answered
J

2

6

I have trouble to read data in DB of a Siemens PLC S7 1500 using S7netplus.

The situation:

  • I have a C# application running.
  • I connect on the PLC very well.
  • I can read data such as Boolean, UInt, UShot, Bytes

But I don't know how to read String data (see the image below)

PLC Datas

To read the other datas like Boolean I use this call:

plc.Read("DB105.DBX0.0")

I understood that this read in the Datablock 105 (DB105) with a datatype Boolean (DBX) at the offset 0.0 I would like to apply the same type of reading for the string. So I Tried "DB105.DBB10.0" in my example. But it return a value "40" in Byte type (and i should have something else)

I saw that there is another reading method

plc.ReadBytes(DataType DB, int DBNumber, int StartByteArray, int lengthToRead)

But I have difficulties to see how to apply it to my example (I know that I have to convert it to string after).

TO resume: - Is there a simple way with a string like "DB105.DBX0.0" to read string data in a Siemens PLC? - If not how to use the ReadBytes function in my example?

Thanks for your help

Johnsonian answered 2/10, 2019 at 18:47 Comment(0)
J
4

I managed to read my string value by the ReadBytes method. In my example I needed to pass values like this:

plc.Read(DataType.DataBlock, 105, 12, VarType.String, 40);

Why 12? Because the 2 first octets of a byte string are for the length. So 10 to 12 return a value as 40 which is the length.

I have override the read method to accept the 'easy string' call like this:

    public T Read<T>(object pValue)
            {
                var splitValue = pValue.ToString().Split('.');
                //check if it is a string template (3 separation ., 2 if not)
                if (splitValue.Count() > 3 && splitValue[1].Substring(2, 1) == "S")
                {
                    DataType dType;

                    //If we have to read string in other dataType need development to make here.
                    if (splitValue[0].Substring(0, 2) == "DB")
                        dType = DataType.DataBlock;
                    else
                        throw new Exception("Data Type not supported for string value yet.");

                    int length = Convert.ToInt32(splitValue[3]);
                    int start = Convert.ToInt32(splitValue[1].Substring(3, splitValue[1].Length - 3));
                    int MemoryNumber = Convert.ToInt32(splitValue[0].Substring(2, splitValue[0].Length - 2));

                    // the 2 first bits are for the length of the string. So we have to pass it
                    int startString = start + 2;
                    var value = ReadFull(dType, MemoryNumber, startString, VarType.String, length);
                    return (T)value;
                }
                else
                {
                    var value = plc.Read(pValue.ToString());

                    //Cast with good format.
                    return (T)value;
                }
}

So now I can call my read function like this: with basic existing call:

  • var element = mPlc.Read<bool>("DB10.DBX1.4").ToString(); => read in Datablock 10 a boolean value on the byte 1 and octet 4
  • var element = mPlc.Read<uint>("DB10.DBD4.0").ToString(); => read in datablock 10 a int value on the byte 4 and octet 0

with the overrided call for the string:

  • var element = mPlc.Read<string>("DB105.DBS10.0.40").ToString() => read in the datablock 105 a string value on the byte 10 and octet 0 with a length of 40

Hope this could help for anyone else :)

Johnsonian answered 3/10, 2019 at 15:59 Comment(0)
J
1

I did it slightly simpler; I ignore the first byte, and then read the second byte to give me the string length. I then use this to give me the length of the bytes for the string. For example the PLC gave me DB offset of 288 for the start of the string. This is using the S7Plus NuGet, with a DB address of 666.

Note, requesting strings seriously slows down the communication, so probably better to only request them when there is a new value.

     TempStringLength(0) = PLC.Read(DataType.DataBlock, 666, 289, VarType.Byte, 1) 'Length of String.'
     TempStringArray(0) = PLC.Read(DataType.DataBlock, 666, 290, VarType.String, TempStringLength(0))'Actual String.'

Jumpoff answered 21/3, 2022 at 0:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.