I'd like to write throgh a modbus connection a boolean into the corresponding bit contained in a WORD in my PLC, but I can't write the single bit to the FC Holding register. I use node-red-contrib-modbus.
When I read the single bit, I read the whole WORD and split it into 16 bits, with node-red-contrib-bit. I looked for a similar node to assemble 16 bits into a single word, but I couldn't find it.
Can you send us some more information on your flow (maybe paste a sample of your flow)
Im interested also in Modbus and have the node-red-contrib-modbus set of nodes installed.
For my simulation i used a Modbus Flex Write for a single value write
yes, I fixed that. Now I can write the value, but it overwrite the whole Word.
The problem is my PLC doesn't support the FC5 function (the coils) because it hasn't the hardware memory, so I can only write the whole word. If I want set the 4th bit to 1, the only way I found to write it is pass a decimal value that's equal to a word that has the 4th bit set to 1.
The problem is in this way I erase the states of the other bits.
I found this code (to be paste in a funciton node?) on another topic:
//Get bit
function getBit(number, bitPosition) {
return (number & (1 << bitPosition)) === 0 ? 0 : 1;
}
//Set Bit
function setBit(number, bitPosition) {
return number | (1 << bitPosition);
}
//Clear Bit
function clearBit(number, bitPosition) {
const mask = ~(1 << bitPosition);
return number & mask;
}
//Update Bit
function updateBit(number, bitPosition, bitValue) {
const bitValueNormalized = bitValue ? 1 : 0;
const clearMask = ~(1 << bitPosition);
return (number & clearMask) | (bitValueNormalized << bitPosition);
}
//You could use the code from these to update a WORD value and set / reset bits...
var plcValue = msg.payload;
//Set Bit 12
plcValue = plcValue | (1 << 12);
//reset Bit 3
const mask = ~(1 << 3);
plcValue = plcValue & mask;
msg.payload = plcValue; //(return this for next node to send it back to the PLC
return msg;
And I think is the right way to achive what I wan: something like everytime I want to set a bit in a Word, check the other bits and write the word in the corrisponding decimal value to set to desidered bit only without alter the others.
The problem is I can't figure out how exactly combine the code above to the function nodes and the modbus writing ones...
So the only way is using FC15 to write to multiple coils?
I don't know how useful those binary functions can be and I dont have any experience with those
but i was thinking the following stages for a possible solution.
Do an initial FC1 read with a trigger node and save the array status result in Node-red flow Context.
You can read about the use of Context here. This array should be an array of boolean [ true, true, false, false, true ] each representing the current status of the coils.
When its time to write to the coils, update with a function node the node-red context array, prepare the modbus msg and send it.
[{"id":"7ed14e5.f2503b","type":"modbus-flex-write","z":"ddb94f08.dac8a8","name":"","showStatusActivities":false,"showErrors":false,"server":"28c906aa.79aae2","emptyMsgOnFail":false,"keepMsgProperties":false,"x":830,"y":420,"wires":[["30459f25.0f9838"],[]]},{"id":"a590b4c1.0f80e","type":"inject","z":"ddb94f08.dac8a8","name":"","props":[{"p":"payload"},{"p":"coil","v":"0","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"true","payloadType":"bool","x":310,"y":320,"wires":[["ebde8026.c14da8"]]},{"id":"30459f25.0f9838","type":"debug","z":"ddb94f08.dac8a8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1070,"y":400,"wires":[]},{"id":"ebde8026.c14da8","type":"function","z":"ddb94f08.dac8a8","name":"FC15","func":"// get current status array for example [ true, true, false, false, true ]\nlet deviceStatus = flow.get(\"deviceStatus\"); \n\n// what coil to update .. must be sent in msg.coil as a number \nlet coil = msg.coil;\n\n// update x coil status in array based on payload true,false\ndeviceStatus[coil] = msg.payload;\n// update status for context\nflow.set(\"deviceStatus\", deviceStatus); \n\n// prepare msg for Modbus flex write\nmsg.payload = {\n value: deviceStatus , \n 'fc': 15, \n 'unitid': 1, \n 'address': 0 , \n 'quantity': 5 \n}; \n\n // send msg to Modbus flex write\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":610,"y":420,"wires":[["7ed14e5.f2503b"]]},{"id":"ef4575de.037b28","type":"comment","z":"ddb94f08.dac8a8","name":"Update Context and Prepare Write","info":"","x":760,"y":320,"wires":[]},{"id":"3237f347.ed54b4","type":"inject","z":"ddb94f08.dac8a8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":"3","topic":"","payload":"trigger","payloadType":"str","x":190,"y":140,"wires":[["4b202f6f.f4938"]]},{"id":"eb0f70eb.9b4c4","type":"debug","z":"ddb94f08.dac8a8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1030,"y":140,"wires":[]},{"id":"4b202f6f.f4938","type":"function","z":"ddb94f08.dac8a8","name":"FC01","func":"msg.payload = { \n value: msg.payload, \n 'fc': 1, \n 'unitid': 1, \n 'address': 0 , \n 'quantity': 5 \n} \nreturn msg\n","outputs":1,"noerr":0,"initialize":"","finalize":"","x":370,"y":140,"wires":[["1d12e1bf.a40bbe"]]},{"id":"1d12e1bf.a40bbe","type":"modbus-flex-getter","z":"ddb94f08.dac8a8","name":"","showStatusActivities":false,"showErrors":false,"logIOActivities":false,"server":"28c906aa.79aae2","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":false,"keepMsgProperties":false,"x":620,"y":140,"wires":[["e471c7d9.aab7c"],[]]},{"id":"e471c7d9.aab7c","type":"function","z":"ddb94f08.dac8a8","name":"","func":"// take only the first 5 because flex getter returns 8\nlet deviceStatus = msg.payload.slice(0,5) \n\n// set Node-red context in memory\nflow.set('deviceStatus', deviceStatus)\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":840,"y":140,"wires":[["eb0f70eb.9b4c4"]]},{"id":"5818ac8a.bccd24","type":"inject","z":"ddb94f08.dac8a8","name":"","props":[{"p":"payload"},{"p":"coil","v":"0","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"false","payloadType":"bool","x":310,"y":380,"wires":[["ebde8026.c14da8"]]},{"id":"5eac710f.091238","type":"comment","z":"ddb94f08.dac8a8","name":"Initial Read","info":"","x":340,"y":80,"wires":[]},{"id":"25f887fd.782f48","type":"comment","z":"ddb94f08.dac8a8","name":"Set Context","info":"","x":850,"y":80,"wires":[]},{"id":"a55a5106.4402b","type":"comment","z":"ddb94f08.dac8a8","name":"0","info":"","x":150,"y":360,"wires":[]},{"id":"d2c7c90d.c7ad5","type":"inject","z":"ddb94f08.dac8a8","name":"","props":[{"p":"payload"},{"p":"coil","v":"1","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"true","payloadType":"bool","x":310,"y":460,"wires":[["ebde8026.c14da8"]]},{"id":"b8d89b7e.10ab6","type":"inject","z":"ddb94f08.dac8a8","name":"","props":[{"p":"payload"},{"p":"coil","v":"1","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"false","payloadType":"bool","x":310,"y":520,"wires":[["ebde8026.c14da8"]]},{"id":"70365c01.0a213c","type":"comment","z":"ddb94f08.dac8a8","name":"1","info":"","x":150,"y":500,"wires":[]},{"id":"28c906aa.79aae2","type":"modbus-client","z":"","name":"TCP1","clienttype":"tcp","bufferCommands":true,"stateLogEnabled":false,"queueLogEnabled":false,"tcpHost":"192.168.1.66","tcpPort":"502","tcpType":"TPC-RTU-BUFFERED","serialPort":"/dev/ttyUSB","serialType":"RTU-BUFFERD","serialBaudrate":"9600","serialDatabits":"8","serialStopbits":"1","serialParity":"none","serialConnectionDelay":"100","unit_id":1,"commandDelay":200,"clientTimeout":1000,"reconnectOnTimeout":true,"reconnectTimeout":2000,"parallelUnitIdsAllowed":true}]
ps. modifications needed to represent your devices and number of outputs etc
Hi There,
Actually it hasn't coil memory at all, it uses different memory function to handle boolean values. I can only read and write Holding Registers, and so the problem occurs.
Anyway, I appreciate a lot yuor example: I managed to use the code above to handle the entire register reading it and update it in order to set or reset the single desired bit, but I had to understand in nodered how to pass information through nodes.
I'm using the payload's topic property, but when I use switch or buttons to pass the 0,1 values it doesn't work like expected.
[{"id":"24c3208f.07b0f8","type":"tab","label":"TEST 1","disabled":false,"info":""},{"id":"3b0ba67b.d282aa","type":"comment","z":"24c3208f.07b0f8","d":true,"name":"NON TOCCARE","info":"","x":134,"y":54,"wires":[]},{"id":"c4ea4cd3.589e6","type":"modbus-read","z":"24c3208f.07b0f8","d":true,"name":"ModbusReadMX0.0","topic":"","showStatusActivities":false,"logIOActivities":false,"showErrors":false,"unitid":"","dataType":"HoldingRegister","adr":"0","quantity":"1","rate":"1","rateUnit":"s","delayOnStart":false,"startDelayTime":"","server":"341b16ee.e3dffa","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":false,"x":126,"y":126,"wires":[["2a4c3fa7.cec83"],[]]},{"id":"2a4c3fa7.cec83","type":"function","z":"24c3208f.07b0f8","d":true,"name":"","func":"//Get bit\nfunction getBit(number, bitPosition) {\n return (number & (1 << bitPosition)) === 0 ? 0 : 1;\n}\n\n//Set Bit\nfunction setBit(number, bitPosition) {\n return number | (1 << bitPosition);\n}\n\n//Clear Bit\nfunction clearBit(number, bitPosition) {\n const mask = ~(1 << bitPosition);\n return number & mask;\n}\n\n//Update Bit\nfunction updateBit(number, bitPosition, bitValue) {\n const bitValueNormalized = bitValue ? 1 : 0;\n const clearMask = ~(1 << bitPosition);\n return (number & clearMask) | (bitValueNormalized << bitPosition);\n}\n\n//You could use the code from these to update a WORD value and set / reset bits...\n\nvar plcValue = msg.payload;\n\n//Set Bit 12\nplcValue = plcValue | (1 << 12);\n\n//reset Bit 3\nconst mask = ~(1 << 3);\nplcValue = plcValue & mask;\n\nmsg.payload = plcValue; //(return this for next node to send it back to the PLC\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":348,"y":126,"wires":[["ddbb45c0.098cf8"]]},{"id":"ddbb45c0.098cf8","type":"debug","z":"24c3208f.07b0f8","d":true,"name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":560,"y":126,"wires":[]},{"id":"ab331823.bbe138","type":"modbus-read","z":"24c3208f.07b0f8","name":"ModbusReadMX0.0","topic":"","showStatusActivities":false,"logIOActivities":false,"showErrors":false,"unitid":"","dataType":"HoldingRegister","adr":"0","quantity":"1","rate":"1","rateUnit":"s","delayOnStart":false,"startDelayTime":"","server":"341b16ee.e3dffa","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":false,"x":162,"y":396,"wires":[["b1ef07b9.1a414"],[]]},{"id":"39fa5629.27d82a","type":"debug","z":"24c3208f.07b0f8","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1096,"y":396,"wires":[]},{"id":"51581f15.ad7af","type":"comment","z":"24c3208f.07b0f8","name":"TEST","info":"","x":176,"y":234,"wires":[]},{"id":"43246e79.252d2","type":"modbus-write","z":"24c3208f.07b0f8","name":"","showStatusActivities":false,"showErrors":false,"unitid":"","dataType":"HoldingRegister","adr":"0","quantity":"1","server":"341b16ee.e3dffa","emptyMsgOnFail":false,"keepMsgProperties":false,"x":890,"y":396,"wires":[["39fa5629.27d82a"],[]]},{"id":"d235ab78.64466","type":"function","z":"24c3208f.07b0f8","name":"ModbusWrite BOOL","func":"//Get bit\nfunction getBit(number, bitPosition) {\n return (number & (1 << bitPosition)) === 0 ? 0 : 1;\n}\n\n//Set Bit\nfunction setBit(number, bitPosition) {\n return number | (1 << bitPosition);\n}\n\n//Clear Bit\nfunction ResetBit(number, bitPosition) {\n const mask = ~(1 << bitPosition);\n return number & mask;\n}\n\n//Update Bit\nfunction updateBit(number, bitPosition, bitValue) {\n const bitValueNormalized = bitValue ? 1 : 0;\n const clearMask = ~(1 << bitPosition);\n return (number & clearMask) | (bitValueNormalized << bitPosition);\n}\n\n//You could use the code from these to update a WORD value and set / reset bits...\n\nvar plcValue = {payload : (msg.topic === \"read\")};\nvar nBitSet = {payload : (msg.topic === \"nBitSet\")};\nvar nBitReset = {payload : (msg.topic === \"nBitReset\")};\nvar BitSet = {payload : (msg.topic === \"BitSet\")};\nvar BitReset = {payload : (msg.topic === \"BitReset\")};\n\n//Set Bit\nplcValue = setBit(plcValue,nBitSet)\nplcValue = ResetBit(plcValue,nBitReset)\n\n//reset Bit \n//plcValue = clearBit(plcValue,)\n\nif (BitSet || BitReset) {\nmsg.payload = plcValue;\nreturn msg;\n}//(return this for next node to send it back to the PLC\n","outputs":1,"noerr":0,"initialize":"","finalize":"","x":622,"y":396,"wires":[["43246e79.252d2","cc4776e5.82b14"]]},{"id":"d672abb8.25bfe8","type":"ui_numeric","z":"24c3208f.07b0f8","name":"nBitSet","label":"Setta il Bit","tooltip":"","group":"55555671.2d14","order":0,"width":0,"height":0,"wrap":true,"passthru":true,"topic":"nBitSet","format":"{{value}}","min":0,"max":"15","step":"1","x":402,"y":270,"wires":[["d235ab78.64466","8f9449aa.d5ed78"]]},{"id":"be7ad185.b3dc38","type":"ui_numeric","z":"24c3208f.07b0f8","name":"nBitReset","label":"Resetta il Bit","tooltip":"","group":"55555671.2d14","order":0,"width":0,"height":0,"wrap":true,"passthru":true,"topic":"nBitReset","format":"{{value}}","min":0,"max":"15","step":1,"x":402,"y":306,"wires":[["d235ab78.64466","5174aa49.7fd86c"]]},{"id":"f9616625.8e8ae","type":"ui_button","z":"24c3208f.07b0f8","name":"BitSet","group":"55555671.2d14","order":2,"width":0,"height":0,"passthru":false,"label":"Alza il Bit","tooltip":"","color":"","bgcolor":"","icon":"","payload":"true","payloadType":"bool","topic":"BitSet","x":410,"y":468,"wires":[["d235ab78.64466"]]},{"id":"ef158df8.ebe1d","type":"ui_button","z":"24c3208f.07b0f8","name":"BitReset","group":"55555671.2d14","order":2,"width":0,"height":0,"passthru":false,"label":"Abbassa il Bit","tooltip":"","color":"","bgcolor":"","icon":"","payload":"true","payloadType":"bool","topic":"BitReset","x":402,"y":504,"wires":[["d235ab78.64466"]]},{"id":"b1ef07b9.1a414","type":"function","z":"24c3208f.07b0f8","name":"","func":"msg.topic = \"read\"\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":366,"y":396,"wires":[["d235ab78.64466"]]},{"id":"5174aa49.7fd86c","type":"debug","z":"24c3208f.07b0f8","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":646,"y":306,"wires":[]},{"id":"8f9449aa.d5ed78","type":"debug","z":"24c3208f.07b0f8","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":646,"y":270,"wires":[]},{"id":"cc4776e5.82b14","type":"debug","z":"24c3208f.07b0f8","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":808,"y":486,"wires":[]},{"id":"341b16ee.e3dffa","type":"modbus-client","z":"","name":"m251@192.168.1.14","clienttype":"tcp","bufferCommands":true,"stateLogEnabled":false,"queueLogEnabled":false,"tcpHost":"192.168.1.14","tcpPort":"502","tcpType":"DEFAULT","serialPort":"/dev/ttyUSB","serialType":"RTU-BUFFERD","serialBaudrate":"9600","serialDatabits":"8","serialStopbits":"1","serialParity":"none","serialConnectionDelay":"100","unit_id":"1","commandDelay":"1","clientTimeout":"1000","reconnectOnTimeout":true,"reconnectTimeout":"2000","parallelUnitIdsAllowed":true},{"id":"55555671.2d14","type":"ui_group","name":"Group 1","tab":"fcf634.204631d","order":1,"disp":true,"width":6},{"id":"fcf634.204631d","type":"ui_tab","z":"","name":"TEST1","icon":"dashboard","order":3,"disabled":false,"hidden":false}]
As now it works if i put numbers manually in the functions, but when I try to send values from the buttons or the number input, it doesn't work (the detalis are in the flow).
Also, it continuosly writing because it is linked to the reading node, and I have to pass the entire word, as now I can't send the word just once
I'm new to node-red, and as I said maybe I'm not already able to understand properly how to pass information throgh the varius nodes.
Maybe you can help!
Aha! .. only after your last posts did it 'register' with me that you were sending decimals to holding registers to control the DO.
I made some modifications to the flow to reflect that .. i dont have time now to expand but there are some comments between the function code.
Try the following :
[{"id":"7ed14e5.f2503b","type":"modbus-flex-write","z":"ddb94f08.dac8a8","name":"","showStatusActivities":false,"showErrors":false,"server":"28c906aa.79aae2","emptyMsgOnFail":false,"keepMsgProperties":false,"x":830,"y":420,"wires":[["30459f25.0f9838"],[]]},{"id":"a590b4c1.0f80e","type":"inject","z":"ddb94f08.dac8a8","name":"","props":[{"p":"payload"},{"p":"coil","v":"0","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"1","payloadType":"str","x":310,"y":320,"wires":[["ebde8026.c14da8"]]},{"id":"30459f25.0f9838","type":"debug","z":"ddb94f08.dac8a8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1070,"y":400,"wires":[]},{"id":"ebde8026.c14da8","type":"function","z":"ddb94f08.dac8a8","name":"FC6","func":"// get current status array\nlet deviceStatus = flow.get(\"deviceStatus\"); \n\n// what coil to update .. must be sent in msg.coil as a number \nlet coil = msg.coil;\n\n// make string to array\ndeviceStatus = deviceStatus.split('');\n\n// update x coil status in array based on payload 0 or 1\ndeviceStatus[coil] = msg.payload;\n// make it to a string AGAIN !!!\ndeviceStatus = deviceStatus.join('');\n\n// update status for Context so node-red will know the status\nflow.set(\"deviceStatus\", deviceStatus); \n\n\n// make the string to a decimal\nlet dec = parseInt(deviceStatus, 2)\n\n\n// prepare msg for Modbus flex write\nmsg.payload = {\n value: dec, \n 'fc': 6, \n 'unitid': 1, \n 'address': 0,\n 'quantity': 1 \n}; \n\n // send msg to Modbus flex write\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":610,"y":420,"wires":[["7ed14e5.f2503b"]]},{"id":"ef4575de.037b28","type":"comment","z":"ddb94f08.dac8a8","name":"Update Context and Prepare Write","info":"","x":760,"y":320,"wires":[]},{"id":"3237f347.ed54b4","type":"inject","z":"ddb94f08.dac8a8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":"3","topic":"","payload":"trigger","payloadType":"str","x":190,"y":140,"wires":[["4b202f6f.f4938"]]},{"id":"eb0f70eb.9b4c4","type":"debug","z":"ddb94f08.dac8a8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1070,"y":140,"wires":[]},{"id":"4b202f6f.f4938","type":"function","z":"ddb94f08.dac8a8","name":"FC03","func":"msg.payload = { \n // value: msg.payload, \n 'fc': 3, \n 'unitid': 1, \n 'address': 0,\n 'quantity': 1 \n} \nreturn msg\n","outputs":1,"noerr":0,"initialize":"","finalize":"","x":370,"y":140,"wires":[["1d12e1bf.a40bbe"]]},{"id":"1d12e1bf.a40bbe","type":"modbus-flex-getter","z":"ddb94f08.dac8a8","name":"","showStatusActivities":false,"showErrors":false,"logIOActivities":false,"server":"28c906aa.79aae2","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":false,"keepMsgProperties":false,"x":620,"y":140,"wires":[["e471c7d9.aab7c"],[]]},{"id":"e471c7d9.aab7c","type":"function","z":"ddb94f08.dac8a8","name":"","func":"\n// convert to binary string and add leading zeros\nlet deviceStatus = msg.payload[0].toString(2).padStart(16, '0');\n\n// set Node-red context in memory so node-red can access the status\nflow.set('deviceStatus', deviceStatus)\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":840,"y":140,"wires":[["eb0f70eb.9b4c4"]]},{"id":"5818ac8a.bccd24","type":"inject","z":"ddb94f08.dac8a8","name":"","props":[{"p":"payload"},{"p":"coil","v":"0","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"0","payloadType":"str","x":310,"y":380,"wires":[["ebde8026.c14da8"]]},{"id":"5eac710f.091238","type":"comment","z":"ddb94f08.dac8a8","name":"Initial Read","info":"","x":340,"y":80,"wires":[]},{"id":"25f887fd.782f48","type":"comment","z":"ddb94f08.dac8a8","name":"Set Context","info":"","x":850,"y":80,"wires":[]},{"id":"a55a5106.4402b","type":"comment","z":"ddb94f08.dac8a8","name":"0","info":"","x":150,"y":360,"wires":[]},{"id":"d2c7c90d.c7ad5","type":"inject","z":"ddb94f08.dac8a8","name":"","props":[{"p":"payload"},{"p":"coil","v":"1","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"1","payloadType":"str","x":310,"y":460,"wires":[["ebde8026.c14da8"]]},{"id":"b8d89b7e.10ab6","type":"inject","z":"ddb94f08.dac8a8","name":"","props":[{"p":"payload"},{"p":"coil","v":"1","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"0","payloadType":"str","x":310,"y":520,"wires":[["ebde8026.c14da8"]]},{"id":"70365c01.0a213c","type":"comment","z":"ddb94f08.dac8a8","name":"1","info":"","x":150,"y":500,"wires":[]},{"id":"64793635.7d5c4","type":"inject","z":"ddb94f08.dac8a8","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":200,"y":720,"wires":[["5ab93fcf.bff26"]]},{"id":"5ab93fcf.bff26","type":"function","z":"ddb94f08.dac8a8","name":"","func":"//get current status from memory\nlet deviceStatus = flow.get(\"deviceStatus\") \n\nlet dec = parseInt(deviceStatus, 2);\n\nmsg.deviceStatus = deviceStatus;\nmsg.dec = dec;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":460,"y":720,"wires":[["de14584b.b0e298"]]},{"id":"de14584b.b0e298","type":"debug","z":"ddb94f08.dac8a8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":690,"y":720,"wires":[]},{"id":"c011668.3824818","type":"comment","z":"ddb94f08.dac8a8","name":"test read - binary to decimal","info":"","x":480,"y":660,"wires":[]},{"id":"28c906aa.79aae2","type":"modbus-client","z":"","name":"TCP1","clienttype":"tcp","bufferCommands":true,"stateLogEnabled":false,"queueLogEnabled":false,"tcpHost":"192.168.1.66","tcpPort":"502","tcpType":"TPC-RTU-BUFFERED","serialPort":"/dev/ttyUSB","serialType":"RTU-BUFFERD","serialBaudrate":"9600","serialDatabits":"8","serialStopbits":"1","serialParity":"none","serialConnectionDelay":"100","unit_id":"1","commandDelay":"200","clientTimeout":"1000","reconnectOnTimeout":true,"reconnectTimeout":"2000","parallelUnitIdsAllowed":true}]
ps. the order of the binary may be wrong, in that case it may need to be reversed.
If you are new to Node-red there is a very good video playlist that goes throught the manipulation of messages here