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 :
ReadHoldingRegisters(byte slaveAddress, ushort StartAddress, ushort numberOfPoints)
with numberOfPoints = 2
. 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);
}
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 :
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.
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 ?
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.