Stable Adc Reading Routine
Dear friends
Recently I came across an AVR application note about an intelligent charger
design based on their controller line.
There was a so called STABLE ADC READING FUNCTION
(not explained in detail ) which was used for getting valid ADC readings.
The following is copy-paste from there.
.................................................. ..................
void stable_ADC(void)
The stable_ADC function is used when measuring battery
voltage or temperature. It makes sure the ADC values are
stable inside a defined area. This is important for an accurate
measurement. The function loops until it gets three
ADC values where the highest is no more than one step
higher than the lowest.
.............................................
There was a pseudo c flowchart but I was not able to follow it through.
stable_ADC
|----------------- V[0] > V[1]+1 No ----------------------------- > return
| Yes
| V[5] = V[4]
| V[4] = V[3]
| V[3] = V[2]
| Start ADC
| ADC done? No ------>-continue conversion
| Yes
| V[2] = ADC
| V[1] = highest value of V[2] to V[5]
| V[0] = lowest value of V[2] to V[5]
| |
| |
-----------------------
I wonder if someone can help in implementing this for picbasic as I would like to
use it in order to improve ADC readings on a PIC12F675 .
At the moment I am adding 64 consecutive values in order to approximate a 16
bit result and by floating point math to end up to my final reading which is not
very stable.
Bill
junk the top and bottom four readings
Hi Bill,
Melanie’s great idea:
Quote:
Originally Posted by Melanie
take say 16 ADC readings, sort them in sequential order of value, junk the top and bottom four readings as being 'out-of-range', sum and average the middle eight... this makes ADC readings in industrial applications pretty much bomb-proof...
http://www.picbasic.co.uk/forum/showthread.php?p=41702
It would be interesting to see a “real world” working example of this technique written for a PIC’s 10 bit ADC.
-Adam-
my co-workers have noticed
Hi Melanie,
Thanks a bunch, this is really easy to understand.
You are spot on, it is overwhelming looking at the problem. Trying to get a foothold.
But not so bad step by step.
Of coarse it is easy with the code as an example.
I will study the whole thing. I learn, not just from your excellent example of how to code it. But, from the style of logic flow and layout. It is good, the way you comment lines of code that seem obvious to you but cause a noobe to pause and check. This allows us to get beyond the mechanics quickly, and see the part you are showing us.
I have saved this example and will try to learn and build from it. You’re the greatest!
(notice the "spot on", my co-workers have noticed my accent growing!)
-Adam-
Re: Stable Adc Reading Routine
I tried to use Melanie's great piece of code (Thanks !) for sorting the values I read with 12F675 ...
But the results are ...strange ; the schematic wont work as I wish.
It's something wrong in my code ? Thanks in advance !
Code:
CounterA var BYTE ' Just a BYTE Temporary working variable
DataW var WORD ' Just a WORD Temporary working variable
RawData var WORD [10] ' Array holding ADC Result
............
Main:
For CounterA=0 to 9
ADCON0 = %10001001
Pauseus 50 ' Wait for channel to setup
ADCON0.1 = 1 ' Start conversion
While ADCON0.1=1:Wend ' Wait for conversion
DataW.HighByte=ADRESH ' Read variable from ADC and save
DataW.LowByte=ADRESL
RawData(CounterA)=DataW
Next CounterA
gosub getsort
CounterA=0
if (ADvalue < 650) then
IF (ADvalue > 450) AND (ADvalue < 640) THEN gosub do_1
IF (ADvalue > 320) AND (ADvalue < 440) THEN gosub do_2
IF (ADvalue > 180) AND (ADvalue < 310) THEN gosub do_3
IF (ADvalue > 90) AND (ADvalue < 170) THEN gosub do_4
IF (ADvalue < 80) THEN gosub do_5
endif
Goto Main
;=========================
; here are the commands
GetSort:
If RawData(CounterA+1) < RawData(CounterA) then
DataW=RawData(CounterA)
RawData(CounterA)=RawData(CounterA+1)
RawData(CounterA+1)=DataW
If CounterA>0 then CounterA=CounterA-2
endif
CounterA=CounterA+1
If CounterA<9 then goto GetSort
DataW=0
For CounterA=2 to 9
DataW=DataW+RawData(CounterA)
Next CounterA
Advalue=DataW>>3
return
Re: Stable Adc Reading Routine
Me ... again ...
Tried to use Mr.Darell (RIP :( ) routine :
Code:
include "D:\PBP\average_DT.pbp"
Main:
ADCON0 = %10001001
Pauseus 50 ' Wait for channel to setup
ADCON0.1 = 1 ' Start conversion
While ADCON0.1=1:Wend ' Wait for conversion
value.HighByte=ADRESH ' Read variable from ADC and save
value.LowByte=ADRESL
gosub Average
advalue=value
if (advalue < 650) then
IF (advalue > 450) AND (advalue < 640) THEN gosub do_1 ...
IF (advalue > 320) AND (advalue < 440) THEN gosub do_2 ...
...
endif
Goto Main
...but something is wrong - always is executed do_1 subroutine
Note : the code in his "simple" variant, works just fine . Just I want more "accuracy" ...
Code:
advalue var word
advaloop var byte
advaltot var word
pause 200
Main:
advaltot=0
advaloop=0
ADCON0 = %10001001
PAUSEuS 50 ' Wait for A/D channel acquisition time
ADCON0.1 = 1
for advaloop = 1 to 20
WHILE ADCON0.1 = 1 : WEND
advalue.HighByte = ADRESH
advalue.LowByte = ADRESL
advaltot=advaltot + advalue
next advaloop
advalue=advaltot / 20
if (ADvalue < 650) then
IF (ADvalue > 470) AND (ADvalue < 640) THEN gosub do_1
IF (ADvalue > 320) AND (ADvalue < 450) THEN gosub do_2
...
endif
Goto Main
Re: Stable Adc Reading Routine
Your implementation of Mel's sort algorithm has a problem in it.
After you read the ADC values in the "For CounterA = 0 to 9" loop, CounterA equals 10.
You then issue the "Gosub GetSort" statement.
Since CounterA = 10 the following line is pointing at memory locations beyond the RawData array.
"If RawData(CounterA+1) < RawData(CounterA) then"
This says If RawData(11) < RawData(10) then....
You need to set CounterA to 0 before calling GetSort.
Re: Stable Adc Reading Routine
Also you did not declare "Advalue" as a variable either.
Re: Stable Adc Reading Routine
Thanks !
In post #6 of Mel's I see the same sort procedure as mine ... why mine is wrong ?!
Advalue is var word ...
Re: Stable Adc Reading Routine
Quote:
In post #6 of Mel's I see the same sort procedure as mine ... why mine is wrong ?!
Simple because, ad mentioned by Tabsoft, you have forgotten to clear the variable 'CounterA' before entering the sorting routine.
Cheers
Al.