Modbus rtu write single coil to arduino

Hi can someone explain to me how to change the status of the bit of a word by setting the node with the F5, below is the setting I perform
'value': val, (true or false)
'FC': 5, (the function)
'unitid': 2, (slave id)
'address': 5, (the word)
'quantity': 15 (this is not clear to me indicates the length but not the bit) Thanks Mino

Function Code 5 in Modbus is writing one value (true false) to the Digital output of a device

quantity 15 doesnt make sense for FC5 since (if im not mistaken) its only for writing to one Modbus register. So quantity should be 1.

Also why do you need to control the individual bits in a modbus message by just setting the value to true or false. If you use the node-red-contrib-modbus nodes this will be done automatically

Here is a Flow example using Modbus Flex Write

[{"id":"1f1dd1ce5f7783cf","type":"inject","z":"54efb553244c241f","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"true","payloadType":"bool","x":170,"y":2060,"wires":[["ded05e56a629ae32"]]},{"id":"c53a7f543ea117e9","type":"modbus-flex-write","z":"54efb553244c241f","name":"","showStatusActivities":true,"showErrors":true,"showWarnings":true,"server":"571417056c8dd220","emptyMsgOnFail":false,"keepMsgProperties":false,"delayOnStart":false,"startDelayTime":"","x":570,"y":2080,"wires":[[],[]]},{"id":"ded05e56a629ae32","type":"function","z":"54efb553244c241f","name":"modbus","func":"msg.payload = {\n    value: msg.payload,\n    'fc': 5,\n    'unitid': 2,\n    'address': 5,\n    'quantity': 1\n} \n\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":340,"y":2080,"wires":[["c53a7f543ea117e9"]]},{"id":"4a5a5c289b4fa51c","type":"inject","z":"54efb553244c241f","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"false","payloadType":"bool","x":170,"y":2120,"wires":[["ded05e56a629ae32"]]},{"id":"571417056c8dd220","type":"modbus-client","name":"","clienttype":"tcp","bufferCommands":true,"stateLogEnabled":true,"queueLogEnabled":false,"failureLogEnabled":true,"tcpHost":"192.168.0.66","tcpPort":"502","tcpType":"TCP-RTU-BUFFERED","serialPort":"/dev/ttyS1","serialType":"RTU-BUFFERD","serialBaudrate":"19200","serialDatabits":"8","serialStopbits":"1","serialParity":"none","serialConnectionDelay":"100","serialAsciiResponseStartDelimiter":"0x3A","unit_id":"1","commandDelay":"50","clientTimeout":"1000","reconnectOnTimeout":true,"reconnectTimeout":"2000","parallelUnitIdsAllowed":false,"showErrors":true,"showWarnings":true,"showLogs":true}]

I suspect the register is a 16 bit word where each bit maps to an individual binary output on the device, but I don't know much about modbus, and know nothing about the software installed on the Arduino, so that is only a suspicion.

quantity 15 on a word register is strange?!
Do you have the documentation for the register you want to change?

Hello, thank you for the example, but for this simulation I have no problems, more than anything else my problem is how to direct the node on an array, example on an array[10] I want to drive the bits individually of the array[5] from the node I have not found anything on how to drive the bits of the word

If you want an array of length 10 with true, false or 1, 0 values
you can either send the whole array with the correct "elements" set from the beginning OR change the position of an element of an already defined array like in the flow below.

[{"id":"1f1dd1ce5f7783cf","type":"inject","z":"54efb553244c241f","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[0,0,0,0,0,1,0,0,0,0]","payloadType":"json","x":170,"y":2060,"wires":[["ded05e56a629ae32"]]},{"id":"ded05e56a629ae32","type":"function","z":"54efb553244c241f","name":"modbus","func":"msg.payload = {\n    value: msg.payload,\n    'fc': 15,\n    'unitid': 1,\n    'address': 5,\n    'quantity': 10\n} \n\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":400,"y":2080,"wires":[["d0ad6ec9fcf1b3f3"]]},{"id":"4a5a5c289b4fa51c","type":"inject","z":"54efb553244c241f","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[0,0,0,0,0,0,0,0,0,0]","payloadType":"json","x":170,"y":2120,"wires":[["ded05e56a629ae32"]]},{"id":"9b43d8fc36b5a3f5","type":"inject","z":"54efb553244c241f","name":"","props":[{"p":"payload"},{"p":"position","v":"5","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"1","payloadType":"num","x":210,"y":2220,"wires":[["a0070e2a2163aa81"]]},{"id":"8c671c7256d70a52","type":"inject","z":"54efb553244c241f","name":"","props":[{"p":"payload"},{"p":"position","v":"5","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"0","payloadType":"num","x":210,"y":2280,"wires":[["a0070e2a2163aa81"]]},{"id":"a0070e2a2163aa81","type":"function","z":"54efb553244c241f","name":"modbus","func":"let array = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\narray[msg.position] = msg.payload\n\nmsg.payload = {\n    value: array,\n    'fc': 15,\n    'unitid': 1,\n    'address': 5,\n    'quantity': 10\n} \n\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":400,"y":2240,"wires":[["cbb94340e5b51b3b"]]},{"id":"d0ad6ec9fcf1b3f3","type":"debug","z":"54efb553244c241f","name":"debug 68","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":580,"y":2080,"wires":[]},{"id":"cbb94340e5b51b3b","type":"debug","z":"54efb553244c241f","name":"debug 69","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":560,"y":2240,"wires":[]}]

In Modbus you can control Multiple Coils with Function Code 15
With the Modbus Write node and you send an array of true, false or 1, 0 values defining the starting Register address, length (how many registers to write) and device id.

As Colin said, each Modbus register is 16bits but you dont need to craft the modbus message yourself since the Modbus nodes handle that.

Can your Adruino device accept Modbus FC15 ?
What is the end goal ? To control individual PINS on the arduino ?
Maybe each PIN (DO) can be controlled by a separate register (not bit)

I set the relays in this way, I have to drive them via a word and from node red with fc5 I would like to write the single bit that interests me managed by the temperatures of the connected sensor, but I can't understand how to set the node bit.
With fc15 I can set a byte or a word, but this is not my case, because as I mentioned the relays are activated by the temperature sensors, so for example it could be the 1 bit or the 4 and the 7 or just the 5 etc.

Hi .. please read this article that better explains how Modbus works and especially the section where it gives an example of FC5.

How can I send a Modbus RTU command to write discrete output? Command 0x05

This command is used to record one value of the DO digital output.

One value .. meaning in the modbus world .. one register

The value of FF 00 hex sets the output to ON.

FF 00 hex for ON - 2 bytes (16 bits) for 1 register .. no control of how these bits can be except FF 00 according to the FC5 modbus specs.

The value 00 00 hex sets the output to OFF.

00 00 hex for OFF - 2 bytes (16 bits) for 1 register .. no control of how these bits can be except 00 00 according to the FC5 modbus specs.

All other values are invalid and will not be affected by the output value.


If you are the one developing the code on the Arduino i would recommend using FC6 to Write one AO
as an unsigned integer. I have read on this forum of relay boards that use this method instead. For example if you send the value 3 .. write code on the Arduino to translate that into bits
3 => 0000000000000011 .. which in turn can control relays 1 and 2 to ON

hi yes I try with fc6 to write on the arduino only that if I first send 1 for the first bit and then 2 for the second bit the latter resets the first and this is my problem

You must remember the current state of all the bits so you can send the whole word.

Do you have control of the Arduino software? If so then don't do it with multiple bits at one address, use one address for each coil.

Hi Colin, if I understand correctly you advise me from the node to memorize the state of the word before sending a new bit, alternatively to commit a word for each coil on the Arduino, this last option honestly doesn't convince me, for your first option Do you have any examples where we can take inspiration thanks mino

Why not, it is much simpler than saving the current states of all the bits. Why do you not want to do that? What is the disadvantage?

Do you have to use an Arduino? Again it would be lot simpler to use a board with WiFi and use MQTT rather than modbus over serial.

A word per I/O makes much more sense. You don't have to maintain state and other subtle timing issues you will hit while trying to send a full word while state is transitioning. Colin's advise is sound and how I'd recommend and how I have done many times in professional work settin with PLC's & various controllers over 25years.

Good morning, my doubt is that my hardware is made up of wemos d1mini and esp32 connected to a rasberry pi3 with homeassiatant installed, I wanted to avoid using a word for a relay, but I ask you a question so if I have an array [ 5], if I want to set the bits of the [3] index, with fc15 I can send them the word memorizing the previous state, while with fc5 I cannot intervene on the bits of the word with for example 3.1 for the 2 bit or 3.5 for the 6 bit etc . the node does not allow this if so, give me some examples thanks mino

Hang on - i think you are not understanding something here.

On your Wemos D1 mini - are you running a program that you have written - that makes the Wemos into a Modbus device i.e. it knows how to listen to modbus requests. Or do you have a device that is plugged into the WEMOS that is a modbus device ?

I assume English is not your native language - but we need maybe som diagrams to show us exactly what you have hooked up so we can help more directly

Craig

Why?

In that case use WiFi and MQTT, it is much easier than modbus.

Hi I apologize for my English, I use the translator, let's see if I can explain myself better rasberry pi3 with homeassistant installed with node-red addon, essentially reads the temperatures and activates or deactivates the relays, connected to modbus rtu wemos d1mini or esp32

I don't prefer wi fi, with modbusrtu I have already connected a heat pump, I wouldn't want to change. So you recommend using a word for relay, but I found an example with fc5 to point to the bit of the array somewhere part , and feasible on node-red thanks mino

This is the part that does not make sense

A Wemos d1 mini does not natively support Modbus - you have to add an RS485 interface and then load a sketch/firmware that implements a Modbus server to run on the Wemos - is this what you have done ? i.e. running some software on the Wemos that makes it a Modbus Server - or have you (more likely) connected a device that needs works with modbus to the Wemos and are trying to send Modbus commands from the Wemos to the Device ?

Draw a picture and label the components so we can help you

Craig

Hi Craig, I attach the photos of the converters, I connect the USB to RS485 converter to the Raspberry with HomeAssistant installed with node-red addon, I connect the serial to the second TTL to RS485 converter to communicate with the Wemos D1mini configured as slave.... .I attach the photos