Author Topic: Bit set in integer walk arround - button write to odometer  (Read 2252 times)

halosome

  • Newbie
  • *
  • Posts: 31
    • View Profile
Bit set in integer walk arround - button write to odometer
« 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?

Godra

  • Hero Member
  • *****
  • Posts: 1446
    • View Profile
Re: Bit set in integer walk arround - button write to odometer
« Reply #1 on: September 29, 2019, 05:50:45 PM »
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.

halosome

  • Newbie
  • *
  • Posts: 31
    • View Profile
Re: Bit set in integer walk arround - button write to odometer
« Reply #2 on: September 29, 2019, 06:04:10 PM »
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.

Godra

  • Hero Member
  • *****
  • Posts: 1446
    • View Profile
Re: Bit set in integer walk arround - button write to odometer
« Reply #3 on: September 29, 2019, 07:08:31 PM »
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:

Code: [Select]
    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:

Code: [Select]
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.

« Last Edit: September 29, 2019, 08:13:05 PM by Godra »

halosome

  • Newbie
  • *
  • Posts: 31
    • View Profile
Re: Bit set in integer walk arround - button write to odometer
« Reply #4 on: September 29, 2019, 08:22:57 PM »
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
« Last Edit: September 29, 2019, 08:24:43 PM by halosome »

Godra

  • Hero Member
  • *****
  • Posts: 1446
    • View Profile
Re: Bit set in integer walk arround - button write to odometer
« Reply #5 on: September 29, 2019, 08:30:43 PM »
Cool.

Why don't you just use the driver to write, like this:

Code: [Select]
    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
« Last Edit: September 29, 2019, 08:52:06 PM by Godra »

halosome

  • Newbie
  • *
  • Posts: 31
    • View Profile
Re: Bit set in integer walk arround - button write to odometer
« Reply #6 on: September 29, 2019, 10:25:19 PM »
I was thinking I might save a reading, but your way is more straight forward.