AdvancedHMI Software
General Category => Support Questions => Topic started by: Andrew.Lenzo on June 18, 2019, 04:30:58 PM
-
Hello,
I have a class called "Signal" setup as follows.
Public Class Signal 'class with properties of signal. Links ModbusTCP/IP driver to memory bit adresses for power and color
Dim _Connection As AdvancedHMIDrivers.ModbusTCPCom
Dim _PWRaddress As String 'memory bit address of power control relay
Dim _CLRaddress As String 'memory bit address of color control relay
Public Property Connection() As AdvancedHMIDrivers.ModbusTCPCom
Get
Return _Connection
End Get
Set(value As AdvancedHMIDrivers.ModbusTCPCom)
_Connection = value
End Set
End Property
Public Property PWRaddress As String
Get
Return _PWRaddress
End Get
Set(value As String)
_PWRaddress = value
End Set
End Property
Public Property CLRaddress As String
Get
Return _CLRaddress
End Get
Set(value As String)
_CLRaddress = value
End Set
End Property
Public Sub WriteCLR(ByVal WriteValue As Integer)
_Connection.Write(_CLRaddress, WriteValue) 'writes to signals color address
End Sub
Public Sub WritePWR(ByVal WriteValue As Integer)
_Connection.Write(PWRaddress, WriteValue) 'writes to signals power address
End Sub
End Class
I have initialized 40 "signals" on load in the main form as "signal1", "signal2", etc. I then added these signals to various object arrays which groups them together and allows me to write to that group using a single button click by looping through all of the signals in that groups array. This works fine except when connection is lost to one of the ModbusTCP drivers. If I disconnect one of the PLCs, the program seems to freeze as it trys to connect to the PLC for every signal in the array.
I am wondering if there is a way to access the status of the Modbus connection and move on the the next object in the array if it is not active or not able to ping that PLC. Any help would be greatly appreciated.
Thanks,
Andrew
-
The Write function is synchronous, so it will hold your code until either a response or a timeout.
You need to either run it on a background thread or use BeginWrite. With BeginWrite it is up to you to ensure you do not flood the buffer.
-
Thank you for your reply Archie. I've never done asynchronous programming before so this may be a good opportunity to learn! Seems simple enough but I'm still trying to get my head around whats happening when I am creating tasks and how to pass info to them. Also, can I create the tasks/threads in my object method or do I need to do that when the main form calls it?
I noticed that there is a function that returns a Boolean called IsSubscriptionActive(). Would it be possible to test the ModbusTCP connection before calling the write function using this? something like
if ModbusTCPCOM1.IsSubscriptionActive()
ModbusTCPCOM1.Write(...)
else
MSGBox("Com1 is not active")
end if
-
The IsSubscriptionActive method is used to determine if a subscribed item still exists or has it been unsubscribed.
Keep in mind if a PLC disconnects the only way to know is by sending a request wand waiting for timeout. The same applies with connection. TCP does not give a disconnection event unless the device is gracefully disconnecting.
Your best chance is using ConnectionEstablish, ConnectionClosed, and ComError events.
if you use BeginWrite, it will not hold up your code and if it is unsuccessful it will fire the ComError event.
-
Thanks this is very informative! I have resolved the freezing issues by running on background threads. It took a lot of googling but it turns out I just needed to use the threadpool and a lambda statements in the "signal" write methods as shown below. I still see a delay a reaction from the hardware as the background threads do their thing but the Main Form doesn't freeze which is fine for this project.
Public Sub WriteCLR(ByVal WriteValue As Integer)
System.Threading.ThreadPool.QueueUserWorkItem(Sub() _Connection.Write(_CLRaddress, WriteValue)) 'writes to signals color address
End Sub
Public Sub WritePWR(ByVal WriteValue As Integer)
System.Threading.ThreadPool.QueueUserWorkItem(Sub() _Connection.Write(PWRaddress, WriteValue)) 'writes to signals power address
End Sub
My next task is to add a network connection diagram to the HMI which will involve changing the color of some lines based on the connection status of the PLCs. It sounds like the ConnectionEstablished, ConnectionClosed, and ComError events may be exactly what I need to do that.
Thanks Archie!