Author Topic: MOdbusRTUCom.vb: when "DLL(MyDLLInstance).SendQueDepth > 10" driver stops  (Read 1464 times)

ianfinlay_aus

  • Newbie
  • *
  • Posts: 21
  • www.earthed.net.au
    • View Profile
    • Earthed Solutions Pty Ltd [Custom Software for Engineering]
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?






« Last Edit: September 24, 2015, 05:45:27 AM by ianfinlay_aus »
Former Citect SCADA Developer, and integrator
now specialist in bespoke\custom engineering software for scientific and automation sectors

ianfinlay_aus

  • Newbie
  • *
  • Posts: 21
  • www.earthed.net.au
    • View Profile
    • Earthed Solutions Pty Ltd [Custom Software for Engineering]
Re: MOdbusRTUCom.vb: when "DLL(MyDLLInstance).SendQueDepth > 10" driver stops
« Reply #1 on: September 24, 2015, 01:37:10 AM »
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
« Last Edit: September 24, 2015, 01:48:10 AM by ianfinlay_aus »
Former Citect SCADA Developer, and integrator
now specialist in bespoke\custom engineering software for scientific and automation sectors

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5262
    • View Profile
    • AdvancedHMI
Re: MOdbusRTUCom.vb: when "DLL(MyDLLInstance).SendQueDepth > 10" driver stops
« Reply #2 on: September 24, 2015, 11:22:02 AM »
Edit ModbusBase.vb and go to line 216, then change the code to this:
Code: [Select]
        '* 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

ianfinlay_aus

  • Newbie
  • *
  • Posts: 21
  • www.earthed.net.au
    • View Profile
    • Earthed Solutions Pty Ltd [Custom Software for Engineering]
Re: MOdbusRTUCom.vb: when "DLL(MyDLLInstance).SendQueDepth > 10" driver stops
« Reply #3 on: September 24, 2015, 07:41:29 PM »
Thanks Archie for your quick reply - appreciated
Former Citect SCADA Developer, and integrator
now specialist in bespoke\custom engineering software for scientific and automation sectors

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5262
    • View Profile
    • AdvancedHMI
Re: MOdbusRTUCom.vb: when "DLL(MyDLLInstance).SendQueDepth > 10" driver stops
« Reply #4 on: September 24, 2015, 08:17:16 PM »
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.

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5262
    • View Profile
    • AdvancedHMI
Re: MOdbusRTUCom.vb: when "DLL(MyDLLInstance).SendQueDepth > 10" driver stops
« Reply #5 on: September 27, 2015, 10:45:19 PM »
This fix is included as part of version 3.99a which is now available for download

ianfinlay_aus

  • Newbie
  • *
  • Posts: 21
  • www.earthed.net.au
    • View Profile
    • Earthed Solutions Pty Ltd [Custom Software for Engineering]
Re: MOdbusRTUCom.vb: when "DLL(MyDLLInstance).SendQueDepth > 10" driver stops
« Reply #6 on: September 27, 2015, 11:41:52 PM »
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 :

Code: [Select]
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)"
Former Citect SCADA Developer, and integrator
now specialist in bespoke\custom engineering software for scientific and automation sectors