Our full technical support staff does not monitor this forum. If you need assistance from a member of our staff, please submit your question from the Ask a Question page.


Log in or register to post/reply in the forum.

AvgRun using Arrays


MThiessen May 19, 2021 03:58 PM

Greetings,

I am having a hard time understanding how to use the AvgRun function with both destination and source variables as array elements.

I have the following in my program within a subscan that repeats 16 times (there are 16 elements in SourceArray():

AvgRun(DestArray(i),1,SourceArray(i),6)

I want to have 16 separate running averages of the last 6 values of EACH element in SourceArray. So that DestArray() contains 16 separate running averages. I do not want an average across the elements of the source array.

The CRBasic Help page has this note on their AvgRun page:

"NOTE: This instruction normally should not be inserted within a For/Next construct with the Source and Destination parameters indexed and Reps set to 1. In essence this would perform a single running average, using the values of the different elements of the array, instead of performing an independent running average on each element of the array. The results of this would be a Running Average of a Spatial Average on the various Source array's elements."

Based on this note it does not sound like my code will work, but how else should I code it? Any help is greaty appreciated!


Nico May 19, 2021 08:31 PM

I have the following in my program within a subscan that repeats 16 times

How did you do that?
With a For/Next?
Or a counting variable in the scan loop, so only every 16th scan your code does the same sensor average.. and you hoping that the logger firmware has 16 instances of the RunAvg() function running in its memory and keeping track of each and every one of them?
I ask, because you clearly use an indexing variable for the RunAvg() arrays there.
I did the latter as a coding exercise some time go to see if I could sove some other problem, but never tested it so wont be of help there. ;-)

That being said.. does your subscan run 16 times before you got all 16 sensor values or does it do them in a loop of sorts within the subscan?
If the former you could introduce a counting variable that increases every subscan and once you reset it (after 16 times) you can have a If/Then instruction to run the RunAvg() instruction over the complete array of collected values.
If instead you got a loop within your subscan loop that runs through all your 16 sensors just put that RunAvg() after that loop has run?

One word of caution.. the help info says 'Scan/NextScan'.. not 'Subscan/NextSubscan'.
I don't know how the firmware/OS running on the logger keeps tracks of things internally.. especially with things like RunAvg().
Their wording could mean that the firmware has no means to keep track of several simultneous RunAvg() functions running alongside each other..

Anyhow.. for alternatives..
What I have seen done (and use, read: not 'invented by me') is to implement a table to do this, that you don't use as a output table but as an intermediary processing table with a depth of for your case 6 timestamps and put the values into it with the Average() instruction.
To get data from that table look into GetRecord() and GetDataRecord().


MThiessen May 20, 2021 07:21 AM

What I have seen done (and use, read: not 'invented by me') is to implement a table to do this, that you don't use as a output table but as an intermediary processing table with a depth of for your case 6 timestamps and put the values into it with the Average() instruction.

 This was my first thought until I ran across the RunAvg() function - which I assumed somehow internally kept track of several values of your variable for calculating purposes - is this not the case?

Here is the actual code:

 

    PortSet(C2,1)
    Delay(0,150,mSec)
    i=0
    SubScan(0,uSec,AReps)
      PulsePort(C1,10000)
      i=i+1
      BrFull(LC_A_mVpV(i),1,mV1000,1,Vx1,1,4000,True,True,0,_60Hz,1.0,0.0)  'Raw mVPerVolt reading.
      LC_A(i)=(LC_A_mVpV(i)*LC_A_Mult(i))+LC_A_oSet(i)  'Apply scalars.
      AvgRun(LC_A_RunAvg(i),1,LC_A(i),6)  'Calculate the 1-minute running average of each pot's weight
    NextSubScan
    PortSet(C2,0)

 

My boss originally wrote the code for measuring load cells some years ago and is asking me to edit it to use a running average of six values (measured every 10sec, so 1-minute average) instead since these load cells jump around quite a bit.

I'll explore the use of tables next - but in the meantime any other comments are very appreciated!


JDavis May 21, 2021 02:42 PM

 

SubScan(0,uSec,AReps)
      PulsePort(C1,10000)
      i=i+1
      BrFull(LC_A_mVpV(i),1,mV1000,1,Vx1,1,4000,True,True,0,_60Hz,1.0,0.0)  'Raw mVPerVolt reading.
      LC_A(i)=(LC_A_mVpV(i)*LC_A_Mult(i))+LC_A_oSet(i)  'Apply scalars.
      
    NextSubScan

AvgRun(LC_A_RunAvg(1),AReps,LC_A(1),6)  'Calculate the 1-minute running average of each pot's weight

 This is the alternative way you could do it. AvgRun can be done outside of the loop. Note the arrays are indexed to 1(the start of the arrays).

Log in or register to post/reply in the forum.