Average several readings pic10f220

microcontroller

I want to make an electronic device that Measures the wind speed in Beaufort. The definition of the Beaufort scale requires the calculation of an average over a period of 10 minutes. We choose to do this using the following principle (average with forgetfulness): filtre-passe-bas2.gif

For economical and space reasons, we choose to realize the RC filter by numerical simulation in the microcontroller.

Power supply: 3V analog output voltage proportional to the Beaufort scale with 0 corresponding to 0V Beaufort, 3V corresponding to 9 Beaufort (it will not show values above 9 Beaufort)
Interface to the LCD module: SPI (SPIdatas and SPI clk) Wind speed encoded in 8 bits

I think
i can Take readings say once a second (wind speed is relatively slow to change so no need to do it faster).
Add the reading to the previous one and halve the result so you get a running average.
Every 10 seconds send the speed scaled 0 – 9 to the LCD.

It is possible to store and average several readings but with only 16 bytes of RAM and some of that needed for the SPI software!! for me it hard to code .
The code is highly optimized That's why I come to ask your help :fs: and knowledge. Any ideas is welcome!

I start coding but I have difficulty to store and average several readings with only 16 bytes of RAM and some of that needed for the SPI software
Can anyone help me please?

movlw           b'00001001'     ;sets GP1 and GP2 as Outputs
    TRIS            GPIO
    movlw           0x41
    movwf           ADCON0

    movlw 0xC7
    option
;****************************************************************************   
;***** VARIABLE DEFINITIONS**************************************************
;****************************************************************************
    cblock    0x09

    Delay         ;variable for the delay ,to make delays
    Counter       ;variable to count how many measurements
    LCD_data      ;hold the data to be sent to the LCD 
    Counter_data   ; hold the counter for the bits as they are sent to the LCD

    endc
;**********************************************************************
;******************* coding begins*************************************
;**********************************************************************
    ORG     0x000             ; coding begins here
    movwf   OSCCAL         ; update register with factory cal value

start
    clrf LCD_data
    clrf Counter_data
    clrf Counter
    clrf Delay

;***********************************************************************
;                       remaining code goes here
;***********************************************************************
Wait
    movlw .15           ;reload 'Delay' again
    movwf Delay
    movlw 1         ;give TMR0 a start value
    movwf TMR0
Wait1
    movf TMR0,f     ;set Z in STATUS if TMR0 = 0
    btfss STATUS,Z      ;bit test the Z bit, skip if set (= Zero)
    goto Wait1          ;not zero yet so keep checking

    decfsz Delay,f      ;subtract 1 from Delay and see if zero
    goto Wait1          ;not reached zero yet so keep checking
    return
;********************************************************************
; read the voltage on the analog input pin, return result in W
;********************************************************************

ReadADC
    bsf ADCON0,GO_NOT_DONE  ;start measuring the voltage
ADC_Wait
    btfsc ADCON0,GO_NOT_DONE ;skip next instruction if GO/-DONE is zero
    goto ADC_Wait       ;not finished yet!
    movf ADRES,W        ;copy the result to W
    return

Best Answer

This is easily done using only 2 bytes of RAM if you implement a 256 times over-sampling filter.

You allocate 2 bytes of RAM to form a 16-bit counter. If you look carefully, you will observe that the upper byte contains the full value of the 16-bit counter / 256.

It is this property that makes this filter so easy.

I'm not at my computer, so I'll try to describe what I mean in pseudo code. Let's call the two bytes that form the counter CntrH & CntrL. As described above, the 8-bit value for the final output is contained in CntrH.

First, subtract the old filter value from the counter.

CntrH : CntrL - CntrH

Now add the 8-bit value from the a/d converter to the 16-bit counter.

A2D + CntrH : CntrL

The filtered output is contained in CntrH.

This is a very slow filter. Therefore, you want to seed the filter upon initialization by taking one a/d sample and loading it into CntrH.

This slow filter means that you want to add new samples fairly quickly. A rough approximation is that your desired filter period takes 256 samples.

In other words, add new samples to the filter at the rate of 10 minutes / 256.

[Edit]

This is extensible by going to a 24-bit accumulator if you want to acquire the samples at a faster rate. This would give you a 2^16 (65536) times over-sampling filter.

Same technique as above but using 3 bytes: CntrH : CntrM : CntrL . As before, the 8-bit filtered output is contained in CntrH.

Given that you want the period to be about 10 minutes (600 seconds), you would accumulate your samples at 600 / (2^16) =~ 9.1ms