Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to read signed float values? #459

Open
mridah opened this issue Apr 18, 2024 · 3 comments
Open

How to read signed float values? #459

mridah opened this issue Apr 18, 2024 · 3 comments
Assignees
Labels

Comments

@mridah
Copy link

mridah commented Apr 18, 2024

I want to read a signed float value. I'm using Modbus Read node with quantity set to 2.

image

The function I have is as follows:

let pay = msg.payload.data;

var sign = pay[0] + pay[1] >= 65535 ? '-' : '+'; 

pay[0] = pay[0] > 32767 ? pay[0] - 32767 : pay[0];
pay[1] = pay[1] > 32767 ? pay[1] - 32767 : pay[1];

const buf = Buffer.allocUnsafe(4);

buf.writeUInt16BE(pay[0], 2); // high byte
buf.writeUInt16BE(pay[1], 0); // low byte

var val = Math.round(buf.readFloatBE(0) * 100) / 100;

msg.payload = parseFloat(sign + val);

This gives me the correct numeric value, however the sign keeps changing randomly. So I figured my logic to calculate the sign is wrong.

How can I read the actual float value with the correct sign?

@unborn-andy
Copy link

unborn-andy commented Apr 19, 2024

Hi .. I believe that readFloatBE should handle negative and positive values .. no need to calculate the sign yourself.
Use the node-red-contrib-buffer-parser nodes .. they are very convenient for these kind of conversions.

Test Flow of their use (note that modbus nodes have the buffer data in msg.responseBuffer.buffer )

[{"id":"e9ea7e42fad5bfc9","type":"debug","z":"54efb553244c241f","name":"debug 71","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":660,"y":2180,"wires":[]},{"id":"e423319c59b4385d","type":"buffer-parser","z":"54efb553244c241f","name":"","data":"payload","dataType":"msg","specification":"spec","specificationType":"ui","items":[{"type":"floatbe","name":"item1","offset":0,"length":1,"offsetbit":0,"scale":"1","mask":""}],"swap1":"","swap2":"","swap3":"","swap1Type":"swap","swap2Type":"swap","swap3Type":"swap","msgProperty":"payload","msgPropertyType":"str","resultType":"keyvalue","resultTypeType":"return","multipleResult":false,"fanOutMultipleResult":false,"setTopic":true,"outputs":1,"x":350,"y":2180,"wires":[["351a01ed0d1285b6"]]},{"id":"7ef5c6af71df65b8","type":"inject","z":"54efb553244c241f","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"-1234.4452","payloadType":"num","x":170,"y":2040,"wires":[["89a4fa5d19b5ccdf"]]},{"id":"89a4fa5d19b5ccdf","type":"buffer-maker","z":"54efb553244c241f","name":"","specification":"spec","specificationType":"ui","items":[{"name":"item1","type":"floatbe","length":1,"dataType":"msg","data":"payload"}],"swap1":"","swap2":"","swap3":"","swap1Type":"swap","swap2Type":"swap","swap3Type":"swap","msgProperty":"payload","msgPropertyType":"str","x":330,"y":2040,"wires":[["9d8e141360959f50"]]},{"id":"9d8e141360959f50","type":"debug","z":"54efb553244c241f","name":"debug 72","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":480,"y":2040,"wires":[]},{"id":"351a01ed0d1285b6","type":"function","z":"54efb553244c241f","name":"math round","func":"msg.payload = Math.round(msg.payload.item1 * 100) /100\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":510,"y":2180,"wires":[["e9ea7e42fad5bfc9"]]},{"id":"31828368077565d8","type":"inject","z":"54efb553244c241f","name":"Modbus buffer","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[196,154,78,63]","payloadType":"bin","x":180,"y":2180,"wires":[["e423319c59b4385d"]]},{"id":"0565e32cafce835e","type":"comment","z":"54efb553244c241f","name":"float to Buffer","info":"","x":170,"y":2000,"wires":[]},{"id":"4a8da04fb4850514","type":"comment","z":"54efb553244c241f","name":"Buffer to float","info":"","x":170,"y":2140,"wires":[]}]

@grewek
Copy link

grewek commented Apr 22, 2024

Hi,

The sign bit in a floating value is the highest bit of the number so in your case this would be bit 15 in pay[0]
so what you could do is use a bit mask and a shift:

var sign = pay[0] & (1 << 15) ? '-' : '+'

Short explanation:
(1 << 15)
First we are take the value 1(binary: 0000 0000 0000 0001) and shift it up 15 positions to the left (<<) which gives us (binary: 1000 0000 0000 0000) we can now isolate the sign bit by use the Binary AND operator (i will use the value shown in your screenshot):

1000 0001 1010 1110 | (33198)
1000 0000 0000 0000 | (32786)
--------------------
1000 0000 0000 0000

This should solve your sign issues

Copy link

This issue is stale because it has been open 60 days with no activity. It will be closed in 30 days, but can be saved by removing the stale label or commenting.

@github-actions github-actions bot added the Stale label Jul 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants