Author Topic: Reading lots of data efficiently every half second or so.  (Read 6624 times)

antsrealm

  • Newbie
  • *
  • Posts: 13
    • View Profile
Reading lots of data efficiently every half second or so.
« on: September 02, 2013, 03:33:44 AM »
Archie,

First of all, love the new site !!!

Second of all love the product and where this is heading !!

Thirdly, I have just completed my first deployment of this software in an industrial touch panel for one of my customers and I couldn't be happier with the result! And I have used similar products that have costed $900 USD just for the comms driver!!

Now onto the only thing that's bugging me and hopefully how to fix this up....

I don't use any of the inbuilt controls so I read all the relevant plc info using a timer every 250ms and load it into public arrays and then use that data throughout my application.

The problem is the more I read the slower it gets and if I'm reading a few timer values and a few integers and some boolean tags next thing I know I can't update them quick enough to see seconds counting smoothly.

I think I know what I need... I need to read as much data as possible in one communication exchange like a block read or something similar then I can disassemble that into a table or arrays for use in my hmi.

If you or someone who knows how to resolve this could make some suggestions that would make this project 100% for me. At the moment I have to read only the data for the current screen to try and keep it preforming well enough. Except I have one screen with a lot of integer values that are monitored and that is just to slow. I would much prefer to be able to poll all the data I need for the entire HMI every 500ms or less and then just have it in the arrays. I have lots of little issues with reading only what's on the screen such as when I change screens it takes a second to update the screen and just isn't quite good enough for me.

Thanks again and I have a donation headed your way shortly as promised.
Thanks
Anthony.

antsrealm

  • Newbie
  • *
  • Posts: 13
    • View Profile
Re: Reading lots of data efficiently every half second or so.
« Reply #1 on: September 02, 2013, 04:20:40 AM »
Basically I have a hidden form that is trying to act as the communicator that reads/ polls all PLC data and puts it into a database for the rest of the application to use. I have seen older programs doing this with visual basic 6 from years ago and want to achieve the same result here.

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5268
    • View Profile
    • AdvancedHMI
Re: Reading lots of data efficiently every half second or so.
« Reply #2 on: September 02, 2013, 04:27:56 AM »
Which driver and what version are you using? Can you post the code you are using to read the data?
« Last Edit: September 02, 2013, 04:38:26 AM by Archie »

antsrealm

  • Newbie
  • *
  • Posts: 13
    • View Profile
Re: Reading lots of data efficiently every half second or so.
« Reply #3 on: September 02, 2013, 05:07:31 AM »
I was using V326 as I was getting the best results with that version at the time of starting....

Here is a small section of code as an example. Basically I check if this tab is showing and then only read the registers that display on this tab as I could not read all the data for all the tabs at once because it would slow down to much. I have about 8 tabs on this screen that contains pretty much the same amount of data on each tab. It's putting the data in public arrays that are accessible from the other form. If I attempt to read much more then this it begins to slow down to much that every now and then it would skip a second increment when monitoring a timer.

Code: [Select]
If BotVacTabOpen = True Then
            BOT_VAC_DELAY_PRE = EthernetIPforCLXComm1.ReadAny("HMI.SEQUENCES.BOTTOM_MAIN_VAC.TIMERS[0].PRE") 'READ BOTTOM MAIN VAC TIMER PRESET
            BOT_VAC_DELAY_ACT = EthernetIPforCLXComm1.ReadAny("HMI.SEQUENCES.BOTTOM_MAIN_VAC.TIMERS[0].ACC") 'READ BOTTOM MAIN VAC TIMER ACTUAL
            BOT_VAC_DURATION_PRE = EthernetIPforCLXComm1.ReadAny("HMI.SEQUENCES.BOTTOM_MAIN_VAC.TIMERS[1].PRE") 'READ BOTTOM MAIN VAC TIMER PRESET
            BOT_VAC_DURATION_ACT = EthernetIPforCLXComm1.ReadAny("HMI.SEQUENCES.BOTTOM_MAIN_VAC.TIMERS[1].ACC") 'READ BOTTOM MAIN VAC TIMER ACTUAL
            BOT_VAC_INTEGERS = EthernetIPforCLXComm1.ReadAny("HMI.SEQUENCES.BOTTOM_MAIN_VAC.INTEGERS[0]", 2) 'READ BOTTOM MAIN VAC INTEGERS
            BOT_VAC_BOOLEANS = EthernetIPforCLXComm1.ReadAny("HMI.SEQUENCES.BOTTOM_MAIN_VAC.BOOLEANS[0]", 4) 'READ BOTTOM MAIN VAC BOOLEANS
HEAT_TIME_PRE = EthernetIPforCLXComm1.ReadAny("HMI.SEQUENCES.SIDEBAR_TIMERS[0].PRE") 'READ HEAT CYCEL TIME TIMER PRESET
        HEAT_TIME_ACT = EthernetIPforCLXComm1.ReadAny("HMI.SEQUENCES.SIDEBAR_TIMERS[0].ACC") 'READ HEAT CYCEL TIME TIMER ACTUAL
        FORM_TIME_PRE = EthernetIPforCLXComm1.ReadAny("HMI.SEQUENCES.SIDEBAR_TIMERS[1].PRE") 'READ FORM CYCLE TIME TIMER PRESET
        FORM_TIME_ACT = EthernetIPforCLXComm1.ReadAny("HMI.SEQUENCES.SIDEBAR_TIMERS[1].ACC") 'READ FORM CYCLE TIME TIMER ACTUAL
        SEC_CLOSE_DELAY_TIME_PRE = EthernetIPforCLXComm1.ReadAny("HMI.SEQUENCES.SIDEBAR_TIMERS[2].PRE") 'READ 2ND CLOSE DELAY TIMER PRESET
        SEC_CLOSE_DELAY_TIME_ACT = EthernetIPforCLXComm1.ReadAny("HMI.SEQUENCES.SIDEBAR_TIMERS[2].ACC") 'READ 2ND CLOSE DELAY TIMER ACTUAL
        FIRST_OPEN_DELAY_PRE = EthernetIPforCLXComm1.ReadAny("HMI.SEQUENCES.SIDEBAR_TIMERS[3].PRE") 'READ 1ST OPEN DELAY TIMER PRESET
        FIRST_OPEN_DELAY_ACT = EthernetIPforCLXComm1.ReadAny("HMI.SEQUENCES.SIDEBAR_TIMERS[3].ACC") 'READ 1ST OPEN DELAY TIMER ACTUAL
        MOULD_OPEN_DELAY_PRE = EthernetIPforCLXComm1.ReadAny("HMI.SEQUENCES.SIDEBAR_TIMERS[4].PRE") 'READ MOULD OPEN DELAY TIMER PRESET
        MOULD_OPEN_DELAY_ACT = EthernetIPforCLXComm1.ReadAny("HMI.SEQUENCES.SIDEBAR_TIMERS[4].ACC") 'READ MOULD OPEN DELAY TIMER ACTUAL
        COOLING_DELAY_PRE = EthernetIPforCLXComm1.ReadAny("HMI.SEQUENCES.SIDEBAR_TIMERS[5].PRE") 'READ COOLING DELAY TIMER PRESET
        COOLING_DELAY_ACT = EthernetIPforCLXComm1.ReadAny("HMI.SEQUENCES.SIDEBAR_TIMERS[5].ACC") 'READ COOLING DELAY TIMER ACTUAL

        SEQ_BOOLEANS = EthernetIPforCLXComm1.ReadAny("HMI.SEQUENCES.BOOLEANS[0]", 11) 'READ TOP SEQUENCE ADJUST BOOLEANS
         
        End If

I downloaded V358 just before and am trying to recreate this problem in that version with a clean project and I'll attach the whole project if I have the same problem.
« Last Edit: September 02, 2013, 05:09:54 AM by antsrealm »

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5268
    • View Profile
    • AdvancedHMI
Re: Reading lots of data efficiently every half second or so.
« Reply #4 on: September 02, 2013, 05:14:05 AM »
Everything looks normal with that bit of code. The only thing in question is the value of the AsyncMode property.

Version 3.58 should give you much better results. The CLX driver has been completely revamped and is faster and more stable.

antsrealm

  • Newbie
  • *
  • Posts: 13
    • View Profile
Re: Reading lots of data efficiently every half second or so.
« Reply #5 on: September 02, 2013, 05:24:20 AM »
Ok, well say I have to read in 50 different timer preset and acc values, 50 different integer values and 50 different boolean values. Do you think it should be possible to read all of that every half second and see timer acc values (to the second) updating on the screen without missing a beat ??

I'm going to play with V358 in the mean time but I wont be finished with that until this time tomorrow I'd say.

Ultimately I'd like to fill a database like table and then just use that to populate all the HMI objects.

Thanks Archie.

antsrealm

  • Newbie
  • *
  • Posts: 13
    • View Profile
Re: Reading lots of data efficiently every half second or so.
« Reply #6 on: September 02, 2013, 05:26:34 AM »
Async mode was set to false. I had ayncmode = true commented out, I think I tried it without much luck at some stage.

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5268
    • View Profile
    • AdvancedHMI
Re: Reading lots of data efficiently every half second or so.
« Reply #7 on: September 02, 2013, 07:34:18 AM »
Ok, well say I have to read in 50 different timer preset and acc values, 50 different integer values and 50 different boolean values. Do you think it should be possible to read all of that every half second and see timer acc values (to the second) updating on the screen without missing a beat ??
Depending on your network speed and PLC processor speed, each read packet will average 10-20ms. Keep in mind that reading synchronously in code will block your UI thread and make your form unresponsive while it is waiting on the response from the PLC. So let's say you have a Read command in a loop of 50 iterations. If each read takes 10ms, the complete loop will take 500ms. Then if you execute that every 500ms, you will essentially lock up your program because the UI(user interface) thread spends all of its time reading and waiting on data.

This is where the BeginRead(asynchronous) or subscriptions come into play. BeginRead will return as soon as the read packet is put in the queue and not hold the UI thread. Once data is returned from the PLC, it will be returned in a DataReceived event.

Subscriptions take this a step further by running on a background thread to continuously update the data without tying up the UI thread. The driver will also group multiple subscriptions into single reads when possible. All of the controls/components use subscriptions making it more efficient to use than reading the values in code synchronously. The latest version has a DataSubscriber component that encapsulates the complexity of using subscriptions.

The bottom line is that you will find your application to be more responsive by using 50 BasicLabels as opposed to synchronously reading in code and storing in a variable.
« Last Edit: September 02, 2013, 07:38:39 AM by Archie »

antsrealm

  • Newbie
  • *
  • Posts: 13
    • View Profile
Re: Reading lots of data efficiently every half second or so.
« Reply #8 on: September 02, 2013, 07:54:50 AM »
OK interesting. Yes I did experience the UI lock up as you described and I got around that by using visual basics background worker which put all the read commands into another thread and that gave me a nice smooth UI. I just created a new project using a L32E processor I have at home and read in quite a lot of integers and timer values and it preforms a lot better the V326 but still has that feeling of being bogged down a bit.

As you said the sum of the read times in this synchronous mode is just to long, I had a quick play with the data subscriber earlier today but I will possibly require some documentation on how to use that properly for multiple addresses (I had it working for one address). From what I briefly read about how other PLC / vb apps do it is by reading in all data, or at least as much as data as possible in one transaction as a block and then processing the data down to the bit level in VB. I don't mind putting the time in up front to get a nice smooth UI that isn't restricted to a certain number of tags.

I guess going forward will be to try the DataSubscriber in more depth. Was there some documentation for that ?

Thanks,
Anthony.

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5268
    • View Profile
    • AdvancedHMI
Re: Reading lots of data efficiently every half second or so.
« Reply #9 on: September 02, 2013, 08:09:58 AM »
The weakness of the current DataSubscriber is that each instance can only subscribe to a single element. The DataSubscriber is essentially a BasicLabel with the visual parts removed. The drivers do not allow subscriptions to multiple elements of an array(not until version 4).

In your scenario, the fastest update would be to move your PREs and ACCs into an array in the PLC, then read the complete array with BeginRead and getting the resulting data in the DataReceived event:

Code: [Select]
'* Initiate the asynchronous read
EthernetIPforCLXCom1.BeginRead("MyArray[0]",100)

    Private Sub EthernetIPforCLXCom1_DataReceived(sender As System.Object, e As MfgControl.AdvancedHMI.Drivers.Common.PlcComEventArgs) Handles EthernetIPforCLXCom1.DataReceived
        If e.PlcAddress = "MyArray[0]" And e.Values.Count >= 100 Then
            '* process the data......
            e.Values.CopyTo(0, ArrayOfPre, 0, 50)
            e.Values.CopyTo(50, ArrayOfAcc, 0, 50)
        End If
    End Sub
« Last Edit: September 02, 2013, 08:12:13 AM by Archie »

antsrealm

  • Newbie
  • *
  • Posts: 13
    • View Profile
Re: Reading lots of data efficiently every half second or so.
« Reply #10 on: September 02, 2013, 08:35:51 AM »
Yeah that would be an acceptable method. I was just playing with your basic button and basic label... they work really well I copied and pasted a basic label with the same address 100 times and it was fairly quick and then I used a basic button that is monitoring the state of a BOOL to change the highlight colour. One of the problems I ran into with my manually coded version was that it would start at form load in say the off position and then it would take a sec to read the plc then it would snap over to the on position and you would see this 1 sec delay when opening a new form before the buttons and labels showed the correct data. However your basic button is flawless no matter the state in the PLC it opens in the correct state when the form opens. I like what I see.

Do you have an account I can send a donation to... I want to make a donation of $200 AUD as a gesture of thanks for putting in the effort to produce this and then for supporting it so well.

Thanks
Anthony.

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5268
    • View Profile
    • AdvancedHMI
Re: Reading lots of data efficiently every half second or so.
« Reply #11 on: September 02, 2013, 10:07:26 AM »
Do you have an account I can send a donation to... I want to make a donation of $200 AUD as a gesture of thanks for putting in the effort to produce this and then for supporting it so well.
I turned off the donation feature on sourceforge in preference to asking to support the software development by purchasing the expansion packs on the web site. I'll soon add a support item on there for support via direct email at a higher priority. I feel like this is a bit more fair for those that give, so at least they can get some extra items.

antsrealm

  • Newbie
  • *
  • Posts: 13
    • View Profile
Re: Reading lots of data efficiently every half second or so.
« Reply #12 on: September 02, 2013, 04:03:10 PM »
Ok, well I just purchased one of everything on your site and that totals something like $10 so I still want to donate more as this has saved me a lot of $$$. I'll keep an eye out for the extra support option when you add it.

If you enable the donate option again let me know as I want to support this project.

Thanks,
Anthony.

TSLJon

  • Newbie
  • *
  • Posts: 24
    • View Profile
Re: Reading lots of data efficiently every half second or so.
« Reply #13 on: September 09, 2013, 10:36:20 AM »
Ok, well I just purchased one of everything on your site and that totals something like $10 so I still want to donate more as this has saved me a lot of $$$. I'll keep an eye out for the extra support option when you add it.

If you enable the donate option again let me know as I want to support this project.

Thanks,
Anthony.

In agreement with this yes!