Modbus write multiple registers


Recommended Posts

Hi, is it possible to write to multiple holding registers at once, kind of in the same way you can read from multiple registers at the same time?

for example, device.mydevice.readHolding32(Station, starting address, datapoints) where datapoints decides how many registers you read from. Is it possible to achieve a similar thing with the write function, such as passing an array containing all values to be added to each register?

Currently I am having to write "device.mydevice.writeholding32(station, starting address, data) multiple times.

Cheers,

Ben

Link to comment
Share on other sites

You can definitely do it through script.  Just pass an array for data points.  So for example:

device.mydevice.setRegisterS32(1, 100, {1,2,3})

which would set register 100/101 to 1, 102/103 to 2, and 104/105 to 3 (register pairs because of the S32 of course).  Note that it is "Set" not "Write", and is "Register" not "Holding" because Input Registers can't be set, so there is no reason to differentiate on the output side.

Note that with channels, DAQFactory will automatically combine reads of the same type into a minimum number of calls if they are consecutive and the same data type.  It will not fill in blanks, though, so sometimes its best to create dummy channels.  That said, on the output side you cannot do multiple outputs with one query through channels because there is no way to set multiple channels simultaneously.

Link to comment
Share on other sites

  • 2 weeks later...

Hi, thanks for the advice, this works properly now.

However, is there a maximum sized array that can be passed to the datapoints field? I currently have a datapoints array with 32 addresses, but i need to write:

device.myDevice.setRegisterS16(station, starting_address, data[0,16])

device.myDevice.setRegisterS16(station, starting_address, data[17,31])

 

I am unable to simply do device.myDevice.setRegisterS16(station, starting_address, data).

 

Cheers,

Ben

Link to comment
Share on other sites

There is a limit defined in the Modbus spec.  I don't remember off hand what it is, but I think it is 63 bytes of data for RTU, and each register is 2 bytes.  But don't take my word for it on the exact number.  The point is that it is a Modbus limit, not DAQFactory, though DAQFactory enforces it.  Also note that some devices don't support setting of multiple registers.  This is not your case, as it is obviously working with 16 registers.  I simply mention it for others that may have issues trying to set more than one at a time.

 

Link to comment
Share on other sites

  • 4 years later...

I have a similar syntax issue - 

I am trying to update the clock on a mppt solar controller (ID 5 ) (I can read the data  - no issues)

I would like to update the 3 registers (hex 9013-9015 = decimal 36883-36885) with the DAQ time values on start up - see the simple clock sequence below

The documentation appears fairly simple and comprehensive

I was hoping line 8 of the sequence would update the registers - but no luck

thanks in advance

Rodney

 

 

mppt_clock_details.JPG

Clock_Sequence.JPG

Link to comment
Share on other sites

In your case the issue is several fold, and all related to your DAQFactory syntax:

1) you can't put anything but constants inside {}.  Your clock variable is not a constant, and in fact is already a properly formatted array, so you don't even need {}
2) you don't need execute() and you are using it wrong anyway.  Execute() takes a string and executes the contents of the string as if it was a line of script.  You just want to run a line of script so you don't need execute at all.
3) there is no SetRegisterU16, only S16.  This is largely because it doesn't matter.  DAQFactory isn't going to translate from signed to unsigned for an output nor does it need to.  Unless you really want it, I'll save you the long winded explanation why...

In the end you just need:

Device.myModbusDevice.setRegisterS16(5,36883, clock)

 

Link to comment
Share on other sites

Thank you that worked

its been a few years since I have used DAQ and the execute command was copied from a sequence that used a string to generate the line

thanks for the reminder

 

Link to comment
Share on other sites

  • 2 months later...

Is there a way to force DF to use Modbus function code 16 for single register writes? I need to write to a ModbusTCP server that doesn't support function code 6 and is timing out on setRegisterS16 requests. SetRegisterS32RWords works fine.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.