Citect Scada 2018 - IOServer stops when transferring data between Array's

Hi,

When I try to move data from one array defined in Cicode to an array defined in Variable Table, the IOServer "halts" and sometimes stops and then restarts.

My Simple test code in Cicode Editor is as follow:
REAL HPCData[8760];
FUNCTION Transfer()
INT i;
FOR i = 0 TO 8760 DO
  HPCPerfDatahttps://softwareforums.aveva.com/cfs-file/__key/system/emoji/1f4a1.svg = HPCDatahttps://softwareforums.aveva.com/cfs-file/__key/system/emoji/1f4a1.svg;
END
The Variable Array HPCPerDatahttps://softwareforums.aveva.com/cfs-file/__key/system/emoji/1f4a1.svg is defined as follow:
TagName: HPCPerDatahttps://softwareforums.aveva.com/cfs-file/__key/system/emoji/1f4a1.svg
I/O Device: GENERIC
Data Type: REAL
Address: R1[8760]
If I reduce the array size, the IOServer is not halted/stopped that frequently. As an array may have 32767 elements according to help files, this number should not be an issue.
Appreciate any input that can help enlighten what's going on and perhaps there are some good best practices in Citect on how to work efficient with Arrays. 
Thanks,
Rune
  • Hi Rune.

    This is not possible to do if you were using physical PLC, you have to consider;
    Maximum Request Length is the maximum number of data bits that can be read from an I/O Device in a single request. For example, if the maximum request length is 2048 bits, the maximum number of integers that can be read is: 2048/16 = 128
    If you define an array of I/O Device variables, you must ensure that the array does not exceed the maximum request length.
    Citect also has a limit of 2048 bits irrespective of the protocol!

    Since you are using a Generic driver , I should consider to use Local variables. The drawback with Local variables are the values in a local variable are only available to the process in which they were written.
  • Hi Rune,

    First thing: when performing large FOR or WHILE loops, always put a SleepMs(0) statement in the loop to prevent your cicode from locking up other Citect processes.

    On array limits in Citect this is what the documentation says:
    In the "GENERIC" protocol help, a limit of 16376 elements is mentioned for the REAL datatype, not 32767.

    As for cicode arrays, help states (topic "Compile Error Messages") that there is a memory limit of 60kB per array, which translates to max. 7680 elements for (64 bit) REALs. If that limit is exceeded a compiler error "Cicode data limit reached" should be thrown.
    My personal understanding however is that in the past cicode arrays could always be declared up to 64kB (8192 elements) and I'm not 100% sure but I thought they increased that limit in newer Citect versions to 8192kB (over 1,000,000 REAL elements).

    In any case, the exception you are experiencing should never occur for going over the maximum array size. Perhaps the I/O server chokes on the many tag writes it has to perform in one go. Putting in a SleepMs(0) command should prevent that.

    Furtermore: do you have the "Persist" option set to TRUE or FALSE for this I/O device? If it is set to TRUE then it saves all values to disk as well, which might cause disk performance issues. Again, applying some sleep time in your loop might prevent this.

    If the problem persists, best option is to contact support for this issue. If you have the crash reports and dump files it might help them.

    Last thing:
    In v2015 there is a known bug (bug 60143) that can cause exceptions when writing to memory I/O device array tags.
    Maybe this bug has re-appeared in v2018?

    Best Regards,
    Patrick
  • Hi Patrick,
    Thanks for your supplementary explanation, most appreciated.

    Yes I had the Persist to True, changed it to False, did not have nay major impact.

    Added the SleepMS(1) to the FOR loop and that prevented the IOServer from halted/restarting.
    However it then requires quite some time to loop through the 8759 elements (used about 15seconds).

    I then added a new IOServer2 only dedicated to the GENERIC Protocol.
    This seems to really do the magic trick, now the data move completes within 1-2s and no impact on IOServer1.

    What do you think about this solutions? Do you see any impact when it comes to remote access etc, or other tasks?

    Thanks
    Rune
  • Thanks Peter for your prompt input and clarification!

    It seems like the additional IOServer and/or SleepMS(1) does the trick.

    Thanks,
    Rune
  • Hi Rune,

    Glad you found a solution.

    By using SleepMS(1) you are delaying your loop at least by 8759 milliseconds, which explains most of the extra delay.
    SleepMS(0) is usually enough for Citect to allow other threads and processes to run without problems.

    Splitting up I/O servers can be a valid option if a single I/O server is running out of resources (CPU, memory, disk), and if your budget allows for the extra costs of hardware, software and licenses. Normally you would do that for applications with really large amounts of I/O points (like 10,000+ points or so).

    I don't know if it is possible to avoid the copy loop altogether by using the Variable Tags directly in your application?
  • Hi Patrick,
    I tried SleepMS(0) but then the IOServer halted.

    I don't think I can avoid, please correct me if I'm wrong.
    I'm using the TrnGetTable to get data from the Trend database. This function does not allow me to use an Variable defined Array directly. Have to use a Cicode defined Array as a temporarily array.

    The end goal is to use the data in VBA and 3 party Active-X. My understanding is that the Array would have to be defined as an Variable array if both Cicode and VBA should have access to it. I'm not able to access an Cicode Array directly from VBA.

    Configuring Active-X with VBA is so much easier than with cicode. I think some features are not supported either in Cicode towards an active-x.

    If you have other tricks I'm open to test any suggestions.

    Rune