Float 32 bit number from 2 modbus registers !
111 views (last 30 days)
Show older comments
Hello Everyone,
I need some guidance about floating point numbers coming from modbus RTU, I'm working with RS485 serial interface.
No issues with modbus read. if i just read the values with the modbus read function, i have v1=36260 v2=17056 (??)
Code:
m = modbus('serialrtu','COM6','Timeout',5)
v1=read(m,'holdingregs',140,1,3)
v2=read(m,'holdingregs',141,1,3)
It seems that the final value is according the (IEEE 754) but is splited into 2 registers of 16bit. As i'm reading through internet, this is common in modbus protocol since is the maximum a register can hold is 16bit, so they use 2 registers with more and less significant order.
This is information from the datasheet of the metering device.
ModBUS address R/W Description Length (byte) Default value Meaning
________________________________________________________________________________________________________________
140 R VRMS ABC (MSB) [float – 32 bit] 2 0.0 Three-phase RMS voltage [Vrms] (Upper part)
141 R VRMS ABC (LSB) [float – 32 bit] 2 0.0 Three-phase RMS voltage [Vrms] (Lower part)
All values in 32bits are stored into 2 consecutive registers, for example:
VRMS A in floating point 32 bits is stored into registers 40140 and 40141, the Most significant word is the register 40140, the less significant word is the 40141.
So the 32bits value is obtained by the following relation: ???? ?=???40141+(???40140×216)
note! 40140 = read only holding register 140. [same thing in modbus language]
Abreviation:
“MS” = Most significant
“LS” = Less significant
“MSB” = Most significant Byte
“LSB” = Less significant Byte
“MSW” = Most significant Word (16 bits)
“LSW” = Less significant Word (16 bits)
“R” = Read only register
“RW” = Read and write register
“Unsigned 16 bits” = Unsigned 16 bits register
“Signed 16 bits” = 16 bits register with sign
“Float 32 bits” = Floating point single precision 32 bits (IEEE 754) register
“0x” = Hexadecimal Value
if i just read the values with the modbus read function, i have v1=36260 v2=17056 (??)
Final comment is that i used for test a modbus poll app https://www.modbustools.com/modbus_poll.html and it represents correctly the value if i change the view settings to Float Inverse - Description: Use this command to display data in floating point format. 2 Registers are used. Hi and Lo registers are swapped. IEEE 754 specification is used. This is representing the value correctly !!
Question:
How to get the correct value in matlab as a double numeric value with some decimals? For example 238.34985
0 Comments
Answers (2)
Steven Lord
on 24 Feb 2019
What is the class of v1 and v2 in your code above?
If they're 16-bit or 32-bit integers, take a look at the typecast and swapbytes functions.
lagmesh gavali
on 12 Jun 2023
I got output for energy meter L&T WL4410
Below is code of esp8266 nodemcu
In datasheet they mentioned addres is like 40101 to 40501
i have used MAX485 for communication with energymeter WL4410 with Node mcu ESP8266
//////////////////////////////////////////////////////////////////////////////////////////////
#include <ModbusMaster.h>
#include <Wire.h>
#define MAX485_DE 16
#define MAX485_RE_NEG 5
float gg[30];
char pub_str[100];
ModbusMaster node;
float frequency;
void preTransmission()
{
digitalWrite(MAX485_RE_NEG, 1);
digitalWrite(MAX485_DE, 1);
}
void postTransmission()
{
digitalWrite(MAX485_RE_NEG, 0);
digitalWrite(MAX485_DE, 0);
}
void setup()
{
pinMode(MAX485_RE_NEG, OUTPUT);
pinMode(MAX485_DE, OUTPUT);
digitalWrite(MAX485_RE_NEG, 0);
digitalWrite(MAX485_DE, 0);
Serial.begin(9600);
node.begin(23, Serial);
node.preTransmission(preTransmission);
node.postTransmission(postTransmission);
}
void loop()
{
uint8_t result;
uint16_t res2;
delay(3000);
result = node.readHoldingRegisters(152, 26);
delay(1000);
if (result == node.ku8MBSuccess)
{
for (int i = 1; i <= 26; i += 2)
{
uint16_t msw = node.getResponseBuffer(i);
uint16_t lsw = node.getResponseBuffer(i + 1);
uint32_t combinedValue = ((uint32_t)msw << 16) | lsw;
float floatValue;
memcpy(&floatValue, &combinedValue, sizeof(float));
gg[i / 2] = floatValue;
delay(300);
Serial.println("okokoko");
}
}
Serial.println(gg[0]);
Serial.println(gg[1]);
Serial.println(gg[2]);
Serial.println(gg[3]);
Serial.println(gg[4]);
Serial.println(gg[5]);
Serial.println(gg[6]);
Serial.println(gg[7]);
Serial.println(gg[8]);
Serial.println(gg[9]);
Serial.println(gg[10]);
Serial.println(gg[11]);
Serial.println(gg[12]);
Serial.println(gg[13]);
Serial.println(gg[14]);
Serial.println(gg[15]);
}
0 Comments
See Also
Categories
Find more on Modbus Communication in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!