Dear reader,
I am writing a C# program using the library ‘EasyModbus’ that needs to communicate with Siemens WinCC via the connection type ‘Modicon modbus’ I have written a version using the ‘float’ data type in WinCC and that works perfectly. Here my code fragment:
Method to convert ‘double’ to bytes in C#:
public static byte[] DoubleToModbusFloat(double value)
{
byte[] bytes = new byte[4];
float floatValue = (float)value;
int intValue = BitConverter.ToInt32(BitConverter.GetBytes(floatValue), 0);
bytes[0] = (byte)(intValue >> 24);
bytes[1] = (byte)(intValue >> 16);
bytes[2] = (byte)(intValue >> 8);
bytes[3] = (byte)intValue;
return bytes;
}
Call of the method and loading of the modbus registers in EasyModbus:
Bytes = PublicCode.DoubleToModbusFloat(TmpDbl);
int n = (int)ModbusStartAddress + ((i - 1) * 2);
mb.ModServer.holdingRegisters[n + 1] = (short)((Bytes[0] << 8) + Bytes[1]);
mb.ModServer.holdingRegisters[n + 2] = (short)((Bytes[2] << 8) + Bytes[3]);
So far so good – this works fine. But I also want to be able to use the ‘Double’ data type in WinCC because I sometimes need more precision than the 7 figures of the ‘float’. I thought it would simply be a case of doubling up the code so I wrote:
Method to convert ‘double’ to bytes in C#:
public static byte[] DoubleToModbusDouble(double value)
{
byte[] bytes = new byte[8];
long intValue = BitConverter.ToInt64(BitConverter.GetBytes(value), 0);
bytes[0] = (byte)((intValue >> 56) & 0xff);
bytes[1] = (byte)((intValue >> 48) & 0xff);
bytes[2] = (byte)((intValue >> 40) & 0xff);
bytes[3] = (byte)((intValue >> 32) & 0xff);
bytes[4] = (byte)((intValue >> 24) & 0xff);
bytes[5] = (byte)((intValue >> 16) & 0xff);
bytes[6] = (byte)((intValue >> 8) & 0xff);
bytes[7] = (byte)(intValue & 0xff);
return bytes;
}
Call of method and loading of the modbus registers in EasyModbus:
Bytes = PublicCode.DoubleToModbusDouble(TmpDbl);
int n = (int)ModbusStartAddress + ((i - 1) * 4);
mb.ModServer.holdingRegisters[n + 1] = (short)((Bytes[0] << 8) + Bytes[1]);
mb.ModServer.holdingRegisters[n + 2] = (short)((Bytes[2] << 8) + Bytes[3]);
mb.ModServer.holdingRegisters[n + 3] = (short)((Bytes[4] << 8) + Bytes[5]);
mb.ModServer.holdingRegisters[n + 4] = (short)((Bytes[6] << 8) + Bytes[7]);
However, this code does not work correctly. I have tried all combinations of byte and word reversal, and whatever I do WinCC either displays nonsensical values or ‘####’ showing that it cannot display the value. I have tried reading as much documentation as I can but it still looks to me as if I am doing the right thing. Also, I have downloaded a number of ‘modbus master’ code examples, and they seem to be able to read the ‘Double’ from my program without any issues. In WinCC I also see that there are two types of double – ‘Double’ and ‘+/- Double’ – I am also unsure as to why this is – there is no ‘+/- Float’ data type, which seems inconsistent to me.
I am obviously missing something, but cannot seem to discover what exactly.
I hope that someone can point me in the right direction as to what I am doing wrong.
Please see attached word file for a picture of the configuration of the connection in WinCC.
Thanks in advance for any help !,
Dave Long