How can I capture an analog value into array .

Hi,

I want to know how i can snapshot ( e.g.,5 values from same analog input ) the analog value to a array.

  

  • If you are asking what the format of an expression in an ACT or CALC block on how to save to the array then

    '^/ARRAY_PARAM'[ x ][ y ] := VALUE;

    where x is Row and y is Column of the array.

  • In reply to Matt Stoner:

    Thank you sir . I want to assign 10 values from a single analog input to 10 place of an array.  After 1 scan one value will capture to '^/ARRAY_PARAM'[ 1 ][1y] := n1(value from analog input); & so on. Is my question clear to you now?

  • In reply to Matt Stoner:

    And I always forget this, but note the parameter name within single quotes in Matt's post does not include the X and Y values. '^/ARRAY_PARAM' is the path.

    This allows you to use variables for the [x] and [y] designators. So you can programmatically reference the Array cells, like in a DO While loop, where you could sum the cells in the array and divide by the number of values to calculate an average.

    i :=1;
    SUM :=0;

    WHILE( i <= 5) DO
    SUM := SUM + '^/ARRAY_PARAM'[i][1];
    i := i + 1;
    END_WHILE;

    Average := SUM /i ;

    Andre Dicaire

  • In reply to Rajeev Kumar:

    I had to update the format of the y to put spaces before and after the brackets as it changed it to [y] so remove the spaces before and after brackets.

    If your array is 10 rows by 1 column, then you would have 10 lines in the expression using [1][1], [2][1], [3][1], etc for the x and y format shown above
    If your array is 1 row by 10 columns, then you would have 10 lines in the expression using [1][1], [1][2], [1][3], etc for the x and y format shown above
  • In reply to Matt Stoner:

    Sir after 1 scan i want one value will capture to '^/ARRAY_PARAM'[ 1 ][1] := (value from one scan of analog input); & so on. After completing ten scan again to reset the values of array.
  • In reply to Rajeev Kumar:

    Rajeev, You should be paying me...I know Matt would pay me.

    First, there are many ways to implement this, but here is one approach

    i :=1;

    WHILE( i <= 9) DO
    '^/MY_ARRAY[i][1] := '^/MY_ARRAY[i+1][1]; Rem This moves the content of the array to make room for the new value.
    i := i + 1;
    END_WHILE;

    '^/MY_ARRAY' [10][1] := 'MY_MODULE/AI1/OUT.CV';

    The array has 10 rows and 1 column. On the first scan, i= 1. the array is basically empty. The While loop moves all the values up 2 goes to 1, 3 goes to 2 etc. When you get to i=9, the value from 10 goes to 9 and the loop ends. Then you write your value to 10. The array contains the last 10 module scan values from My_Module/AI1/OUT, with the newest value in index [10][1]. Change this to store what ever value you want.

    You could go the other way, starting with i=10, and storing [i-1] and counting down the index, and set the While (i>=2). Then in the end you store your most current value in index 1

    i :=10;

    WHILE( i >= 2) DO
    '^/MY_ARRAY[i][1] := '^/MY_ARRAY[i-1][1]; Rem This moves the content of the array to make room for the new value.
    i := i -1;
    END_WHILE;

    '^/MY_ARRAY' [1][1] := 'MY_MODULE/AI1/OUT.CV';

    It depends on whether you want to see the oldest value in the 10th position. Actually, I like this better, because if you decide to make the array bigger, you can increase the starting i value to match the array size and you don't have to change anything else. Also your most recent values are still in the same location, that is the most recent value is in [1][1].

    All code examples provided without guarantee. No copyright attached. Use at your own risk!

    Andre Dicaire

  • In reply to Andre Dicaire:

    The autocorrect keeps putting a light bulb instead of the letter "i". Next time I'm using "n" for my index letter :-(

    Andre Dicaire

  • Using a Dead Time block could help here. This fb "delays" an analog value by DEAD_TIME seconds. So the easy way could be adding 4 dead time fb, setting their DEAD_TIME parameter to 1,2,3 and 4 seconds. Then outputs of those dead time fb will hold analog  last 4 values (fifth value is current analog value). Inside a CALC you may copy into an array parameter (eventually, if array is not required  for other reasons, your application may work directly with dead time fb OUT parameters).

    The advantage of this approach is that you don't need to care about sampling cycle initialization and reset, even downloading module without getting bad values may be supported.

    Next PIC show that implementation. SGGN1 is configured to generate variable with SIN_AMP=60 and SIN_PERIOD=600. PARAMS1 to PARAM% hill hold last 5 values and are copied into ARR_OUT by CALC1.

    DISABLE parame is an extra, it allows to "equalize" al 5 values by demand.

  • In reply to gamella:

    gamella said:

    Using a Dead Time block could help here. This fb "delays" an analog value by DEAD_TIME seconds. So the easy way could be adding 4 dead time fb, setting their DEAD_TIME parameter to 1,2,3 and 4 seconds. Then outputs of those dead time fb will hold analog  last 4 values (fifth value is current analog value). Inside a CALC you may copy into an array parameter (eventually, if array is not required  for other reasons, your application may work directly with dead time fb OUT parameters).

    The advantage of this approach is that you don't need to care about sampling cycle initialization and reset, even downloading module without getting bad values may be supported.

    Next PIC show that implementation. SGGN1 is configured to generate variable with SIN_AMP=60 and SIN_PERIOD=600. PARAMS1 to PARAM% hill hold last 5 values and are copied into ARR_OUT by CALC1.

    DISABLE parame is an extra, it allows to "equalize" al 5 values by demand.

  • In reply to gamella:

    Next PIC show a module DOWNLOAD effect on this algorithm.

  • Thanks Matt and Andre for sharing your logic. I like that idea. will keep that in mind.

    Had the same request before, using a CALC block and a module scan of 1 sec

    OUT10 := OUT9
    OUT9 := OUT8
    OUT8 := OUT7
    .
    .
    .
    .
    OUT1 := AI/OUT

  • In reply to Andre Dicaire:

    Thank you for sharing your logic.
  • In reply to Rajeev Kumar:

    There are always multiple ways to configure a flexible tool like a DeltaV controller. Personal preference or comfort with the solution are important.

    Using a calc block to do the function of a function block is often not advised. Similarly using a group of blocks to do a programming function like populate an array will be a burdensome on CPU.



    Collecting a series of delayed signals in Dead time blocks could still require a calc block to process the values and adding more values means adding more code.

    Looking at programming methods for arrays, such tracking a pointer to the latest value. This allows data to be stored without moving existing value. Counting the number of stored values let's the array populate but the calculation only use the valid values.

    You can choose to also store the status in the array so you can determine the quality of the result. Maybe the value goes uncertain with a few bad signals and goes bad is more than 25 % of values are bad.

    The point is error checking is often more complex than the primary function being developed.

    It's my opinion In this case a calc block is the most efficient and flexible solution. Changing the size of the array can be done using the same fundamental structure. The code will be more efficient in cpu. Initialization of the array is important. The calc expression can use the sysstat parameter to detect a download to properly initialize the array.

    The use of deadline blocks as presented in this thread is not wrong, but it is more complex a solution and requires user set up in each block. One instance of this in a controller is negligible. If it is deployed often the CPU load must be considered.

    Good luck.

    Andre Dicaire