Welcome to our new forum
All users of the legacy CODESYS Forums, please create a new account at account.codesys.com. But make sure to use the same E-Mail address as in the old Forum. Then your posts will be matched. Close

average function

pautorras
2014-01-20
2014-01-24
  • pautorras - 2014-01-20

    Hi,

    I want to make an FB to make an average of a var_input (integer type).

    Example:
    VAR_INPUT
    value:int;
    trigger_time_pulse:time;
    number_of_values:int;
    END_VAR
    VAR
    values: array of int [0..sizeof(number_of_values-1)]; //This is not working
    I: INT;
    ............
    END_VAR

    I want to put the value into the array values. The index of the array increases consecutively with the trigger of pulse timer (trigger_time_pulse).
    Then I need to know the average of the whole array.

    How can I do an array with dinamic lenght depending of var_input integer value?
    Is there any function to make the average value of an array of number_of_values?

    Thanks in advance,

    Pau

     
  • Anonymous - 2014-01-20

    Originally created by: Captive Engineer

    Hi, Pautorras.

    What you are trying to do is possible, but there are a couple of problems with your way.

    First, an array declaration usually needs to have a set of constant values for the range, so declaring in your VAR section the upper limit of the range as one of your input variables is not going to compile. A variable defined as a CONST would probably work so long as you define/initialize it before the Average function block is declared. Of course, this is not really the solution you seem to be after since it appears that you want to take a number of samples that is unknown at compile time.

    A lesser problem which goes away once we adjust your syntax is seen in the following line of code. . .

    values: array of int [0..sizeof(number_of_values-1)]; 
    

    This line is incorrect for at least two reasons. First, the SIZEOF function returns the size of the variable type in parenthesis, i.e. the argument, in terms of bytes of memory. Since number of bytes in an INT is normally 2, this part of the expression would probably compile but give you an array of only 3 elements numbered 0 to 2. Keep in mind that even though you subtract one from the number_of_values, the SIZEOF function still evaluates the whole expression in parenthesis as an integer type, so the resulting value is still 2. Of course, the code above should not compile since the OF INT should be after the range declaration instead of in front of it, like so . . .

    values: array [0..Some_Constant_Value] of int;
    

    Now, if you are sure that you do not know exactly how many values there will be, you need to answer a couple of questions:

    1) Do you need to store all the values, or do you simply need to calculate a running average as you collect more samples?
    2) If you do need to store all the values, do you know what is the absolute maximum number of values that you will need to average?

    If you really just want the average, you might be able to divide a running sum by the number of values you have when you read each new value. This is an easy solution as long as your numbers do not sum to something too large or your number of sample values also does not become too great. Remember, the maximum positive value of an INT is 32767. If this limitation could be a problem when you add lots of positive numbers, you may want to convert your values to REAL or even LREAL values as you collect each one.

    If you do need to store all the values but you know that your value count will never exceed some limit, say for example 1000, you could make the array that large. Remember, though, that to average all the numbers at once can take a long time, especially if your array is huge. You may find it to your advantage to keep the running sum as you store each new value. It all depends on your particular requirements.

    There is at least one other possibility if you want to make your own solution, especially if you require dynamic length. You could make use of dynamic memory allocation using __NEW and __DELETE and POINTER operations, setting aside data space for each value as you collect it. This is considered to be advanced programming, so if you are still learning the rudiments of CoDeSys, you may want to hold off on this approach.

    As far as a library for doing averages, http://www.oscat.de

    I shall try to keep looking at this thread for a few days in case you have more questions.

    Kind regards,
    The Captive Engineer

     
  • shooter - 2014-01-24

    have a look at w www.oscat.de w for functions and blocks , also average etc.

    why array not static and use only part of it.
    average can also be very simple adding them all and divide by number of samples.
    if walking average you will need an array yes.

     

Log in to post a comment.