Author Topic: Data Subscriber Question  (Read 12717 times)

cws

  • Newbie
  • *
  • Posts: 16
    • View Profile
Data Subscriber Question
« on: November 05, 2013, 10:13:18 AM »
I'm using version 3.5.9.  If I add several Data Subscribers using code that looks something like:

For i = 1 To 8
mobjDataSubscribers(DataSubscriberCount) = New MfgControl.AdvancedHMI.DataSubscriber
         mobjDataSubscribers(DataSubscriberCount).CommComponent = EthernetIPforCLXCom1
         mobjDataSubscribers(DataSubscriberCount).SynchronizingObject = Me
         mobjDataSubscribers(DataSubscriberCount).PLCAddressValue = "AndOn_Call_Sta." & i.ToString   '(i + 1).ToString("D2")
         AddHandler mobjDataSubscribers(DataSubscriberCount).DataChanged, AddressOf DataSubscriber_DataChanged
         DataSubscriberCount += 1
      Next

cws

  • Newbie
  • *
  • Posts: 16
    • View Profile
Re: Data Subscriber Question
« Reply #1 on: November 05, 2013, 10:32:05 AM »
Sorry, didn't finish writing question before it posted.

Hi,

I'm using version 3.5.9.  If I add several Data Subscribers using code that looks something like:

For i = 1 To 8
    mobjDataSubscribers(DataSubscriberCount) = New MfgControl.AdvancedHMI.DataSubscriber
    mobjDataSubscribers(DataSubscriberCount).CommComponent = EthernetIPforCLXCom1
    mobjDataSubscribers(DataSubscriberCount).SynchronizingObject = Me
    mobjDataSubscribers(DataSubscriberCount).PLCAddressValue = "AndOn_Call_Sta." & i.ToString   '(i + 1).ToString("D2")
    AddHandler mobjDataSubscribers(DataSubscriberCount).DataChanged, AddressOf DataSubscriber_DataChanged
    DataSubscriberCount += 1
Next

The DataSubscriber_DataChanged event seems to fire twice for each change when a button is pressed.  I'm logging info to a file and doing Debug.Print and the data looks like:

PLCAddress: AndOn_Line_Stop_Sta.6 - True 11/05/2013 10:05:03 AM
PLCAddress: AndOn_Line_Stop_Sta.6 - True 11/05/2013 10:05:03 AM
PLCAddress: CONV_T2.S_RUN - False 11/05/2013 10:05:04 AM
PLCAddress: CONV_T2.S_RUN - False 11/05/2013 10:05:05 AM
PLCAddress: AndOn_Call_Sta.6 - True 11/05/2013 10:05:06 AM
PLCAddress: AndOn_Call_Sta.6 - True 11/05/2013 10:05:06 AM
PLCAddress: AndOn_Line_Stop_Sta.6 - False 11/05/2013 10:05:08 AM
PLCAddress: AndOn_Line_Stop_Sta.6 - False 11/05/2013 10:05:08 AM
PLCAddress: AndOn_Call_Sta.6 - False 11/05/2013 10:05:10 AM
PLCAddress: AndOn_Call_Sta.6 - False 11/05/2013 10:05:10 AM
PLCAddress: CONV_T2.S_RUN - True 11/05/2013 10:05:16 AM
PLCAddress: CONV_T2.S_RUN - True 11/05/2013 10:05:17 AM

When I walk through the code, it looks like the DataSubscriber_DataChanged gets fired twice for each change.

I'm I doing something wrong on my side? 

I'm watching 3 sets of data (3 x 12) and using the same DataSubscriber_DataChanged event for all of them and just distinguishing the different sets by looking at the e.PlcAddress property.  Should I be using different DataSubscriber_DataChanged events for each set?

Also, when subscribing to data, what are the pros/cons for using MfgControl.AdvancedHMI.DataSubscriber like above versus doing something like:

SubscriptionID = EthernetIPforCLXCom1.Subscribe("Program:MainProgram.E_Stop_PB[1])", 1, 14, AddressOf SubscribedDataReturned)

Is it just having to keep track of SubscriptionID's and doing "EthernetIPforCLXCom1.UnSubscribe(SubscriptionID)" in the Form Closing event?

Thanks,
Chris

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5322
    • View Profile
    • AdvancedHMI
Re: Data Subscriber Question
« Reply #2 on: November 05, 2013, 10:52:28 AM »
I will test this to see why it is firing twice.

Using the Subscribe method is more efficient  than using the DataSubscriber component. The component was created to give a control that can be pulled from the Toolbox onto the form to make it easier for non-programmers.

cws

  • Newbie
  • *
  • Posts: 16
    • View Profile
Re: Data Subscriber Question
« Reply #3 on: November 05, 2013, 12:11:15 PM »
Thanks for the fast reply Archie...

If I try to subscribe using something like:

SubscriptionID = EthernetIPforCLXCom1.Subscribe("Program:MainProgram.E_Stop_PB[1])", 1, 1000, AddressOf SubscribedDataReturned)

The SubscribedDataReturned continuously fires at the poll rate instead of when the data changes?  Is that right?  And I need to unsubscribe each one when the form closes?  Is there a public subscriber list to loop through or do I have to manage that?

Thanks,
Chris

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5322
    • View Profile
    • AdvancedHMI
Re: Data Subscriber Question
« Reply #4 on: November 05, 2013, 12:38:48 PM »
You will need to save all of the Subscription IDs and use them to unsubscribe when the form closes.

That event fires every time data comes back form the PLC, so you will have to write some code to only process when the value changes.

You can also point all of your subscriptions to the same event handler and use the e object to see what the PLC address is that the value came from.

cws

  • Newbie
  • *
  • Posts: 16
    • View Profile
Re: Data Subscriber Question
« Reply #5 on: November 05, 2013, 01:29:57 PM »
You mentioned previously that using EthernetIPforCLXCom1.Subscribe was more efficient than using the DataSubscriber component but it seems I have to write a lot more code dealing with tracking the data returned to see when the values really changed, keeping track of subscription id's and then having to unsubscribe them.  It seems a lot easier to use the other component since a lot of that complexity is taken care of for you.  Other than having the issue with the event fire multiple times, is there a compelling reason to not use that one?

Thanks,
Chris

cws

  • Newbie
  • *
  • Posts: 16
    • View Profile
Re: Data Subscriber Question
« Reply #6 on: November 05, 2013, 01:42:03 PM »
Also, if I have to manage all of that information, should I just use the read method on a timer every 1 second like this?

values1 = EthernetIPforCLXCom1.Read("EStop_1501.O1", 1)

I know these are probably very basic questions, but it's still not clear to me when to use what methods in the software.

Thanks,
Chris

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5322
    • View Profile
    • AdvancedHMI
Re: Data Subscriber Question
« Reply #7 on: November 05, 2013, 02:14:41 PM »
The Read method is a synchronous read, so it will tie up the UI thread until the data comes back. If you do a lot of Reads, it will begin to make the interface less responsive and even potentially appear to be locked up

Subscriptions run on a background thread and get optimized by the driver. For instance, if you subscribe to MyTag[0] and MyTag[1], the driver will read both with a single packet to make the update faster.

To summarize the 3 data retreive methods:

Synchronous Reads - very easy to do in code, but tie up the UI thread
AsynchronousReads - a little more involved to code, but does not tie up UI thread
Subscriptions - the most involved to write code for, but run asynchronously on a background thread and automatically groups multiple subscriptions into single reads

ENA

  • Newbie
  • *
  • Posts: 26
    • View Profile
    • ENA
Re: Data Subscriber Question
« Reply #8 on: December 02, 2013, 02:55:18 AM »
I have a similar problem with double firing of event. I use data subscribers to log an event in excel file, when data subscriber data changes. My code is:

Code: [Select]
Private Sub DS_NZS_DataChanged(sender As Object, e As Drivers.Common.PlcComEventArgs) Handles DS_NZS.DataChanged
        Pump_general_error_handler()
        If DS_NZS.Value = True Then
            '**************************************************************************************************
            'write data to Excel file
            GlobalVariables.oSheet_file2.Range("A" + CStr(GlobalVariables.CellIndexRow_file2)).Value = GlobalVariables.CellIndexRow_file2 - 1
            GlobalVariables.oSheet_file2.Range("B" + CStr(GlobalVariables.CellIndexRow_file2)).Value = DateString
            GlobalVariables.oSheet_file2.Range("C" + CStr(GlobalVariables.CellIndexRow_file2)).Value = TimeOfDay()
            GlobalVariables.oSheet_file2.Range("D" + CStr(GlobalVariables.CellIndexRow_file2)).Value = "ALARM Pump low level"
            GlobalVariables.oSheet_file2.Range("E" + CStr(GlobalVariables.CellIndexRow_file2)).Value = "Pumping station 1"
            GlobalVariables.oSheet_file2.Range("F" + CStr(GlobalVariables.CellIndexRow_file2)).Value = "General"
            'increase row pointer in Excel
            GlobalVariables.CellIndexRow_file2 = GlobalVariables.CellIndexRow_file2 + 1
            'save changes
            GlobalVariables.oBook_file2.Save()
            '**************************************************************************************************
        End If
    End Sub

Pump_general_error_handler() is a function call that handles a basic indicator color change, not really relevant to this issue.

When my PLC input goes high (the Value condition is True) the code exports and stores event in excel. Problem is, for every event I get two entries in file (see picture).

EDIT: I have a similar function for power supply changes.

DougLyons

  • Jr. Member
  • **
  • Posts: 68
    • View Profile
Re: Data Subscriber Question
« Reply #9 on: September 10, 2014, 05:45:14 AM »
Hello,
I am new here and I have seen the same duplication with the EthernetIPforCLXCom driver.

The solution that seems to work for me is to change the code in the Component named DataSubscriber.vb
Here is where to look for this item:


Just add the four lines noted below or just replace the complete code with this.

Code: [Select]
‘DataSubscriber.vb Component
Protected Overridable Sub OnDataChanged(ByVal e As MfgControl.AdvancedHMI.Drivers.Common.PlcComEventArgs)
    Static Dim Old As String                    ' Added
    If m_SynchronizingObject Is Nothing Then
        RaiseEvent DataChanged(Me, e)
    Else
        If DirectCast(m_SynchronizingObject, Control).IsHandleCreated Then
            Dim Parameters() As Object = {Me, e}
            If Old <> Me.Value Then             ' Added
                SynchronizingObject.BeginInvoke(dcsd, Parameters)
                Old = Me.Value                  ' Added
            End If                              ' Added
        End If
    End If
End Sub

This may not be the best way to handle this, but it did work for me.
Note: I am not sure how to embed images here and I have tried to attach the image as well.
Also, I know that I have not followed the normal naming conventions, so feel free to change the new variable name.

Thanks Archie for your great work.

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5322
    • View Profile
    • AdvancedHMI
Re: Data Subscriber Question
« Reply #10 on: September 10, 2014, 07:34:31 AM »
The code that checks to see if the value has changed is in the PolledDataReturnedValue event handler.

I tried the DataSubcriber with Version 3.70 and the DF1Com driver by putting a BasicLabel on the form and setting the PLCAddressKeypad to N7:0, just to allow me to easily change the value in the PLC.

I then added a DataSubscriber, set the PLCAddressValue to N7:0. Double clicked the DataSubscriber to get to the DataChanged event handler and added the code:

MsgBox "N7:=" & e.values(0)

Every time I click on the BasicLabel and changed the value, a message box pops up indicating the value changed through the DataSubscriber

ENA

  • Newbie
  • *
  • Posts: 26
    • View Profile
    • ENA
Re: Data Subscriber Question
« Reply #11 on: September 12, 2014, 09:02:51 AM »
Hello again.

I'm using data subscriber to read data from Micrologix 1400 using ethernet driver. However, when network cable between Micrologix and PC is physically disconnected, application generates the following error (please see screenshot). You can also see the line, when error is generated. Data subscriber reads an integer from N100 file, which is then processed bit by bit.

Does anyone have suggestion how to resolve this issue?

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5322
    • View Profile
    • AdvancedHMI
Re: Data Subscriber Question
« Reply #12 on: September 12, 2014, 12:58:04 PM »
See if this code works for you:
Code: [Select]
        Try
            Dim Result As Integer
            If Integer.TryParse(e.Values(0), Result) Then
                GlobalVariables.cs_tel = ((Result And 1) > 0)
            Else()
                MsgBox("Error in value " & v)
            End If
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try

DougLyons

  • Jr. Member
  • **
  • Posts: 68
    • View Profile
Re: Data Subscriber Question
« Reply #13 on: September 13, 2014, 02:33:42 PM »
Hello,

Regarding the duplication of data on a DataSubscriber_DataChanged event, I have done more testing.
Note that I am using Visual Studio Express 2013 with Update 3 and Patch KB2932965 (Sept. 8, 2014).
I downloaded a new version 3.70 and unzipped it to a new solution directory.
Then I added a new DF1Comm driver and added the components as you noted above.
When I changed the value using the BasicLabel, I got two Message Boxes instead of only one.
Could this be a result of the poll rate being 500 mSec?

I saw that you noted that the value change testing is done in the PolledDataReturnedValue event handler.
I went to this routine and did some testing and found that changing one statement fixes this for me.
The statement "LastValue = m_Value" can be changed to "LastValue = e.Values(0)" and now I get no duplications.
This might affect other things adversely so I was hoping that you might provide your knowledge on this here.

I am very impressed with the speed that you responded previously.
It took me a while to get set up with the SLC-5/05 to test your suggestions or I would have responded sooner.
I had been using a ControlLogix L63 and the EthernetIPforCLXCom driver previously.

Thanks again Archie for such a wonderful program.

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5322
    • View Profile
    • AdvancedHMI
Re: Data Subscriber Question
« Reply #14 on: September 13, 2014, 05:38:12 PM »
I saw that you noted that the value change testing is done in the PolledDataReturnedValue event handler.
I went to this routine and did some testing and found that changing one statement fixes this for me.
The statement "LastValue = m_Value" can be changed to "LastValue = e.Values(0)" and now I get no duplications.
This might affect other things adversely so I was hoping that you might provide your knowledge on this here.
As I was looking at the DataSubscriber code the other day, I did notice this and correct it. However I did not think of it being the cause of the event firing twice. This has been a long running problem that may now be fixed.