Shop OBEX P1 Docs P2 Docs Learn Events
moving average/rolling average — Parallax Forums

moving average/rolling average

yarisboyyarisboy Posts: 245
edited 2010-10-15 18:32 in Propeller 1
Hi,
I searched the OBEX and this forum for a simple five sample simple moving average routine. I found one object that was way off the deep end for complexity. I would think some clever trick with absolute address space may be in order but I've never tried that yet with the Prop. Thoughts?

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2010-10-14 14:42
    This is not a complex problem. It can be done with a couple of lines of Spin. You need to save the old moving average, 3 most recent values, and the new value. Add them together and divide by 5 to get the new moving average and shift the other values "left" so your new "3 most recent values" are the 2 most recent values and the new value.
  • JonnyMacJonnyMac Posts: 9,208
    edited 2010-10-14 15:18
    I'm working on a project for a friend and was going to do something like this:
    pub newaverage(newvalue) | idx
    
      samples[samplepntr] := newvalue
      if (++samplepntr == 5)
        samplepntr := 0
    
      result := 0
      repeat idx from 0 to 4
        result += samples[idx]
    
      result /= 5
    
  • T ChapT Chap Posts: 4,223
    edited 2010-10-14 15:33
    Here is something I do to get an average of X number of values that are always updating inside a repeat:


    error := SomeValue
    Darray[2] := error - PrevError
    Daverage := (Darray[0] + Darray[1] + Darray[2])/3
    PrevError := error
  • John AbshierJohn Abshier Posts: 1,116
    edited 2010-10-14 16:12
    Here is another one. The constant ORDER is the number of terms in the moving average. This sample program prints out the values of the data array, then the sum, then the average.
    CON
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
      #1, HOME, #8, BKSP, TAB, LF, CLREOL, CLRLB, CR, #16, CLS      ' PST formmatting control
      ORDER = 4                                                     ' length of moving average
    OBJ
      Sio  : "FullDuplexSerialPlus"
    VAR
      long values[ORDER], sum, newValue, avg
      byte index
    Pub Main | i
      Sio.start(31,30,0,115200)  ' Rx,Tx, Mode, Baud
      repeat until Sio.rxcheck <> -1                        ' wait for PST
      
      Sio.str(string("Enter a value:   "))                  ' initialize with first value
      newValue := Sio.GetDec
      sio.Dec(newValue)
      Sio.tx(CR)
      sum := ORDER * newValue
      avg := sum / ORDER
      repeat index from 0 to ORDER - 1
        values[index] := newValue
      Display
          
      repeat
        newValue := GetValue
        index++                                             ' update value of index
        index //= ORDER
        sum -= values[index]                                ' remove oldest from sum
        values[index] := newValue                           ' insert new value in list
        sum += newValue                                     ' add new value to sum
        avg := sum / ORDER                                  ' calculate average
        Display
    
    PRI GetValue                                            ' get the value 
      Sio.str(string("Enter a value:   "))                
      result := Sio.GetDec
      Sio.Dec(result)
      Sio.tx(CR)
       
    PRI Display | i
      repeat i from 0 to ORDER - 1
        sio.dec(values[i])
        sio.tx(TAB)
      sio.dec(sum)
      sio.tx(TAB)
      sio.dec(avg)
      sio.tx(CR)
     
    {{
    &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
    &#9474;                                                   TERMS OF USE: MIT License                                                  &#9474;
    &#9500;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9508;
    &#9474;Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation    &#9474;
    &#9474;files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,    &#9474;
    &#9474;modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software&#9474;
    &#9474;is furnished to do so, subject to the following conditions:                                                                   &#9474;
    &#9474;                                                                                                                              &#9474;
    &#9474;The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.&#9474;
    &#9474;                                                                                                                              &#9474;
    &#9474;THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE          &#9474;
    &#9474;WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR         &#9474;
    &#9474;COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,   &#9474;
    &#9474;ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                         &#9474;
    &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
    }}
    

    John Abshier
  • BRBR Posts: 92
    edited 2010-10-14 17:35
    pub ma4(x_meas):x_ret
    ''4-sample moving average filter, implemented with recursion.
    ''Max filter update rate ~13000 samples/sec for 1 cog @ clkfreq=80
    
      ptr &= %00000011                         'mask off all but lower two bits
      sum := sum + x_meas - x_buf4[ptr]
      x_buf4[ptr] := x_meas
      x_ret := sum ~> 2                        'divide sum by 4
      ptr++
      
     
    pub ma16(x_meas):x_ret
    ''16-sample moving average filter, implemented with recursion.
    ''Max filter update rate ~13000 samples/sec for 1 cog @ clkfreq=80
    
      ptr &= %00001111                         'mask off all but lower four bits
      sum := sum + x_meas - x_buf16[ptr]
      x_buf16[ptr] := x_meas
      x_ret := sum ~> 4                        'divide sum by 16
      ptr++
    
    dat                                
    '-----------[ Predefined variables and constants ]-----------------------------
    x_buf4         long      0,0,0,0           '4-place filter input history buffer
    x_buf16        long      0,0,0,0,0,0,0,0   '16-place filter input history buffer
                   long      0,0,0,0,0,0,0,0   
    sum            long      0
    ptr            byte      0                 'pointer (set up as ring buffer)
    
    
  • WBA ConsultingWBA Consulting Posts: 2,935
    edited 2010-10-14 20:40
    These are some really nice code samples for averaging. I will be coming back to this thread soon when I get the Polar Heart Rate Monitor receiver chip as creating an optimum logging program will require some good averaging as well as ruling out sporadic readings. I have the notes for creating an ideal algorithm, and this thread will address a good portion of the SPIN code
    I will need. THANKS!!!
  • yarisboyyarisboy Posts: 245
    edited 2010-10-14 20:42
    Thanks Jon,
    I won't have it in the EEPROM until Friday. I'll be able to see the effect on the tachometer DRO on the commute to work on Saturday. Switching to cat 5 cable and tightening the connections to the breadboard already killed some of the display jitter. jw_freqin is working well at 5 samples per second.
    Stan
  • yarisboyyarisboy Posts: 245
    edited 2010-10-15 05:38
    If I'm understanding it correctly, the comments I added to Jon's contribution should make it clear as mud for spin newbes like me. I do appreciate the help.
  • KaosKiddKaosKidd Posts: 296
    edited 2010-10-15 06:36
    LOL @
    yarisboy wrote: »
    If I'm understanding it correctly the comments I added to Jon's contribution should make it clear as mud for spin newbes.
  • JonnyMacJonnyMac Posts: 9,208
    edited 2010-10-15 10:12
    ...for spin newbes like me.

    As spoon-feeding is demanded, let the spoon-feeding begin.... <grin>

    The attached demo uses PST to display the array values as well as the average. The display is refreshed after each new entry.
    485 x 442 - 18K
  • yarisboyyarisboy Posts: 245
    edited 2010-10-15 18:32
    JonnyMac wrote: »
    As spoon-feeding is demanded, let the spoon-feeding begin.... <grin>

    The attached demo uses PST to display the array values as well as the average. The display is refreshed after each new entry.

    Way cool! I now have two data streams to smooth because this evening I got the programmable speedometer read out working in concert with the tachometer. 90% of the software is the same. The breadboard and coding stage of the project now stands at 50% complete.
Sign In or Register to comment.