Reputation: 192
I have trouble to read data in DB of a Siemens PLC S7 1500 using S7netplus.
The situation:
But I don't know how to read String data (see the image below)
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
Upvotes: 6
Views: 10333
Reputation: 19
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.'
Upvotes: 1
Reputation: 192
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 4var element = mPlc.Read<uint>("DB10.DBD4.0").ToString();
=> read in datablock 10 a int value on the byte 4 and octet 0with 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 40Hope this could help for anyone else :)
Upvotes: 4