Sign in to follow this  
ethushara

maximum no of channels

Recommended Posts

Hi,

Can you let me know the maximum no of channels can be handled by Daqfactory in modbus RTU or TCP if it read once per second in parallel? Because in my system when the no of channels are increasing the data receives very slowly. Sometimes once a 10 seconds. Sometimes still lower. Right now it gets around 70 channels. I meant tags. 

I'm going to add some more channels with modbus TCP and it will be around 300. So please let me know how to do this to get exact ones per second in each channel. 

BR,

Thushara 

 

Share this post


Link to post
Share on other sites

That actually depends on your remote device and what it's turn-around time is.  You should, however, be able to increase the speed by connecting to different TCP devices on different threads so that DAQFactory can communicate with them in parallel.  If using Channels the best way to achieve that is to give them different Timing or Offset parameters.  So one device might be Timing 1, Offset 0, while another might be at Timing 1, Offset 0.1.  They both get read once a second, but in parallel.

To figure out your remote device turnaround, use the comm monitor with the time of Tx/Rx display enabled.

Note also that you can get better through-put if you make your tags concurrent.  In other words, instead of reading registers 1, 3, 7 and 10, try and pack those registers inside the PLC, so 1,2,3 and 4.  If you can't pack them, consider reading the in between values in junk channels that you don't use.   DAQFactory can read 1, 3, 7, and 10 in either 4 separate queries, if you only specify those channels, or as 1 query if you specify all the registers between 1 and 10 with the same timing and offset.

Share this post


Link to post
Share on other sites

Hi,

It changed the speed in good scale in Modbus protocol. Still i need to get your guidance to speedup the CANbus connection speed in my Daqfactory. In fact those are on ready by the program and so i don't know the delay comes from where. A sequence used to read the messages is as below. 

 

while (1)
   device.U1GOV.Purge()
   private string strIn1 = device.U1GOV.read(1)
   private string in1 = asca(strIn1)
   strIn1 = device.U1GOV.read(in1[1])
   in1 = asca(strIn1)
   ID1.Addvalue(in1 [4])
   If ((ID1 (0) > 87) && (ID1 (0) < 89))
      CCP100.Addvalue(in1 [9])
      CCP101.Addvalue(in1 [10])
      CCP102.Addvalue(in1 [11])
      CCP103.Addvalue(in1 [12])
      CCP104.Addvalue(in1 [13])
      CCP105.Addvalue(in1 [14])
      CCP106.Addvalue(in1 [15])
      CCP107.Addvalue(in1 [16])
   else
      If ((ID1 (0) > 23) && (ID1 (0) < 25))
         IP150.Addvalue(in1 [9])
         IP151.Addvalue(in1 [10])
         IP152.Addvalue(in1 [11])
         IP153.Addvalue(in1 [12])
         IP154.Addvalue(in1 [13])
         IP155.Addvalue(in1 [14])
         IP156.Addvalue(in1 [15])
         IP157.Addvalue(in1 [16])
      else
         If ((ID1 (0) > 31) && (ID1 (0) < 33))
            IP200.Addvalue(in1 [9])
            IP201.Addvalue(in1 [10])
            IP202.Addvalue(in1 [11])
            IP203.Addvalue(in1 [12])
            IP204.Addvalue(in1 [13])
            IP205.Addvalue(in1 [14])
            IP206.Addvalue(in1 [15])
            IP207.Addvalue(in1 [16])
         else
            If ((ID1 (0) > 55) && (ID1 (0) < 57))
               CCP250.Addvalue(in1 [9])
               CCP251.Addvalue(in1 [10])
               CCP252.Addvalue(in1 [11])
               CCP253.Addvalue(in1 [12])
               CCP254.Addvalue(in1 [13])
               CCP255.Addvalue(in1 [14])
               CCP256.Addvalue(in1 [15])
               CCP257.Addvalue(in1 [16])
            else
               If ((ID1 (0) > 103) && (ID1 (0) < 105))
                  IP300.Addvalue(in1 [9])
                  IP301.Addvalue(in1 [10])
                  IP302.Addvalue(in1 [11])
                  IP303.Addvalue(in1 [12])
                  IP304.Addvalue(in1 [13])
                  IP305.Addvalue(in1 [14])
                  IP306.Addvalue(in1 [15])
                  IP307.Addvalue(in1 [16])
               else
                  If ((ID1 (0) > 119) && (ID1 (0) < 121))
                     IP350.Addvalue(in1 [9])
                     IP351.Addvalue(in1 [10])
                     IP352.Addvalue(in1 [11])
                     IP353.Addvalue(in1 [12])
                     IP354.Addvalue(in1 [13])
                     IP355.Addvalue(in1 [14])
                     IP356.Addvalue(in1 [15])
                     IP357.Addvalue(in1 [16])
                  else
                     If ((ID1 (0) > 151) && (ID1 (0) < 153))
                        CCP450.Addvalue(in1 [9])
                        CCP451.Addvalue(in1 [10])
                        CCP452.Addvalue(in1 [11])
                        CCP453.Addvalue(in1 [12])
                        CCP454.Addvalue(in1 [13])
                        CCP455.Addvalue(in1 [14])
                        CCP456.Addvalue(in1 [15])
                        CCP457.Addvalue(in1 [16])
                     else
                        If ((ID1 (0) > 71) && (ID1 (0) < 73))
                           CCP280.Addvalue(in1 [9])
                           CCP281.Addvalue(in1 [10])
                           CCP282.Addvalue(in1 [11])
                           CCP283.Addvalue(in1 [12])
                        endif
                     endif
                  endif
               endif
            endif
         endif
      endif
   endif
   delay (0.2)
endwhile

 

Best regards,

Thushara

Share this post


Link to post
Share on other sites

You probably don't need the delay(0.2).  Just add a try/catch around everything and put delay(0.1) inside the catch(), then let the read() handle the delay.  Right now, if the data comes faster than 0.2 seconds, you'll get backlogged because you are only reading from the buffer every 0.2 seconds.

 

Share this post


Link to post
Share on other sites

First, I'd use a switch/case() in lieu of the many nested ifs.

But I can't figure out what's going on here.  You're doing an asca() on values from your buffer, which implies they're ASCII and you want integer numeric codes instead.  But then you assign the result to a string variable (and then use it in a numeric comparison), so I'm confused.

Is the data coming in as string-encoded  numeric data and you want actual numbers in the channels?  If that's the case, you probably want chra() rather than asca().  Or are you actually pushing ASCII character codes into channels?  If so, what's the application?  Does this all work as expected other than wanting to optimize speed?

Can you give us background on what the encoding is for the incoming stream and what you're doing with the information?

Share this post


Link to post
Share on other sites

Assuming the repetitive part under the while() is correct, I'd create a function to do that

function PackChannels(string UnitName, ChanPoint, FloatPoint, count)
    for(private idx = 0, idx < Count, idx++)
        execute(UnitName + format("%03.0f", ChanPoint + idx) + ".Addvalue(in1[" + \
            (FloatPoint + idx)) + "])")
        endfor
    return

That would reduce that portion of the while() to

    private UnitID = floor(in1[4] + 0.5)
    switch
        case(UnitID == 88)
            PackChannels("CCP", 100, 9, 8)
        case(UnitID == 24)
            PackChannels("IP",  150, 9, 8)
        ...
        endcase

which is a lot more compact.

 

Share this post


Link to post
Share on other sites

I suspect (though I don't know what driver you're using or how it works) that doing the purge() immediately before the read() might be an issue.  Will the read() wait till there are characters in the buffer?  I think I might purge(), then delay(), then read(), if read() wants the bytes to already be there.

Also, could you be deleting telegrams from devices other than the one you just read when you do the purge()?  If so, that might explain why it takes a long time to get data from each remote.

Share this post


Link to post
Share on other sites

Unless you do read(0) which will return whatever is in the buffer, read() will block (wait) until the specified number of characters is received, or the timeout occurs.  If the timeout does occur then it will throw an error.  ReadUntil() also will block.  For this reason you do not need, nor should you use delay().  That said, you should not be purging inside your loop because that will clear out characters that accumulate between the last read() and the purge().  Instead you really just want to use this pattern:

purge()
while(1)
   try
      read() // or readuntil()
      // process data
   catch()
       delay(0.05)
   endcatch
endwhile

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this