Author Topic: Reading a large amount of tags  (Read 4208 times)

kenjacoby

  • Newbie
  • *
  • Posts: 3
    • View Profile
Reading a large amount of tags
« on: December 16, 2016, 10:01:18 AM »
Good morning, I am logging fault alarms from 350 different tags.  they are located in an array(3) of 150 INT tags. 

PROGRAM:ProductionData.FaultSummary[0]
PROGRAM:ProductionData.FaultSummary[1]
PROGRAM:ProductionData.FaultSummary[2]


I currently create 3 arrays(150 long in VB) and record the status of each tag.  on the local network this takes 15 seconds to go through all 350 tags.  From home, with a DSL connection, it takes over 10 minutes. 

        ARRAY(0) = EthernetIPforCLXCom1.Read("PROGRAM:ProductionData.FaultSummary[0].GycolTankRunning")
        ARRAY(1) = EthernetIPforCLXCom1.Read("PROGRAM:ProductionData.FaultSummary[0].PreheatOvenDNS")
        ARRAY(2) = EthernetIPforCLXCom1.Read("PROGRAM:ProductionData.FaultSummary[0].PreheatBlowerDNS")
        ARRAY(3) = EthernetIPforCLXCom1.Read("PROGRAM:ProductionData.FaultSummary[0].DryOvenDNS")
        ARRAY(4) = EthernetIPforCLXCom1.Read("PROGRAM:ProductionData.FaultSummary[0].DryOvenBlowerDNS")
        ARRAY(5) = EthernetIPforCLXCom1.Read("PROGRAM:ProductionData.FaultSummary[0].PreheatBlowerTripped")
        ARRAY(6) = EthernetIPforCLXCom1.Read("PROGRAM:ProductionData.FaultSummary[0].PreheatExhaustTripped")

after recording all the data in the array files, I write all the data to a text file to import into excel.

Every thing works fine.  I am just trying to speed up the transfer, especially over my VPN.

thanks,
Kenneth

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5262
    • View Profile
    • AdvancedHMI
Re: Reading a large amount of tags
« Reply #1 on: December 16, 2016, 06:48:14 PM »
A multi-read will significantly increase the read speed:

        Dim Taglist(3) As String
        Taglist(0) = "PROGRAM:ProductionData.FaultSummary[0].GycolTankRunning"
        Taglist(1) = "PROGRAM:ProductionData.FaultSummary[0].PreheatOvenDNS"
        Taglist(2) = "PROGRAM:ProductionData.FaultSummary[0].PreheatBlowerDNS"
        Taglist(3) = "PROGRAM:ProductionData.FaultSummary[0].DryOvenDNS"
        EthernetIPforCLXCom1.BeginReadMultiple(Taglist)


It is an asynchronous method, so to receive the data:

    Private Sub EthernetIPforCLXCom1_DataReceived(sender As Object, e As Drivers.Common.PlcComEventArgs) Handles EthernetIPforCLXCom1.DataReceived
        If e.ErrorId = 0 Then
            If e.PlcAddress = "PROGRAM:ProductionData.FaultSummary[0].GycolTankRunning" Then
                Array(0) = e.Values(0)
            End If
        End If
    End Sub



The multi-read is limited by the request packet size. If you take the lengths of all the tag names requested then add 4 for each tag, that result cannot exceed 470. The example tags I used above would result in 228 byte packet size, so I could add about 4 more tags to the list.

mondacag

  • Newbie
  • *
  • Posts: 8
    • View Profile
Re: Reading a large amount of tags
« Reply #2 on: June 28, 2017, 03:27:39 PM »
I have an array of structured UDT used to store production data and limits. There are 272 elements or tags (more could be added) that needs to be logged. I tried with consecutive individual reads using:
Code: [Select]
NumNido = EIPforCLX1.Read("Num_Nido_E12")
Data.NestNum.Valor = EIPforCLX1.Read("Nido[" & NumNido & "].NestNum.Valor")
Data.NestNum.C_Error = EIPforCLX1.Read("Nido[" & NumNido & "].NestNum.Codigo_Falla")

I tested it with a CLX L18ER and a HP ZBook G3 15 with a Core i7. The PLC has no code, only the tags. It takes 1.5 seconds to read all the data after the fist read. But when i tested it on site in a L36ERM with 12 programs, 23 Ethernet IP devices (robocilinders, 2d scanners, vision sensors, an SCARA, communication units, and some RS232 devices), 5 HMI, and an industrial PC to log the data (iTac)

First the PLC was running two tasks, one periodic (20ms) and one continuos(20ms min 150ms max due an AOI and the periodic task). It took almost 3 minutes to read the data that was downloaded 2.5 minutes ago.

Then i disabled the periodic task, leaving only the continuos (now 20ms min 100ms max due the AOI), and it took somewhat 16 seconds to read all the data, plus the station time cycle (pick&place) plus the time to send the data to the server (less than 2 seconds), it almost 30 seconds. And the machine is planned to produce a piece every 15 seconds.

The machine has a dial with 12 positions, and all the operations are distributed in 11 stations.

Now i was trying to use the BeginReadMultiple method, similar as described by Archie, with some extra code to ensure the data was read before changing the Tag list:

I have a routine to asign all the tag names depending on the nest presente in station 12
Code: [Select]
        NumNido = EIPforCLX1.Read("Num_Nido_E12") 'Read the Nest Number in Station 12: Download
        PLCAddress(0) = "Nido[" & NumNido & "].NestNum.Valor"
        PLCAddress(1) = "Nido[0].NestNum.Lim_Inf"  'The element or nest 0, stores the limits for the machine
        PLCAddress(2) = "Nido[0].NestNum.Lim_Sup"
        PLCAddress(3) = "Nido[" & NumNido & "].NestNum.Codigo_Falla"

To implement the MultiRead:
Code: [Select]
            'Clear all the read status
            For i = 0 To 271
                Read(i) = False
            Next
            'Dimention the array depending on the number of tags that can be read
            ReDim TagList(12)
            For i = 0 To 12
                TagList(i) = PLCAddress(i) 'Asign the PLCAddress to the Tag list
            Next
            EIPforCLX1.BeginReadMultiple(TagList)
            Do Until DataRead = 13 'Checks if all the tags in the list were read
                DataRead = 0
                Application.DoEvents()
                For i = 0 To 12
                    If Read(i) Then
                        DataRead += 1
                    End If
                Next
            Loop
            Redim TagList(11) 'Repeat the code to read all the tags



Then to receive the data, i didn't wanted to write an IF..THEN for every element:
Code: [Select]
    Private Sub EIPforCLX1_DataReceived(ByVal sender As Object, ByVal e As Drivers.Common.PlcComEventArgs) Handles EIPforCLX1.DataReceived
        If e.ErrorId = 0 Then
            'If e.PlcAddress = TagList(0) Then
            '    Data_Value(0) = e.Values(0)
            'End If

            For i = 0 To 271

                If e.PlcAddress = PLCAddress(i) Then
                    For j = 0 To TagList.Length
                        If e.PlcAddress = TagList(j) Then
                            Data_Value(i) = e.Values(0)
                            Read(i) = True
                            'Exit For
                        End If
                    Next
                End If
                If Read(i) Then
                    'Exit For
                End If
            Next

        End If
    End Sub

When i tested this in the PLC i have in the office (L18ER), i took almos 4 seconds to read the data. I have to test it on site to see if there is some improvement in the time.

Phrog30

  • Guest
Re: Reading a large amount of tags
« Reply #3 on: June 28, 2017, 04:36:47 PM »
AHMI drivers and UDT's don't work well together.  That's been my biggest hurdle is UDT's.  So reading one at a time, which looks like what you are doing, is about the only choice.  You may want to look at DINT or REAL arrays so you can do block read/writes.  Another option is to use data change so you are only reading what changed.  Basically, there is no reason to read something that didn't change.  When the app loads it will read all tags, but after that only what changed.

mondacag

  • Newbie
  • *
  • Posts: 8
    • View Profile
Re: Reading a large amount of tags
« Reply #4 on: June 28, 2017, 06:22:25 PM »
There is some hope

It's actually a coincidence this topic came back up because just this past week the driver had been given functionality to write complete UDTs and custom length strings. If testing goes well this coming week, it should be part of the next release.

Phrog30

  • Guest
Re: Reading a large amount of tags
« Reply #5 on: June 28, 2017, 07:47:21 PM »
I'm on pins and needles.... If that gets introduced that would be the best thing so far.

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5262
    • View Profile
    • AdvancedHMI
Re: Reading a large amount of tags
« Reply #6 on: June 28, 2017, 08:42:56 PM »
I tested it with a CLX L18ER and a HP ZBook G3 15 with a Core i7. The PLC has no code, only the tags. It takes 1.5 seconds to read all the data after the fist read. But when i tested it on site in a L36ERM with 12 programs, 23 Ethernet IP devices (robocilinders, 2d scanners, vision sensors, an SCARA, communication units, and some RS232 devices), 5 HMI, and an industrial PC to log the data (iTac)
What you are seeing is the sharing of your processor time slice between program logic and communications. Your communication speed bottleneck comes from how fast the processor can process and respond to the read request. If there is no PLC program and the processor is in program mode, then it can have the maximum amount of CPU time dedicated to servicing communications. From my testing in this scenario, response time averaged around 2.5ms. I did a further test with a single rung and the processor in run mode. This took away from the CPU being able to process communications and it then took an average of 5ms. So any bit of processor time that has to be used for program processing will be time taken away from communication processing.

So then how can you optimize this? Each request requires a header packet of about 24 bytes, but more importantly requires the CPU to process it and put the response on the wire. By reducing the number of requests, you increase the overall communication response. This can be done in several ways.

One is to read part or all of the UDT in one request. Since AdvancedHMI is unaware of UDT structures, it's only option is to return an array of raw bytes, then it is up to you to parse into the elements. This take a fairly in depth understanding of the way elements are packed into memory. If you UDT contains only 4 byte elements, such as DINTs and REALs, then it become very easy. But if you have mixed elements, then it can be quite complex.

Let's take your example with a few assumptions. I will make the assumption your UDT elements of Valor and Codigo_Falla are both DINT and are the only elements in the NestNum UDT. Based on those assumptions, let's read the complete UDT like this:
Code: [Select]
Dim b() as string=EIPforCLX1.Read("Nido[" & NumNido & "].NestNum")

Let's assume the scenario where Valor=1 and Codigo_Falla=2. I will also make the assumption Valor is the first element in the UDT definition. With all of those assumptions, the read above will return this:

0100000002000000

What does all that mean? Well it is the raw bytes in hex. We know that a DINT uses 4 bytes, so the first 4 bytes are:

01 00 00 00

If you take those 4 bytes and convert from hex to decimal, store it in a byte array, then convert it to an Iint32, you will get the result of Valor. This now leaves the last 4 bytes which will be the raw data for the value of Codigo_Falla

Using this method we will decrease our read time in almost half, but will require some additional code for parsing.

This post is becoming long so I won't go into the specific code for doing all of this parsing.
« Last Edit: June 28, 2017, 08:45:06 PM by Archie »

mondacag

  • Newbie
  • *
  • Posts: 8
    • View Profile
Re: Reading a large amount of tags
« Reply #7 on: June 28, 2017, 11:31:58 PM »
I know what you mean Archie. It is similar to what happens when trying to read a custom string, you get the raw data the four bytes of the lenght followed for the data bytes of the string.

I have an idea of how to do the parsing. I got some help to develop the app using another driver for the communication. The AOI i mentioned in a previous post is to concatenate al the data in string format using a token between values, to then split everything in the VB app. That's why i have that increase in the PLC scan time, also i got an string with 1600 chars. I'm looking for a better way to do this.

I remember trying to read the whole UDT whe i started testing with AHMI, but did't received a response. I'm gonna give it another try.

Edit: After a couple of hours testing (most of it arranging the variables to parse the data), i'm able to read the whole UDT and parse it to a variable with the same structure. The routine to parse the data has about 310 lines of code, but it only takes from 20 to 30ms to read all the data. The only thing left is test it on site.
« Last Edit: June 29, 2017, 02:20:49 AM by mondacag »

Ashish

  • Newbie
  • *
  • Posts: 1
    • View Profile
Re: Reading a large amount of tags
« Reply #8 on: July 16, 2019, 05:19:45 PM »
Question:

1. If we are using "BeginReadMultiple" method to read tags, for each tag response is coming back to call back function, how do program will know that all tag responses are received?

2. What would happen if requested for 100 tags but for some tags no response received?

3. What would happen if requested for 100 tags but during reading complete tag response exception occurrs?

We downloaded the latest driver of "EthernetIPforCLXCom.cs" and "ClxDriver.dll" from:
V130 - This is paid version.

Please advise.

« Last Edit: July 16, 2019, 06:50:22 PM by Archie »