Author Topic: BasicButton - Multi Address/Value Write  (Read 11736 times)

Godra

  • Hero Member
  • *****
  • Posts: 1447
    • View Profile
BasicButton - Multi Address/Value Write
« on: October 29, 2016, 07:40:57 PM »
The attached control is a modified BasicButton control.

It was created to support writing multiple values to multiple addresses with a single click of the button. This could be useful for presets (zeroing or setting identical value to bunch of PLC addresses) or repetitive writes. Multiple buttons can be used to point to the same PLCAddresses but write different values.

The following would be a representation of how the control could be used:

     Single Address       -    Single Value to write to this address
     Single Address       -    Multiple Values to write to the range starting with this address
     Multiple Addresses  -    Single Value to write to each address
     Multiple Addresses  -    Multiple Values to write to each range starting with each address

The button's property PLCAddressClickItems holds PLCAddresses (it has replaced PLCAddressClick property but provides the same functionality if single address is used). Each item independently allows for ScaleFactor and ScaleOffset values.

The button's property ValueToWrite holds values (which is array of strings). It represents NumberOfElements that will be written with the driver's BeginWrite function.

There is a new property ValueToWriteType which defines whether ScaleFactor and ScaleOffset are applied to the value before it is written to the destination address. NumericType writes scaled numeric values and StringType just writes the string as it is. The string doesn't have to be numerical but then its destination has to be able to accept string <-- the example could be AB ST9:x addresses. Writing strings with Modbus is not implemented since it is quite complex to integrate into this control (at the end of this post, there is an example of how to go about writing/reading a string value with Modbus). <-- Modbus String writing for this button control might work properly in v3.99y+ since Archie implemented that functionality into drivers

For this all to work, the button's OtputType property has to be set to WriteValue.
Any other setting will still use defined PLCAddresses but will be using True/False values only, as intended.

If you need to use the code to receive values then you might try using this control's ClickItemsDataReturned event. Here is a code example for Modbus, knowing that F40001 and F40011 addresses were subscribed to, with 2 elements each:

Code: [Select]
    Private Sub BasicButtonMulti1_ClickItemsDataReturned(sender As Object, e As AdvancedHMIControls.SubscriptionHandlerEventArgs) Handles BasicButtonMulti1.ClickItemsDataReturned
        If e.PLCComEventArgs.PlcAddress.Equals("F40001") Then
            Label2.Text = e.PLCComEventArgs.Values(0)
            Label3.Text = e.PLCComEventArgs.Values(1)
        ElseIf e.PLCComEventArgs.PlcAddress.Equals("F40011") Then
            Label4.Text = e.PLCComEventArgs.Values(0)
            Label5.Text = e.PLCComEventArgs.Values(1)
        End If
    End Sub

You could as well try using the drivers DataReceived event.

Try to understand all of the above before attempting to use the control.

The control was tested to a degree with MODRSSim simulator and RSLogix Emulate 500. It might have bugs and is offered AS IS.

----------------- M O D B U S ------------------

Here is a possible way of writing a string (str) with Modbus by using the BeginWrite function of the driver inside some sub (maybe a Click event of a button named btnWrite):

Code: [Select]

    Private str As String = "123abc"

... Some Sub ...

    'Format to write is: startAddress As String, numberOfElements As Integer, dataToWrite() As String
    ModbusTCPCom1.BeginWrite("40061", str.Length, ConvertStringToStringOfIntegers(str))

... Some Sub ...

    Private Function ConvertStringToStringOfIntegers(ByVal str As String) As String()
        '* Convert string to an array of bytes
        Dim ByteArray(str.Length - 1) As Byte
        ByteArray = System.Text.Encoding.Default.GetBytes(str)

        '* Convert each byte to integer and then convert this integer to its string representation and store it in the string array
        Dim ints(ByteArray.Length - 1) As String
        For i = 0 To ByteArray.Length - 1
            ints(i) = CStr(CInt(ByteArray(i)))
        Next

        '* Return the string array
        Return ints
    End Function

Holding registers, 4xxxx addresses, should be used to store a string as an array of integers.

In order to read the string, this exact array of integers has to be read and converted back to string inside some sub (maybe a Click event of a button named btnRead), and the string could be shown on some standard label:

Code: [Select]
... Some Sub ...

    'For example, we could initiate the read and then use DataReceived event of the driver
    'Format to read is: startAddress As String, numberOfElements As Integer
    ModbusTCPCom1.BeginRead("40061", str.Length)

... Some Sub ...

    Private Sub ModbusTCPCom1_DataReceived(sender As Object, e As Drivers.Common.PlcComEventArgs) Handles ModbusTCPCom1.DataReceived
        If e.PlcAddress.Equals("40061") Then
            Dim ints(e.Values.Count - 1) As String
            For i = 0 To e.Values.Count - 1
                ints(i) = e.Values(i)
            Next
            Label6.Text = ConvertStringOfIntegersToString(ints)
        End If
    End Sub

    Private Function ConvertStringOfIntegersToString(ByVal ints() As String) As String
        '* Convert integer values to strings and then to an array of bytes
        Dim ByteArray(ints.Length - 1) As Byte
        For i = 0 To ints.Length - 1
            ByteArray(i) = CByte(CStr(ints(i)))
        Next

        '* Convert the array of bytes to a string
        Dim result As String
        result = System.Text.Encoding.UTF8.GetString(ByteArray)

        'Return the string
        Return result
    End Function

Archie already explained some of this here: https://www.advancedhmi.com/forum/index.php?topic=1301.msg6918#msg6918

I slightly modified his code.
« Last Edit: July 02, 2019, 01:00:05 AM by Godra »

Godra

  • Hero Member
  • *****
  • Posts: 1447
    • View Profile
Re: BasicButton - Multi Address/Value Write
« Reply #1 on: April 12, 2020, 02:26:33 AM »
A new feature was added and this newly modified control is attached in this post.

The new WriteValuesIndividually property will, when set to true, write each value from the ValueToWrite collection to its respective address in the PLCAddressClickItems.

The output type has to be set to WriteValue and the number of the above mentioned items has to match.

The addresses can be from different I/O, a Modbus example could be addresses 00001 and 40001.

« Last Edit: June 28, 2020, 06:37:44 AM by Godra »

ibah

  • Newbie
  • *
  • Posts: 3
    • View Profile
Re: BasicButton - Multi Address/Value Write
« Reply #2 on: June 16, 2021, 03:44:56 AM »
Hi Godra,

Is it true that I cant assign the plc address list & value to be sent to PLC programmatically ?

I tried the following code but I keep getting error something like 'the address & value not match'. It works if I set from the properties.

Dim minFL As New AdvancedHMIControls.ClickItem, maxFL As New AdvancedHMIControls.ClickItem, volFlow As New AdvancedHMIControls.ClickItem
        Dim freqVal As New AdvancedHMIControls.ClickItem
        Dim arrData(4) As String

        'Minimum flowrate
        minFL.PLCAddress = "F40037"
        minFL.ScaleFactor = 0
        minFL.ScaleOffset = 1

        'Max flowrate
        maxFL.PLCAddress = "F40035"
        maxFL.ScaleFactor = 0
        maxFL.ScaleOffset = 1

        'Freq value
        freqVal.PLCAddress = "F40082"
        freqVal.ScaleFactor = 0
        freqVal.ScaleOffset = 1

        'Volume flow
        volFlow.PLCAddress = "40131"
        volFlow.ScaleFactor = 0
        volFlow.ScaleOffset = 1



        rDbg.PLCAddressClickItems.Add(minFL)
        rDbg.PLCAddressClickItems.Add(maxFL)
        rDbg.PLCAddressClickItems.Add(freqVal)
        rDbg.PLCAddressClickItems.Add(volFlow)


        arrData(0) = "2969"
        arrData(1) = "3125"
        arrData(2) = "100"
        arrData(3) = "43.8"

        rDbg.ValueToWrite = arrData
        rDbg.ValueToWriteType = AdvancedHMIControls.BasicButtonMulti.ValType.NumericType

Godra

  • Hero Member
  • *****
  • Posts: 1447
    • View Profile
Re: BasicButton - Multi Address/Value Write
« Reply #3 on: June 16, 2021, 07:30:38 AM »
Your code looks like a mess to me.

The first thing you need to correct is Dim arrData(3) As String, then you have all factors and offsets values reversed and your volume flow address is 40131 but you are assigning a float value of 43.8 to it.
« Last Edit: June 16, 2021, 07:33:19 AM by Godra »

ibah

  • Newbie
  • *
  • Posts: 3
    • View Profile
Re: BasicButton - Multi Address/Value Write
« Reply #4 on: July 08, 2021, 07:52:26 PM »
Hi,

The button's property PLCAddressClickItems holds PLCAddresses (it has replaced PLCAddressClick property but provides the same functionality if single address is used). Each item independently allows for ScaleFactor and ScaleOffset values.

-->
  minFL As New AdvancedHMIControls.ClickItem
        'Minimum flowrate
        minFL.PLCAddress = "F40037"
        minFL.ScaleFactor = 0
        minFL.ScaleOffset = 1
       rDbg.PLCAddressClickItems.Add(minFL)
// rDbg is my button name

The button's property ValueToWrite holds values (which is array of strings). It represents NumberOfElements that will be written with the driver's BeginWrite function.
--->
      Dim arrData(4) As String
      arrData(0) = "2969" // Data for above address
      rDbg.ValueToWrite = arrData


Could you advice which part i'm missing ? Looks like I already follow your notes on your 1st posting.


Godra

  • Hero Member
  • *****
  • Posts: 1447
    • View Profile
Re: BasicButton - Multi Address/Value Write
« Reply #5 on: July 09, 2021, 05:58:42 AM »
You have 4 elements and are declaring array of 5 elements, Dim arrData(4) goes from arrData[0] to arrData[4].

If you are used to using C# then you should read this:

   http://kcwebprogrammers.blogspot.com/2011/01/vb-arrays-vs-c-arrays-in-aspnet.html

You should have used your code and made changes I suggested in my previous post to test it.
« Last Edit: August 11, 2021, 04:02:58 AM by Godra »