Format data to INT_16 for Modbus TCP

We are using the 1-wire node to read temperature from a 1-wire sensor. The node output msg.payload is as follows:
{"payload":15.25,"topic":"","_msgid":"dac51164c5a5ec03"}

We need to write this temperature data (in this example 15.25) to a Modbus TCP client with the "Modbus write" node, and the error we currently get is:
Error: Data length error, expected 8 got 4

So I guess some sort of data parsing/conversion needs to take place (with a function node or parse node?) to format the payload to a clean 16 bit signed integer so that the Modbus TCP client register can be written with function code 6.

What is the simplest most effective way to achieve this?

Thank you!

Flow and used nodes follow:

[
    {
        "id": "873e6f46fb3cd974",
        "type": "1-Wire",
        "z": "f41a1647b9ab4cab",
        "identifier": "28-00000cfa46e8",
        "name": "Sensor",
        "format": "1",
        "x": 380,
        "y": 840,
        "wires": [
            [
                "b71bc2e80e367d13",
                "6d814f4da6947f0b"
            ]
        ]
    },
    {
        "id": "b71bc2e80e367d13",
        "type": "debug",
        "z": "f41a1647b9ab4cab",
        "name": "debug 1",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 660,
        "y": 840,
        "wires": []
    },
    {
        "id": "5849884c7f8b304d",
        "type": "inject",
        "z": "f41a1647b9ab4cab",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "5",
        "crontab": "",
        "once": true,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 190,
        "y": 840,
        "wires": [
            [
                "873e6f46fb3cd974"
            ]
        ]
    },
    {
        "id": "6d814f4da6947f0b",
        "type": "modbus-write",
        "z": "f41a1647b9ab4cab",
        "name": "MTCP",
        "showStatusActivities": true,
        "showErrors": true,
        "unitid": "1",
        "dataType": "HoldingRegister",
        "adr": "40002",
        "quantity": "1",
        "server": "df54d9acd8346d83",
        "emptyMsgOnFail": true,
        "keepMsgProperties": true,
        "x": 650,
        "y": 920,
        "wires": [
            [],
            []
        ]
    },
    {
        "id": "df54d9acd8346d83",
        "type": "modbus-client",
        "name": "MDBUS CLIENT",
        "clienttype": "tcp",
        "bufferCommands": true,
        "stateLogEnabled": false,
        "queueLogEnabled": false,
        "failureLogEnabled": true,
        "tcpHost": "192.168.1.167",
        "tcpPort": "502",
        "tcpType": "DEFAULT",
        "serialPort": "/dev/ttyUSB",
        "serialType": "RTU-BUFFERD",
        "serialBaudrate": "9600",
        "serialDatabits": "8",
        "serialStopbits": "1",
        "serialParity": "none",
        "serialConnectionDelay": "100",
        "serialAsciiResponseStartDelimiter": "0x3A",
        "unit_id": "1",
        "commandDelay": "1",
        "clientTimeout": "1000",
        "reconnectOnTimeout": true,
        "reconnectTimeout": "2000",
        "parallelUnitIdsAllowed": true
    }
]

your value is a float .. sometimes floats are 32 bit values (2 registers) or it could be an integer divided by a /10 or /100 (multiplied in this case to get back to an 16bit int). Do you know how your Modbus device expects the value ? Do you have any documentation ?

Hi there, yes the modbus device expects a INT_16 value, that is a signed 16 bit interger value.

ok .. what if you do send an integer instead of a float
If you wire an Inject node to the Modbus Write node and send a msg.payload 15 (change to type Number)

image

does this get written to the device ?


.. you can also try changing your register and writing to address 2

image


[EDIT]

As i mentioned above floats are usually 32bit and use 4 bytes
meaning that you may need to write to 2 x registers to the device. FC16
If that is the case the conversion for that could be done either with the buffer nodes
or in a Function node, make an array of the two registers UInt16bit values that the modbus node expects

let buf = Buffer.alloc(4)
buf.writeFloatBE(msg.payload, 0)
msg.payload = [buf.readUInt16BE(0), buf.readUInt16BE(2)]

return msg;

From the node's help tab :

For FC 16, msg.payload must be an array[] of comma separated values between 0:65535 each.

i could be wrong .. im tagging @Steve-Mcl who is a ninja with these things .. crunches bytes for breakfast

Hi telinal,

like UnborN suggested you are trying to write a float value (32 bit) in a single register (16 bit). I replicated what you are doing with a local modbus server and basically I get to write "15" (the floating point part is ignored). I am reading 4 registers just to show that there is nothing else being written.


If you really want to write the exact value, you need to write it to multiple registers with FC16 (check for your device endianess requirements).

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.