ADC Averaging

MikeGyver

Senior Member
I've been searching and I'm still having a hard time figuring this out.

I'm using a multiplexed triple 7 segment display and I'm trying to settle it down some from alternating between 2 adjacent values by adding some hysterisis.

How can I readacd like 5 times, and set my word value (w0) to the average? (ideally in as few lines as possible)

Thanks
 

hippy

Ex-Staff (retired)
ReadAdc pin, b1
ReadAdc pin, b2
ReadAdc pin, b3
ReadAdc pin, b4
ReadAdc pin, b5
w0 = b1 + b2 + b3 + b4 + b5 / 5

Or some variation on that including putting the code into a loop

You could create a simpler 'rolling average' every loop which only requires one reading per loop -

ReadAdc pin, b2
w0 = w0 + b2 / 2
 

Dave E

Senior Member
This is how I do it:

W2 = 0
FOR X = 1 T0 25
READADC PIN, W0
W2 = W2 + W0
NEXT
W0 = W2 / 25 'W0 WILL CONTAIN 25 READINGS AVERAGED

You can set the number of averaged readings from 1 to 257 if you are using READADC or from 1 to 64 if using READADC10.

Dave E
 

BCJKiwi

Senior Member
An alternative is to use an accumulator/FIFO.

The advantage here is that only one read is required per program cycle
The disadvantage is that the FIFO values need to be stored over program cycles. The sample below is from a simple program so the W variables were available but these could be stored if the variables were not free.

The following snippets are from a rev counter program utilising the count command but the same principle will work for ADC readings.
When starting, stopping, or making rapid changes, the value output ramps up or down.

Of course the number of values in the FIFO and the integer math manipulation should be varied as required to suit your project conditions.


Code:
symbol FIFO_1  = w3     ;FIFO accumulator
symbol FIFO_2  = w4     ;FIFO accumulator
symbol FIFO_3  = w5     ;FIFO accumulator
symbol FIFO_4  = w6     ;FIFO accumulator
symbol FIFO_SUM = w7     ;Average of FIFO Accumulator
 
Accumulator:
;Sum the last 4 Count values to smooth output
;* 6 to improve resolution of integer math
FIFO_1 = FIFO_2
FIFO_2 = FIFO_3
FIFO_3 = FIFO_4
FIFO_4 = Count_In * 6
FIFO_SUM = FIFO_1 + FIFO_2 + FIFO_3 + FIFO_4 ;24 * Sum of last 4 Readings
RPM = FIFO_SUM * 6 / 24      ; *6 for 416.67 counts == 2500rpm
Return
 
Last edited:

Dave E

Senior Member
Sometimes integer math throws me off so correct me if I am wrong.

Largest number you are able to store in a WORD variable = 65535
Largest number you are able to store in a BYTE variable = 255 (256 levels read by READADC which are 0 - 255)

65535 / 255 = 257
Therefore, one could store the accumulation of at least 257-8 bit readings in a WORD variable.

If using READADC10 (10 bit), the largest number returned will be 1023 (2^10 = 1024, readings will be from 0 to 1023)

65535 / 1023 = 64.06 ..... rounded to 64 whole number

I have found that taking 50 - 100 readings doesn't take much time. I generally use READADC10 and average 25 readings.

Dave E

P.S. FYI

According to my hacked stop watch connected to a 20X2:

At 4 MHz:
257 READADC readings take 0.89 seconds, 5 readings take 0.04 seconds.

At 8 MHz:
257 readings = 0.44 seconds, 5 readings = 0.02 seconds

So, unless you require the fastest program you can have, take a lot of readings to stabelize the display.
 
Last edited:
Top