Hello, I've got a rotation sensor that is returning values via Modbus through a Mitsubishi PLC, and the PLC programming software is calculating and displaying decimal values for a rate in the range 0.2m3/hr to 3 decimal places and stored as FLOAT [Single Precision]. However, when the numbers get to node-red, they're completely different. I'm putting them through buffer parser and have to set that to UINT16 to get the same numbers output.
I'm sure there must be some sort of formula I have to put them through, but I'm not sure what I'm dealing with... unsigned 16-bit integers that are off by orders of magnitude and seem to switch between very specific numbers?
Here's an example of what I'm getting in node-red, along with equivalent (?) numbers that appear in GXWorks 3 PLC programming software. The numbers seem to switch between these very specific values.
Typically though, what happens with PLC values is you or reading across the bounds of two different values or the data is byteswapped (little vs big endian).
The easiest way to solve this is to read from a unused area in the PLC. Enter known values directly into the PLC and check the buffer parser outputs what your expect.
More often than not, you need to byte swap or in the case of non IEE 754 compliant data, extract the exponent and whole parts manually.
Lastly, in mitsubishi PLC, the default for values is signed data. So any 16 bit number that goes above 32767 suddenly becomes a negative value, but when read as an unsigned integer, it does not.
If you can capture real data coming from the modbus node (use the debug copy value button) and provide the exact expected value, I'll show you how to use the buffer parser
Slightly frustratingly, I've tested reading several other known-value registers from the PLC, and e.g. 60 is broadcast for temperature, and 60 is received, no conversion/buffer parser needed.
Exact expected values are those seen in GXW3. Modbus node output is sequential as it is fed with a large data structure of available devices, and is just a single-number array. It looks like the 0. might be throwing node-red off.
PS, tables are supported in markdown, making it much easier to read
e.g...
GXWorks | Node-red | Expected Value / Type | Info
------- | -------- | --------------------- | ----
49504 | 49504 | 0.241 | buffer parser type set to UINT16 & scale of `/1000` - working ok
60645 | 60645 | 0.240 | buffer parser type set to UINT16 & scale of `/1000` - working ok
becomes
GXWorks
Node-red
Expected Value / Type
Info
49504
49504
0.241
buffer parser type set to UINT16 & scale of /1000 - working ok
60645
60645
0.240
buffer parser type set to UINT16 & scale of /1000 - working ok
I have reformatted the data. Issue is node-red seems to be reading single precision floats as garbage (albeit consistent sequential garbage), whereas all other modbus output numbers are read as exported from the PLC without any problems or buffer parsing. I was just wondering if there was a known number format that node-red used in such situations or whether the existing numbers looked like a known particular format that I could apply a transformation formula to? I can't see any pattern.
That makes sense; apologies for misunderstanding. I will post it here:
gfuel_flow_rate
Double numbers given for some numbers as I have observed both to appear in node-red while the PLC monitoring software GXW3 reports only one value. The numbers are definitely not random/read from the wrong place, as they consistently appear at the same time. I'm not sure if that's all the info required; a colleague who was also helping was saying that the hex values would probably be useful, but the software doesn't have an easy way of monitoring them so I would have to convert the numbers back to hex and hope I didn't mess it up if needed
I found this thread: Modbus 16 bit registers to Float value that sounds quite like my issue, but haven't had much luck copying the measures from that thread.
I'm currently experimenting with reading the hex buffer from the Modbus node.
In order to develop a solution for you, I need actual data captured using the copy value button and for it to be posted into a reply as text (JSON) (not a screenshot).
The reason for this is I will simulate your device (something I do not have access to) by taking the ACTUAL data that you post and injecting it into a demo flow.
The screenshots were not data, only illustrative of my data acquisition process(es), as I'm not sure if we're talking about getting it from the same place.
My Modbus-flex-getter node is outputting numbers like I previously posted (though if I remember rightly the previous data went through buffer parser set to UINT16), just with square brackets around them. I'm not sure how I can make the data any more real than that. As it is multiplexing across many different devices, I have to use a switch to select individual data streams, all of which are configured the same and all of which, bar one, work perfectly. e.g. like the following, from the malfunctioning gfuel_flow_rate data stream:
[41496]
[65061]
[41496]
The buffer output from the Modbus-flex-getter is different, but I'm not sure if that is what you're asking for, hence the screen recordings
NB. data not copied directly from Modbus node debug because there are 6 simultaneous data streams and I can't pause the node-red debug log or move fast enough to copy the relevant part...
@Darren, no need for the apologies. And don't worry, this will all fall into place very soon (you are getting close - and you will learn lots in the process - so its all good)
This is what I need - BUT - what are they supposed to be parsed to? Are these the first 2 from your list?
Value in PLC (read from GXW3, m3/hr)
PLC Data Type
Value seen in Modbus
Expected value
0.241
Float [Single Precision]
49504
0.241
0.240
Float [Single Precision]
60645, 16420
0.240
One more thing: Single precision floats are typically 32bit values. Can you confirm if the PLC occupies uses 2 16 bit WORDS to hold the float values?
If they are 32 Bit, you need to request a length of 2 in the ModBus data.
In case you are not aware, ModBus always delivers 16 bit data. Thats why floats can be a pain. It doesnt help when the PLC or interface swaps bytes and doesnt adhere to IEE floats.
That isnt really a worry but it is important to know what size the data is in the PLC.
If you dont know, identify the function in the PLC writing to the address & I will tell you.
Back to the data for parsing:
Let me try to make this clearer .
I need:
The ACTUAL ModBus payload (you did this when you copied the full payload value - great!)
At the EXACT SAME TIME - I need the ACTUAL equivalent matching value from the PLC - so that I have both the source (ModBus) data AND a target value to achieve - so I can check my work and ensure you get accurate data.
Understood now! Thank you! I will enter the data here:
Expected value
Modbus
0.165
{"data":[41496],"buffer":[162,24]}
0.229
{"data":[32108],"buffer":[125,108]}
0.201
{"data":[56615],"buffer":[221,39]}
0.235
{"data":[11439],"buffer":[44,175]}
0.228
{"data":[52312],"buffer":[204,88]}
0.164
{"data":[65061],"buffer":[254,37]}
0.228
{"data":[7247],"buffer":[28,79]}
0.165
{"data":[65061],"buffer":[254,37]}
0.164
{"data":[60204],"buffer":[235,44]}
That is the data from the monitoring software with the concurrent Modbus reading. Strangely, for the same expected value, there are multiple (but consistent) Modbus readings.
I must admit, it skipped my mind to remove the other data streams; however, I believe the switch implemented serves much the same purpose to separate them out. I didn't think to use a delay note to rate limit things. I think I've got it working now, though. Thank you for the advice
A colleague did mention Modbus output only 16bit, wheras I have read on StackOverflow that JS only uses 32bit by default. I'm looking through the PLC documentation, though in the "Data Type Selection" there are Double Word [Unsigned]/Bit String [32-bit], Word [Unsigned]/Bit String [16-bit], Word [Signed], Double-Word [Signed] as well as FLOAT [Single Precision]
Before I do this, please clarify the size of data in PLC:
Its just that you have provided 1 WD (2 byte) data for each "Expected value" and typically, single precision floats are 32bit (2 WDs / 4 bytes) and this will be key (critical) to getting this right.