Search code examples
c#modbus

How should I access these (Enron Modbus) registers?


While using an OMNI Flow computer I ran into an issue I can't really wrap my head around. I'm trying to access 32 bits IEEE floating points number using NModbus.

What I do to get one number :

  1. Read 2 registers using ReadHoldingRegisters(byte slaveAddress, ushort StartAddress, ushort numberOfPoints) with numberOfPoints = 2.
  2. Convert the 2 ushorts I read into 1 float like so :
    private static float ToFloat(ushort[] data)
        {
            var bArray = new byte[4];
            BitConverter.GetBytes(data[0]).CopyTo(bArray, 2);
            BitConverter.GetBytes(data[1]).CopyTo(bArray, 0);
            return BitConverter.ToSingle(bArray, 0);
        }
  1. Use this float in my code.

I've tried this method and it seems to work for most of the data I read, but right now I'm having trouble reading points (I get unexpected values but cannot conclude on the cause) and would like to be sure that it is not due to the addressing; points are arranged like so :


addresses of data I want to read


Where one address is equivalent to 32 bits of information, whereas usually 2 different registers would be used. My device has a parameter called Modicon modbus compatible which has led me to research what kind of protocol it uses by default and it turns out it is Enron Modbus.


enter image description here


According to this bit of documentation (particularly the lower box)

The starting address of the variable still applies

Meaning that if I switch to the usual Modicon Modbus, I would access 2 registers while using only one point ? For example if I wanted to read the first two floating points, I would need to read 2 registers starting at address 8080 and then 2 more registers but starting at address 8081. When usually I would start at address 8082 for my second point.

How should I access these registers ? Also, is there an offset in the addressing even if the documentation says otherwise ? If, when using NModbus, I was to read 2 registers using the ReadMultipleRegisters method would it return the correct value ?


Solution

  • After a few tests I have noticed that I am able to read the correct value from a register by using ReadHoldingRegisters(byte slaveAddress, ushort address, ushort numberOfPoints) with numberOfPoints = 2 while I get an error if I try with numberOfPoints = 1 because my device sends back 8 bytes of data instead of 4. This is coherent with the documentation stating that

    You cannot read or write a partial variable

    And since each floating point is in the form of a 32bits register I can't read less than 2 ushorts.

    Moreover, I discovered that, for me to read a value from a specific register (be it float or boolean) I had to use an address that was decremented by 1. So for example if I wanted to read the value in register 8080, in my code I should in fact read register 8079.

    I had a feeling there was an offset in the addressing but I wasn't expecting this.