AdvancedHMI Software
General Category => Feature Request => Topic started by: Darrell on May 09, 2015, 11:40:23 AM
-
I would be nice to have a read button on the keypad , so if you are changing a value you can see what it was prior to changing it , for example changing timer preset it would be nice.
Darrell
-
Here is what I have done.... On the BasicLabel, I added a property KeypadShowCurrentValue. If this property is set to True, then when the keypad pops up, it will have the current value showing.
-
Thanks Archie , this comes in handy especially when changing timer presets
Darrell
-
Archie,
I have tried adding this feature to the KeypadHMI control, by using the following single line of your code:
Me.KeypadPopUp.Value = Me.m_CommComponent.Read(Me.m_PLCAddressKeypad, 1)(0)
In the case of OPC simulator I got an error, which can be seen in the attached screenshot. Prior to using the above line of code, I had created properties which worked fine for initial read but not subsequent ones unless data was changed (noticed that this was marked as TODO by Archie since the event would fire only with data change).
In the case of MicroLogix 1000, the code did work but was reversing values (which can also been seen in the attached screenshots). The driver seems to work fine since BasicLabels did show correct values.
I have also attached the KeypadHMI control file, so if either you or Darrell could test it with some other PLC that would help me troubleshooting this (if not, that's fine as well).
-
In OpcDaCom.vb try adding this line of code as the first line in the Read Function:
If DLL Is Nothing Then CreateDLLInstance()
-
After adding that line the KeypadPopUp did show but followed by another error: Parameter count mismatch (as seen in the attached screenshot).
Some guy in this thread http://stackoverflow.com/questions/3721782/parameter-count-mismatch-with-invoke suggested "array covariance" as cause for the error but I wasn't sure if that was applicable in this case.
I will probably try a different approach and just add a BasicLabel to the control to see if that works.
-
Archie,
Just to let you know that I tried this KeypadHMI control with older AHMI, version 3.97c, and it wasn't reversing values received from MicroLogix 1000.
-
Darrell,
I have attached KeypadHMI control file which shows current value of the PLCAddress being used.
It did work fine reading MicroLogix 1000 in older version of AHMI while it was reversing values in the latest version (it looks like Archie might need to make some small change in the code).
It appears to be working fine with MODBUS (tested with MOD RSSIM simulator).
It also worked fine with OPC driver, connected to Matrikon OPC Simulator, but with slightly modified code (that file is attached as well).
If you ever test it with another PLC let me know if it works fine.
-
Archie,
Related to the "Parameter count mismatch" error mentioned in one of previous posts, here is what is happening when I insert a breakpoint inside AsyncReadCompleteCallback function:
1) The KeypadPopUp shows up with a value of "1" which appears to be "r" created at the end of the Read function that is {TransactionID.ToString}
2) The process reaches the breakpoint and does show the correct value which should be returned (in this case "False")
3) The error pops up after the last line as marked in the attached pictures.
4) I tried changing the line TransactionID += 1 to TransactionID += 2 and then the KeypadPopUp was showing value "2" before showing the error (confirming what is stated in the point 1).
So, all together, using this line of code with OpcDaCom seems to have side effect:
Me.KeypadPopUp.Value = Me.m_CommComponent.Read(Me.m_PLCAddressKeypad, 1)(0)
-
It appears that Read and BeginRead and named backwards. Read should be synchronous and return the value, BeginRead should be asynchronous and return the TransactionID
-
You seem to be correct.
After swapping the very first line of these 2 functions and making small changes at the end of each function, the address reading appears to be working fine.
Here are the new functions so you could check whether those small changes at the end were correct (they do work):
Public Function BeginRead(ByVal startAddress As String, ByVal numberOfElements As Integer) As Integer Implements IComComponent.BeginRead
If DLL Is Nothing Then CreateDLLInstance()
'*********************************************************************
'* If Async Mode, then return immediately and return value on event
'*********************************************************************
If TransactionID < 32767 Then
TransactionID += 1
Else
TransactionID = 0
End If
If ReadSubscriptionState Is Nothing Then
ReadSubscriptionState = New Opc.Da.SubscriptionState
ReadSubscriptionState.Name = "AsyncReadGroup"
ReadSubscription = DLL.CreateSubscription(ReadSubscriptionState)
End If
Dim Items(0) As Opc.Da.Item
Items(0) = New Opc.Da.Item
If (m_OPCTopic IsNot Nothing) AndAlso (String.Compare(m_OPCTopic, "") <> 0) Then
Items(0).ItemName = "[" & m_OPCTopic & "]"
Else
Items(0).ItemName = ""
End If
Items(0).ItemName &= startAddress
If numberOfElements > 1 Then
Items(0).ItemName &= ",L" & numberOfElements
End If
Items(0).SamplingRate = 250
Items(0).ClientHandle = TransactionID
Dim ItemRes() As Opc.Da.ItemResult
ItemRes = ReadSubscription.AddItems(Items)
For i As Integer = 0 To ItemRes.Length - 1
Items(i).ServerHandle = ItemRes(i).ServerHandle
Next
Dim req As Opc.IRequest = Nothing
ReadSubscription.Read(Items, TransactionID, New Opc.Da.ReadCompleteEventHandler(AddressOf AsyncReadCompleteCallback), req)
'Dim r() As String = {TransactionID.ToString}
'Return r
Return TransactionID
End Function
Public Function Read(ByVal startAddress As String, ByVal numberOfElements As Integer) As String() Implements IComComponent.Read
If DLL Is Nothing Then CreateDLLInstance()
Dim items(0) As Opc.Da.Item
items(0) = New Opc.Da.Item
If m_OPCTopic IsNot Nothing AndAlso (String.Compare(OPCTopic, "") <> 0) Then
items(0).ItemName = "[" & m_OPCTopic & "]"
Else
items(0).ItemName = ""
End If
items(0).ItemName &= startAddress
If numberOfElements > 1 Then
items(0).ItemName &= ",L" & numberOfElements
End If
items(0).SamplingRate = 50
items(0).Active = True
Dim values() As Opc.Da.ItemValue
values = DLL.Read(items)
Dim ArraySize As Integer = 0
If TypeOf (values(0).Value) Is System.Array Then
ArraySize = DirectCast(values(0).Value, System.Array).Length - 1
End If
Dim ReturnValues(ArraySize) As String
If ArraySize > 0 Then
For i As Integer = 0 To DirectCast(values(0).Value, System.Array).Length - 1
ReturnValues(i) = Convert.ToString(values(0).Value)
Next
Else
ReturnValues(0) = Convert.ToString(values(0).Value)
End If
'Return Convert.ToInt32(values(0).Value)
Return ReturnValues
End Function
-
I made these changes and they will be part of the next release. Thanks for helping find that
-
You are welcome.
I have attached the KeypadHMI control's latest file that will work with the next version of OpcDaCom driver.
It also includes a few minor corrections so Darrell and anyone else using it, should re-download it.
-
Did notice that with a timer on a micrologix 1400 the accumulated value is shown on the keypad from a timer address t4:5.ACC for instance and the t4:5.PRE also shows the accumulated value and not the preset,
I really like this control , I use it a lot , keep up the good work,
Darrell
-
Darrell,
We discussed reversed values in other topic http://advancedhmi.com/forum/index.php?topic=779.0, and it had nothing to do with the KeypadHMI control.
The second post by Archie on Page1 did provide a solution. See if that works for you.
-
Darrell,
I just edited my previous post (in case if you read it after it was posted then read it again).
-
Thanks I'll check it out