AdvancedHMI Software
General Category => Open Discussion => Topic started by: halosome on September 29, 2019, 05:41:10 PM
-
Lets say that we have a odometer, reads/writes to PLC: 40001
is it possible to program a button, the button_click triggers a sub, bit and odometer's value with 00000000001 and send this value to PLC by triggering the odometer write?
-
You should try to explain things a bit better.
The button_click is already a sub.
What is this 00000000001?
Maybe use a step by step approach with more details.
-
Thanks Godra,
I try to click a button and change one bit of the plc:40001, lets say bit 2.
so I create an odometer and the PLCaddress =40001, also PLCaddressKeyboard = 40001; (I can click on it and modify the values but I want to use a button, not with the keypad)
when I click on a button, I will use odometer.value OR 0000010 (bit 2) and somehow send to odometer, and directly trigger the odometer.write.
In this way I can change a bit of PLC:40001, instead of using ModbusTCP function 22, bit mask write. However, I don't know how to write this program.
-
According to this manual, your PLC doesn't support function 22:
https://cdn.automationdirect.com/static/manuals/p2userm/ch6.pdf
You don't seem to have other choice but to code it.
These would be kind of the steps to follow:
- Get the currently displayed odometer value (which seems to be floating point value)
- Convert it to binary
- Change the bit that you want
- Convert the binary back to float value and send it to PLC
Google is your best friend and here is one possibility that might help you partially:
https://www.codeproject.com/Questions/484209/Convertplusfloatplustoplusbinary
And the converted code from Solution 1 would be:
Private Shared Function ToBinaryString(ByVal value As Single) As String
Dim bitCount As Integer
(float * 8)
' never rely on your knowledge of the size
Dim result() As Char = New Char((bitCount) - 1) {}
' better not use string, to avoid ineffective string concatenation repeated in a loop
' now, most important thing: (int)value would be "semantic" cast of the same
' mathematical value (with possible rounding), something we don't want; so:
Dim intValue As Integer = System.BitConverter.ToInt32(BitConverter.GetBytes(value), 0)
Dim bit As Integer = 0
Do While (bit < bitCount)
Dim maskedValue As Integer = (intValue And (1 + bit))
' this is how shift and mask is done.
If (maskedValue > 0) Then
maskedValue = 1
End If
' at this point, masked value is either int 0 or 1
result((bitCount _
- (bit - 1))) = maskedValue.ToString(0)
' bits go right-to-left in usual Western Arabic-based notation
bit = (bit + 1)
Loop
Return New String(result)
' string from character array
End Function
Archie has some conversions already built into the AHMI solution, which are called like this for example:
Dim str As String = MfgControl.AdvancedHMI.Drivers.Common.CalculationsAndConversions.IntToHex(data As Integer)
Dim str As String = MfgControl.AdvancedHMI.Drivers.Common.CalculationsAndConversions.ByteToHex(data As Byte)
Dim bt As Byte = MfgControl.AdvancedHMI.Drivers.Common.CalculationsAndConversions.HexToByte(hexValue As String)
Dim int() As Integer = MfgControl.AdvancedHMI.Drivers.Common.CalculationsAndConversions.StringToIntegers(source As String)
Dim int() As Integer = MfgControl.AdvancedHMI.Drivers.Common.CalculationsAndConversions.StringToWords(source As String)
Dim str As String = MfgControl.AdvancedHMI.Drivers.Common.CalculationsAndConversions.WordsToString(words() As String)
'or this last one as
Dim str As String = MfgControl.AdvancedHMI.Drivers.Common.CalculationsAndConversions.WordsToString(words() As Integer)
For this example, you would replace "data As Integer" / "data As Byte" / "hexValue As String" / "source As String" / "source As String" / words() with your value which must be of Integer / Byte / String / String / String / (Integer() or String()) type respectively.
-
Thanks a lot Godra,
I have got a pretty easy solution. For example I would manipulate the bit 15 of integer PLC:40001.
1) Add a sub to existing odmeter control as the end of the post:
2) Create a hidden odometer1 -> PLC:40001
3) Create a button, in button_click, just call odometer1.setbit(15)
Public Sub SetBit(ByVal b_Num As Integer)
Try
m_ComComponent.Write(m_PLCAddressKeypad, Value Or 2 ^ (b_Num - 1))
Catch ex As Exception
System.Windows.Forms.MessageBox.Show("Failed to write value. " & ex.Message)
End Try
End Sub
-
Cool.
Why don't you just use the driver to write, like this:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Try
Dim b_Num As Integer = 15 'or if dynamically changing then call it from a TextBox, like: Dim b_Num As Integer = TextBox1.Text
Dim Value = Me.ModbusTCPCom1.Read("40001")
Me.ModbusTCPCom1.Write("40001", Value Or 2 ^ (b_Num - 1))
Catch ex As Exception
System.Windows.Forms.MessageBox.Show("Failed to write value. " & ex.Message)
End Try
End Sub
-
I was thinking I might save a reading, but your way is more straight forward.