Signed Integer showing 3 phase power factor for electrical metering

This is a signed three phase power factor value. The manual states the following "-100 to +1000 to +100 in 1000th. It is from a 16 bit register. The most significant bit is left as read and is the sign value. When "0" the number is positive. When a "1" it is negative. The most significant value bit is 512 in binary
Example 0000_0011_1110_1000 = 1000 and 1000_0000_0000_0001 = -1. Thanks, Hans

I’m not sure what the question is, but I suspect that the node-red-contrib-buffer-parser node is the answer.

Can you provide a reference to the 'manual' as the maths (you quoted) doesn't make sense (to me).
Normally in signed binary values the sign-digit has a negative value (if it is set) all other bits are positive.
Your first example works out to be decimal 1000, but I can't work out how your second example equals -1

In a binary number, the bit furthest to the left is called the most significant bit (msb) and the bit furthest to the right is called the least significant bit (lsb). The MSB gives the sign of the number (sign bit) , 0 for positive and 1 for negative.

Electrical Power Factor is the relationship between the phase angles of voltage and current. When in unity the value = 1 that is represented by 1000 in this case it then closes on zero or negative zero as the angles between increase. I know negative zero is imaginary.

We need a way to change the number from negative to positive based on the left most significant bit. Does that help?

Can you explain how to configure node-red-buffer-parser node for this?

In a binary number, the bit furthest to the left is called the most significant bit (msb) and the bit furthest to the right is called the least significant bit (lsb). The MSB gives the sign of the number (sign bit) , 0 for positive and 1 for negative.

Electrical Power Factor is the relationship between the phase angles of voltage and current. When in unity the value = 1 that is represented by 1000 in this case it then closes on zero or negative zero as the angles between increase. I know negative zero is imaginary.

We need a way to change the number from negative to positive based on the left most significant bit. Does that help?
[/quote]

So that binary value is just a regular 16 bit INT (or UINT for that matter)

Are you 100% certain?

In regular 16 bit encoding, 1000_0000_0000_0001 is either -32767 (int) or 32769 (uint)

If that is really how the numbers have been encoded then here is one way...

[{"id":"384f507fa0042cf6","type":"function","z":"10ece3ab98e93683","name":"1000_0000_0000_0001 ","func":"const b = Buffer.alloc(2)\nb.writeUint16BE(0b1000_0000_0000_0001)\nmsg.payload = b\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":650,"y":1100,"wires":[["717232324b714dcb"]]},{"id":"aa51d42f601ceae8","type":"function","z":"10ece3ab98e93683","name":"0000_0011_1110_1000","func":"const b = Buffer.alloc(2) \nb.writeUint16BE(0b0000_0011_1110_1000)\nmsg.payload = b\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":650,"y":1060,"wires":[["717232324b714dcb"]]},{"id":"717232324b714dcb","type":"buffer-parser","z":"10ece3ab98e93683","name":"","data":"payload","dataType":"msg","specification":"spec","specificationType":"ui","items":[{"type":"int16be","name":"regularINT","offset":0,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"uint16be","name":"regularUINT","offset":0,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"uint16be","name":"youWant=>sign","offset":0,"length":1,"offsetbit":15,"scale":">> 15","mask":""},{"type":"uint16be","name":"youWant=>value","offset":0,"length":1,"offsetbit":15,"scale":"1","mask":"0x7FFF"}],"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":890,"y":1080,"wires":[["02fdc15c11448b36"]]},{"id":"b89f8dbdd3e04361","type":"inject","z":"10ece3ab98e93683","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":495,"y":1100,"wires":[["384f507fa0042cf6"]],"l":false},{"id":"1908b4bdb09a7523","type":"inject","z":"10ece3ab98e93683","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":495,"y":1060,"wires":[["aa51d42f601ceae8"]],"l":false},{"id":"291cdcec1cedbe62","type":"debug","z":"10ece3ab98e93683","name":"debug 55","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1060,"y":1140,"wires":[]},{"id":"02fdc15c11448b36","type":"change","z":"10ece3ab98e93683","name":"make result","rules":[{"t":"set","p":"payload.youWant.result","pt":"msg","to":"payload.youWant.sign ? -payload.youWant.value : payload.youWant.value","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":1070,"y":1080,"wires":[["291cdcec1cedbe62"]]}]
1 Like

Yes pretty certain. Took samples, ran binary results through programmer calculator, viewed the values and compared to what is displayed on device. It is an odd use but real.

pretty much what whatever the results are except the msb on left is the sign bit.

It is essentially a 16 bit form of traditional two's complement with the 16th bit being the sign bit.

Some references call this signed magnitude.

In a 16-bit binary pattern, where the MSB (is the sign digit) it would have a value of -32,768
This gives a numeric range from -32,768 to +32,767
If all the bits are set as in... 1111_1111_1111_1111
Then I believe that should be equal to -1 (e.g. -32,768 + (+32,767) )

We are basically presented with values as high as 1000 down to zero with the 16th big (MSB left) as the sign bit. We then take the result and divide by 1000 to get the answer. What code / setting do we need to make this happen?

Does the flow and function I provided not work? If it does work, then simply add one more line to the change node to divide the value by 1000.

Steve-Mcl:

Regret that I am new to Node-Red coding. Like the other example that you helped me figure out (Mod 10k) I do not know enough to understand what is going on "under the hood." Did put the blocks you suggested in place but there must be more settings in the blocks that need to be set for this to work. Thanks Hans

I copied that string of code that you wrote and dropped it into the buffer parser block programming area. Results still not coming out right.

Display on device is reading around -260. If jumps around since it is a live reading. Do not know how to configure the second block that you are showing in your example.

Flow - use CTRL-I to import

[{"id":"48b9b71af44a1cd9","type":"function","z":"b851e68919625d02","name":"1000_0000_0000_0001 ","func":"const b = Buffer.alloc(2)\nb.writeUint16BE(0b1000_0000_0000_0001)\nmsg.payload = b\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1970,"y":360,"wires":[["b234510f066da748"]]},{"id":"8e40dff5f6ab0d93","type":"function","z":"b851e68919625d02","name":"0000_0011_1110_1000","func":"const b = Buffer.alloc(2) \nb.writeUint16BE(0b0000_0011_1110_1000)\nmsg.payload = b\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1970,"y":320,"wires":[["b234510f066da748"]]},{"id":"b234510f066da748","type":"buffer-parser","z":"b851e68919625d02","name":"","data":"payload","dataType":"msg","specification":"spec","specificationType":"ui","items":[{"type":"uint16be","name":"sign","offset":0,"length":1,"offsetbit":15,"scale":">> 15","mask":""},{"type":"uint16be","name":"value","offset":0,"length":1,"offsetbit":15,"scale":"/ 1000","mask":"0x7FFF"}],"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":2210,"y":340,"wires":[["e82b5f868774848a"]]},{"id":"26afa10e45aa369e","type":"inject","z":"b851e68919625d02","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":1815,"y":360,"wires":[["48b9b71af44a1cd9"]],"l":false},{"id":"ef7260b23a524a46","type":"inject","z":"b851e68919625d02","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":1815,"y":320,"wires":[["8e40dff5f6ab0d93"]],"l":false},{"id":"5ff03b1f2adc175c","type":"debug","z":"b851e68919625d02","name":"debug 55","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":2380,"y":400,"wires":[]},{"id":"e82b5f868774848a","type":"change","z":"b851e68919625d02","name":"make result","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.sign ? -payload.value : payload.value","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":2390,"y":340,"wires":[["5ff03b1f2adc175c"]]}]
1 Like

Works perfectly. Thanks for the complete explanation. You made it too easy for me. Will need to do a post mortem to figure out what you did. Need to learn how to stand on my own legs. Still crawling now. Sincere Thanks,Hans
w