Dave Long

MrPLC Member
  • Content count

    1
  • Joined

  • Last visited

Posts posted by Dave Long


  1. 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

    Double trouble.docx