Float 32 bit number from 2 modbus registers !

171 visualizaciones (últimos 30 días)
Bambos
Bambos el 24 de Feb. de 2019
Respondida: lagmesh gavali el 12 de Jun. de 2023
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

Respuestas (2)

Steven Lord
Steven Lord el 24 de Feb. de 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.
  1 comentario
Bambos
Bambos el 24 de Feb. de 2019
Current class is double - without forcing the variable type.
If i force the modbus read function with :
v1=read(m,'holdingregs',140,1,3,'uint16')
insteaf of
v1=read(m,'holdingregs',140,1,3)
is changing accordingly, but i don't see any help from that.
As i mentioned in first post, are Float32 ieee 754 standart, just splited in 2 registers with significance. Since are not clearly integers, maybe we have to take a step back and get the values to binary or hex format and reassemble again. I try a lot of functions like cast, typecast, i don't have yet any success.

Iniciar sesión para comentar.


lagmesh gavali
lagmesh gavali el 12 de Jun. de 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]);
}

Categorías

Más información sobre Modbus Communication en Help Center y File Exchange.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by