AdvancedHMI Software
General Category => Support Questions => Topic started by: ianfinlay_aus on September 24, 2015, 01:22:29 AM
-
Hi Archie,
I have the following setup (all tags are 40001+ range):
modbusrtucom_1000msec (10 tags)
modbusrtucom_3000msec (2 tags)
modbusrtucom_5000msec (4 tags)
modbusrtucom_DISABLED (16 tags) but with subscriptions disabled
Baud is 115200
I also write to 3 tags every 3 seconds , with a gap of 250msec between them , It is sometimes more frequent if the setpoints are changing (but write loop is limited to 1sec minimum), but in observed tests the setpoints are untouched, therefore only sending writes every 3sec.
I find if I just sit and watch,. when "DLL(MyDLLInstance).SendQueDepth > 10" the driver stops communicating altogether and comes back by itself after about 20-30 seconds, which isn't good as my modbus device stops if the setpoint isnt written to after 5 sec. (I added a method to extract the queue size)
When things are working fine, queue is size 0, but very reliably falls over when queue size starts to grow
Any suggestions?
-
Archie,
To track down and isolate the issue, I decided to simplify and place all tags to use only one instance of the modbusRTU driver
modbuscom_1000msec , and removed the 2 other subscribing instances (3000msec poll rate, 5000 msec poll rate)
and now it works without any loss of comms
I still have modbuscom_DISABLED with disablesubscriptions = true
Hope this helps identify the issue
-
Edit ModbusBase.vb and go to line 216, then change the code to this:
'* WriteFunction code of 0 means it is invalid
If address.WriteFunctionCode > 0 Then
Dim TransactionID As Integer = GetNextTransactionID(32767)
Dim PDU As New MfgControl.AdvancedHMI.Drivers.Modbus.ModbusPDUFrame(address.WriteFunctionCode, address, TransactionID, dataPacket.ToArray)
Requests(TransactionID And 255) = address
Requests(TransactionID And 255).IsWrite = True
Responses(TransactionID And 255) = Nothing
SendRequest(PDU)
'* Make the write synchronous to avoid SendQueFull
Dim result As Integer = WaitForResponse(CUShort(TransactionID))
Return TransactionID
Else
Throw New MfgControl.AdvancedHMI.Drivers.Common.PLCDriverException(-200, "Invalid address to write to")
End If
-
Thanks Archie for your quick reply - appreciated
-
To elaborate more on this change, this changes writes from an asynchronous operation to synchronous. The reason this is necessary would be in a scenario where you have a loop or a series of writes back to back. The code execution is much faster than the communication with the PLC or device. Let's say you have a loop with 20 writes. These code for these writes can be executed on the order of microseconds. A round trip write and response can take in the range of 5-100ms depending on the driver, network, and device. So the code essentially over flows the communication que.
By making the write a synchronous operation, it will not return from the call until the write as been acknowledged from the device. This in turn essentially throttles the writing in code to match the speed of the device communication.
This has been implemented on some of the other drivers quite a while ago, but the Modbus drivers was overlooked until now.
-
This fix is included as part of version 3.99a which is now available for download
-
Thanks Archie,
I notice MaxTicks was removed,
I have swapped out the hardcoded 3000 msec for miRepsonseWait_msec in the three places its used and added :
Private miRepsonseWait_msec As Integer = 3000
#Region "EXTENDED PUBLIC PROPERTIES"
Public Property ResponseWait() As Integer
Get
Return miRepsonseWait_msec
End Get
Set(value As Integer)
'default = 3000 (msec)
miRepsonseWait_msec = value
End Set
End Property
#End Region
in all instance of "... .WaitOne(miRepsonseWait_msec)"