# Newbie: convert modbus float \[array\] register to float value

**URL:** <https://discourse.nodered.org/t/newbie-convert-modbus-float-array-register-to-float-value/20293>\
**Category:** General\
**Created:** [14 January 2020 04:14 UTC](https://discourse.nodered.org/t/newbie-convert-modbus-float-array-register-to-float-value/20293 "2020-01-14T04:14:29Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![PPz](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/ppz/32/15429_2.png) [@PPz](https://discourse.nodered.org/u/PPz)\
**Post date:** [14 January 2020 04:14 UTC](https://discourse.nodered.org/t/newbie-convert-modbus-float-array-register-to-float-value/20293/1 "2020-01-14T04:14:29Z")

</div>

Hi,  
I have problems to convert float and 32b (signed/unsigned) registers to obtain a result able to be sent to MQTT broker. The modbus device is a semaphore/Servelec Tbox unit. I use node-red modbustcp

Example: I have a float register with a value of **22.362** in it. I want to pass that value to my MQTT broker.  
When I debug in node-red, I obtain an array: **[16818,58720]** but I'm stuck to convert this to a readable precise value of 22.362 (22.36 will be ok)

I have no probs with int16 registers (because they are 16bits obviously but need to find a function to convert negative values to readable ones)  
I found here a function but the result seems weird (imprecise).

\*Edit: I made my test simple. That's the reason I set the value of 22.362 into register 22362 ! Easier to remember

 ![NodeRed - float to value](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/5/0/50352178b517ce465041344af7ec1de3d609d415.jpeg)

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [14 January 2020 11:22 UTC](https://discourse.nodered.org/t/newbie-convert-modbus-float-array-register-to-float-value/20293/2 "2020-01-14T11:22:13Z")

</div>

See [this](https://discourse.nodered.org/t/how-to-decode-16-bit-signed-integer/8112/10) thread (read it all) there are some pointers in there that might help.

---

<div class="post-metadata">

**Author:** ![PPz](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/ppz/32/15429_2.png) [@PPz](https://discourse.nodered.org/u/PPz)\
**Post date:** [14 January 2020 18:20 UTC](https://discourse.nodered.org/t/newbie-convert-modbus-float-array-register-to-float-value/20293/3 "2020-01-14T18:20:11Z")

</div>

Hi Steve and thank you for the link.  
It seems that for me the code is not that difficult (...) because values on the array are not hex but plain decimal.  
With my first test, I put readFloatBE() and I obtained a usable value.  
However, very strange to me, the result varies with every poll (even the data in the register is fixed for my test). Stranger, with 2 polls with the same code, I obtain 2 sets of variable values... The value set in my modbus register is 35.174 and I have the right value (35.17) only once in a while.

\ ***Edit** : here is the code I put. Ok, I'm a real newbie and I added what I found around here. I really don't know why those 2 lines are needed, but without: no results.

const buf = Buffer.allocUnsafe(4);  
buf.writeUInt16BE(pay[0]); // high byte

\ ***Edit2** : it seems, for unknown reasons, that LE displays now "correct" values (aka 0 because wrong type) instead of a replicated one. So Big Endian seems +/- ok, except the variability.

How is it possible ?  
Thank you++  
Mike

 ![node-red float different results](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/5/a/5a0c9690f08504ab77429512d41b136c72354372.jpeg)

 ![node-red float different results 2 and code](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/7/2/72d25c63078edf8b8f937a536c3fc3eebacdab42.jpeg)

 ![node-red float readFloatBE()](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/2/6/26a5c0a523b32350e03f85c1968916fbab60afda.jpeg)

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [14 January 2020 20:32 UTC](https://discourse.nodered.org/t/newbie-convert-modbus-float-array-register-to-float-value/20293/4 "2020-01-14T20:32:37Z")

</div>

I suspect when you update `msg.payload` in function 1 you are affecting the object before it's processed in the 2nd function.

It looks looks like the payload is an array/object so I world probably try returning a new object instead of updating `msg.payload` e.g...

```auto
var msg2 = {
  payload : buf.readFloatBE(0)
}
return msg2;

```

Try to remember the asynchronous nature of node-red and how object references work in JavaScript.

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [14 January 2020 20:34 UTC](https://discourse.nodered.org/t/newbie-convert-modbus-float-array-register-to-float-value/20293/5 "2020-01-14T20:34:03Z")

</div>

Can't really help more unless you post your flow and sample data.

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [14 January 2020 21:57 UTC](https://discourse.nodered.org/t/newbie-convert-modbus-float-array-register-to-float-value/20293/6 "2020-01-14T21:57:12Z")

</div>

> [@Steve-Mcl](#):
>
> I suspect when you update `msg.payload` in function 1 you are affecting the object before it's processed in the 2nd function.

Assuming this is in a recent version of node-red (@PPz which version is it?) then I don't think that should happen as node-red should automatically clone the message for the second wire out of the node.  
@PPz in the functions use `node.warn()` to show the contents of `pay` after you have picked it up.

---

<div class="post-metadata">

**Author:** ![PPz](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/ppz/32/15429_2.png) [@PPz](https://discourse.nodered.org/u/PPz)\
**Post date:** [14 January 2020 22:33 UTC](https://discourse.nodered.org/t/newbie-convert-modbus-float-array-register-to-float-value/20293/7 "2020-01-14T22:33:00Z")

</div>

> [@Colin](#):
>
> `node.warn()`

thank you both of you (@Steve-Mcl) for your kind help.  
My version is 1.0.3

the code of the function is :

let pay = msg.payload;  
const buf = Buffer.allocUnsafe(4); // (4) is ok  
buf.writeUInt16BE(pay[0]); // high byte  
msg.payload = buf.readFloatBE(0);  
// 2 numbers after comma (string)  
// msg.payload = buf.readFloatBE(0).toFixed(2);  
//  
return msg;

the float value into my plc is 22.362  
the raw received data is an array [16818,58720]  
the result (after function) varies from 22.25 to 22.37

about node.warn(), I'm affraid that I'm a real newbie about node-red

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [14 January 2020 22:34 UTC](https://discourse.nodered.org/t/newbie-convert-modbus-float-array-register-to-float-value/20293/8 "2020-01-14T22:34:59Z")

</div>

> [@PPz](#):
>
> about node.warn(), I'm affraid that I'm a real newbie about node-red

Have you tried searching for it?

---

<div class="post-metadata">

**Author:** ![PPz](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/ppz/32/15429_2.png) [@PPz](https://discourse.nodered.org/u/PPz)\
**Post date:** [14 January 2020 22:58 UTC](https://discourse.nodered.org/t/newbie-convert-modbus-float-array-register-to-float-value/20293/9 "2020-01-14T22:58:36Z")

</div>

> [@Colin](#):
>
> node.warn()

Yes, but when I inject  
node.warn(pay);  
I receive exactly the same array value [16818,58720] as the raw debug message

**Update** : when I inject node.warn(buf), I obtain a splitted array like this one: [65,178,98,5], or [65,178,125,3], or [65,178,0,0] (variable). Ok, 16818 = (256\*65)+178

**Update 2** : for what I understand here, the 2 first values of the array [65,178] seems consistent and represent probably/certainly the value that doesn't change (22). Why the others are changing ? A real mystery for me.

**Update 3** : maybe it will help you, but the weird thing about my plc is that the right value is in the array when dealing with 32b registers. If I poll a 32b register with a value of 22358, the node-red poll send me an array with [0,22358]. So it seems that's even not a hex value, just the plain decimal value...

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [15 January 2020 08:55 UTC](https://discourse.nodered.org/t/newbie-convert-modbus-float-array-register-to-float-value/20293/10 "2020-01-15T08:55:27Z")

</div>

> [@PPz](#):
>
> let pay = msg.payload;  
> const buf = Buffer.allocUnsafe(4); // (4) is ok  
> buf.writeUInt16BE(pay[0]); // high byte  
> msg.payload = buf.readFloatBE(0);

You are allocating a buffer of length 4 bytes. Then you use writeUInt16BE to write to the first two bytes. You have not written anything to the second two bytes so they are left with whatever happened to be lying around in that bit of memory. That is why they contain variable data. You then use readFloat to read all four bytes to give you the (veriable) result.

---

<div class="post-metadata">

**Author:** ![Iqapps](https://avatars.discourse-cdn.com/v4/letter/i/eada6e/32.png) [@Iqapps](https://discourse.nodered.org/u/Iqapps)\
**Post date:** [15 January 2020 10:39 UTC](https://discourse.nodered.org/t/newbie-convert-modbus-float-array-register-to-float-value/20293/11 "2020-01-15T10:39:16Z")

</div>

> [@Payload's number to two 16 bit register to be send via modbus](https://discourse.nodered.org/t/payloads-number-to-two-16-bit-register-to-be-send-via-modbus/4112/17):
>
> Hi ! U can use this code in function....after connect it to Modbus Flex Write function float32ToUint16(value) { var buffer = new ArrayBuffer(4); var intView = new Uint16Array(buffer); var floatView = new Float32Array(buffer); floatView[0] = value; return [intView[0], intView[1]]; } //var incoming = JSON.parse(msg.payload); //Compose ModBus message (Holding Registers) READ/WRITE var modbusHR = { payload : { 'value' : [float32ToUint16(msg.payload)[0], float32ToUint16(msg.…

---

<div class="post-metadata">

**Author:** ![PPz](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/ppz/32/15429_2.png) [@PPz](https://discourse.nodered.org/u/PPz)\
**Post date:** [16 January 2020 04:53 UTC](https://discourse.nodered.org/t/newbie-convert-modbus-float-array-register-to-float-value/20293/12 "2020-01-16T04:53:42Z")

</div>

tagging @Iqapps

Thank you. I need to dig more about this and I will probably come come back later with this. For you, it's probably a piece of cake. Not that obvious for me (must read some doc. I usually learn while have a problem to solve).

For the moment, I simplified my problem with my PLC (that I know far better): I created a bunch of 16b variables and made a small pgm (into my plc) to convert some floats registers into int16 (float\*100) and I transform them into floats (int16/100) to obtain a nice result with node-red and passing the values to mqtt and hubitat [shame on me).  
Because my main problem was to harvest modbus data and send them to Hubitat. Learn Hubitat, MQTT apps, mosquitto and Node-red at the same time is a little bit too much for me (I'm an old guy).

Thank you again for your answers.  
Mike

 ![modbus-node-red-mqtt-hubitat](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/9/3/93031a9141bc4a63dbb578cf1f4a86a6290b60fb.jpeg)

---

<div class="post-metadata">

**Author:** ![Iqapps](https://avatars.discourse-cdn.com/v4/letter/i/eada6e/32.png) [@Iqapps](https://discourse.nodered.org/u/Iqapps)\
**Post date:** [16 January 2020 09:48 UTC](https://discourse.nodered.org/t/newbie-convert-modbus-float-array-register-to-float-value/20293/13 "2020-01-16T09:48:39Z")

</div>

Here is little more information about how modbus handle 32 bit....

> **[How Real (Floating Point) and 32-bit Data is Encoded in Modbus RTU Messages](https://store.chipkin.com/articles/how-real-floating-point-and-32-bit-data-is-encoded-in-modbus-rtu-messages)**
>
> Modbus Integration Solutions
>             
> Chipkin has Modbus solutions for almost every situation. We are experts in Modbus RTU/TCP communication
> and carry a wide variety of Modbus products:
>             
>                 
> ...

---

<div class="post-metadata">

**Author:** ![PPz](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/ppz/32/15429_2.png) [@PPz](https://discourse.nodered.org/u/PPz)\
**Post date:** [17 January 2020 09:02 UTC](https://discourse.nodered.org/t/newbie-convert-modbus-float-array-register-to-float-value/20293/14 "2020-01-17T09:02:03Z")

</div>

tagging @Colin

thanks for the doc and the help.  
I discovered more and more and simplified a lot.  
Build on my plc a set of int16 registers.  
at first, I defined different polls, but the target plc was not happy of that (poll errors)  
Like in modbus devices, I set now 1 poll with successive addresses 🙂  
Far better !  
But now, with that method, I loose my different topic names for my MQTT broker (before: 1 topic per poll, now: 1 topic only because 1 poll)

Is it a way to define an array of topics when polling once and/or functions to build a specific topic for each extracted value ?

Before:

 ![multiple reads](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/9/f/9fe98bcdc9921f7b13e5fed25b13018d186b98d5.jpeg)

After:

 ![1 multiple read](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/0/6/06018c5f98b2bdddcd5f7947ab8db87bedcb87b4.jpeg)

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [17 January 2020 09:33 UTC](https://discourse.nodered.org/t/newbie-convert-modbus-float-array-register-to-float-value/20293/15 "2020-01-17T09:33:20Z")

</div>

In the Change nodes where you extract the individual parts add another row that Sets msg.topic To the/topic/for/this/value

---

<div class="post-metadata">

**Author:** ![PPz](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/ppz/32/15429_2.png) [@PPz](https://discourse.nodered.org/u/PPz)\
**Post date:** [17 January 2020 09:53 UTC](https://discourse.nodered.org/t/newbie-convert-modbus-float-array-register-to-float-value/20293/16 "2020-01-17T09:53:49Z")

</div>

Mucho Perfecto ! And much faster too...

 ![nore-red 1 poll multiple topics mqtt](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/6/8/680e6904bd166ffb235a2f024dff858c5f9dbf15.jpeg)

 ![hubitat-mqtt-modbus](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/0/c/0cda93c4d9caa903cfc8f3367f5efe4fe10175d4.jpeg)

---

<div class="post-metadata">

**Author:** ![mschmidt](https://avatars.discourse-cdn.com/v4/letter/m/97f17d/32.png) [@mschmidt](https://discourse.nodered.org/u/mschmidt)\
**Post date:** [28 February 2020 03:13 UTC](https://discourse.nodered.org/t/newbie-convert-modbus-float-array-register-to-float-value/20293/17 "2020-02-28T03:13:27Z")

</div>

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/a/c/ac51027b19aef4ac21a6d9d740b9a7e7785ef2bd.png)  
I believe this is along the same lines as this topic, but I'm a total newbie and need more help then just a picture of some screens.  
A little setting of the stage for this:  
I have some Modbus over Ethernet devices, right now I'm just polling one. I thought at first everything was great until I looked at my data logs this morning and saw some abnormal readings. So long story, I just get to the point, to make this east to understand and view I broke this back to the very basic.

I have a few values I can set manually in my device using the software that comes with it, I'm also polling that value in node-red. I used two just to show the what happens when any value get over 65.53.  
So it did take me a while to notice but each register is 2 points, the first point only shows a 0 or 1, the second point shows the value of point I'm polling. Notice on the bottom poll the actual reading on my device is 65.50 and the polled values are (0, 65000) "yes I could use a range on it to be the normal 65.50 but I wanted to show the raw data for this".  
The top one you'll notice looks completely different. The value in my device is at 66.0 and the polled value is now (1, 464).  
The actual tipping point is 65.53,  
65.54 comes back as 4,  
65.55 as 14  
65.56 as 24  
65.57 as 34  
65.67 as 134  
Its almost like it starts counting over above 65.53.  
It doesn't matter what point I poll on the controller nor does it matter what the scale is if it is 65.54 or greater it comes back as (1, xxx) type value.

Is there a way I can put this value through a function or something to balance this out?

Thank You

---

<div class="post-metadata">

**Author:** ![PPz](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/ppz/32/15429_2.png) [@PPz](https://discourse.nodered.org/u/PPz)\
**Post date:** [28 February 2020 03:39 UTC](https://discourse.nodered.org/t/newbie-convert-modbus-float-array-register-to-float-value/20293/18 "2020-02-28T03:39:37Z")

</div>

65.53 triggered a bell to me.  
does 65535 rings a bell to you ?  
one less than 2 to the 16th power  
there is a 16b integer somewhere in your value.

256 (2 to the 8th power) for 8 bits value. those numbers are important.

The harvested array changes because your data reached a limit.  
below 65500 (I think it could-must be 65535), the low byte is 0 and the high is the value. If it increases, your low byte changes to 1 and you add the difference  
in your case ( **1** x65535) + **464** = = 65999 =\> 65.99 = 66.0 (precision)

Note: it could be different, depending if your register is signed or unsigned.

a signed value has a range of 32767 because the value can be also negative while an unsigned value has a range of a full 16bit, aka 65535 ! In your case, your modbus register is an unsigned 16b

of course, your modbus device could also have 32bit registers, you can count.  
16b registers are common in modbus devices, some devices have only 16b registers. But you can harvest them an modify/split them the way you want.  
I have one plc and before sending data to mqtt / node-red, I change them all to 16b to simplify the poll.

coils (relays), digital 0 or 1 =\> 16b register (0 or 1)  
32b registers ? convert them to 16b registers and pay attention if their value is over 65535.  
I'm lazy, so if I know that the 32b register I poll will never be over 65535 (by example a temperature on a float register), I divide them by 100, tranform them to 16b and multiply then by 100 on the other side to obtain 2 numbers after the comma.

Float1 = 45.35 ===\> tempo = 45.35x100 = 4535 =\> transform to 16b =\> 4535 ===\> node-red/etc ==\> 4535 / 100 = 45.35 on the other side. Far easier than send floats and convert them with functions [low byte, high byte], etc !

---

<div class="post-metadata">

**Author:** ![mschmidt](https://avatars.discourse-cdn.com/v4/letter/m/97f17d/32.png) [@mschmidt](https://discourse.nodered.org/u/mschmidt)\
**Post date:** [28 February 2020 14:52 UTC](https://discourse.nodered.org/t/newbie-convert-modbus-float-array-register-to-float-value/20293/19 "2020-02-28T14:52:54Z")

</div>

PPz,  
thanks for the fast response.  
It sounds like you got this figured out which is great, now we just have to move your knowledge over to me.  
I know I'm asking you to take time out of your day, but is it possible you could either explain your calculations or better yet do it in node-red and show me how to do it.  
FYI the docs on my hardware show I have a few different Bits depending on what I'm polling.  
could you explain what I would need to do for each of these, I guess I'm confused on the signed/Unsigned. I mean I sort of understand the bit thing but not why its not compatible when I poll it through node-red.  
32 bit unsigned Integers  
32 bit signed Integer  
Sometimes those have LOW\_HI at the end, not sure what the LOW\_HI means as there is no further description in the docs.

Thanks for helping.

---

<div class="post-metadata">

**Author:** ![mschmidt](https://avatars.discourse-cdn.com/v4/letter/m/97f17d/32.png) [@mschmidt](https://discourse.nodered.org/u/mschmidt)\
**Post date:** [28 February 2020 15:03 UTC](https://discourse.nodered.org/t/newbie-convert-modbus-float-array-register-to-float-value/20293/20 "2020-02-28T15:03:00Z")

</div>

PPz,

I GOT IT!! well sort of, I know how to do this on paper now I just need to figure out how to do this in node-red.

so I have to poll the two registers (0,65000)  
If the first number is "X" and the second set of number is "Y" then:  
X\*Y+Y is what I'm looking for. then I could multiply time 100 to make it 65.00.

I just don't know how to do that in node-red just yet.

[Next page](https://discourse.nodered.org/t/newbie-convert-modbus-float-array-register-to-float-value/20293.md?page=2)
