View previous topic :: View next topic |
Author |
Message |
notbad
Joined: 10 Jan 2013 Posts: 68
|
ADC result jumps between two numbers after averaging |
Posted: Mon Apr 01, 2013 5:57 pm |
|
|
Hello everyone
I want to use an ADC module to read a potentiometer and generate 1000 different nonlinear frequencies according to ADC result.
The problem is sometimes even after averaging, resulting value jumps between two consecutive numbers.
I want the value to be “locked” after I let go of the pot.
Tried changing the following things with no help: reading intervals, number of samples, clock sources, using statistical “mode” etc.
Code: | #include <18F26K22.h>
#device adc=10
#FUSES NOWDT, WDT128, HSH, NOPLLEN, NOFCMEN, NOIESO, PUT, NOBROWNOUT, WDT_NOSLEEP, NOLVP, NOXINST
#use delay(clock=16000000)
#use rs232(UART2,baud=2400,parity=N,bits=8)
int16 val;
int16 temp;
int16 AdcSum;
int8 n=0;
void main()
{
setup_adc_ports(sAN0);
setup_adc(ADC_CLOCK_DIV_32);
set_adc_channel(0);
while(1)
{
delay_ms(10);
AdcSum+=read_adc();
if(++n==64)
{
n=0;
temp=AdcSum/64; //uses shifts
AdcSum=0;
if (temp!=val)
{
printf("%Lu ", temp );
val=temp;
}
}
}
} |
any ideas?
thanks |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Mon Apr 01, 2013 6:04 pm |
|
|
Maybe it's just me but...
are you saying that with the pot in one position, that the ADC result is giving you say 12000,12002,12000,12000,12002 ?
If so, that would be acceptable, if the ADC input doesn't have any filtering( a small .1mfd cap) or the +5 supply has ripple( as it's the Vref).
Perhaps if you showed us(ok, me) some real numbers(input vs output) would help.
Also what value pot?
hth
jay |
|
|
gpsmikey
Joined: 16 Nov 2010 Posts: 588 Location: Kirkland, WA
|
|
Posted: Mon Apr 01, 2013 6:31 pm |
|
|
As Jay indicates, without actual number examples, it is tough to say, however, unless you have vref and the supply to the pot nailed down and bypassed, you can expect some wandering. It can also be an issue with the pot if it is too high an impedance (the input impedance to the ADC is not very high so if the signal in is high impedance, strange things can happen).
Hmmm - 12000 from a 10 bit A/D ? April 1 ?
mikey _________________ mikey
-- you can't have too many gadgets or too much disk space !
old engineering saying: 1+1 = 3 for sufficiently large values of 1 or small values of 3 |
|
|
languer
Joined: 09 Jan 2004 Posts: 144 Location: USA
|
|
Posted: Mon Apr 01, 2013 7:14 pm |
|
|
a hardware filter should help, a median filter in software may also help. it looks like you are only getting the LSB jumping, so you could discard that as well. |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Mon Apr 01, 2013 7:19 pm |
|
|
Code: |
int16 val=0;
int16 temp=0;
int16 AdcSum=0;
int8 n=0;
void main()
{
setup_adc_ports(sAN0);
setup_adc(ADC_CLOCK_DIV_32);
set_adc_channel(0);
while(1)
{
delay_ms(1); AdcSum+=read_adc();
if(++n==16) {
n=0;
temp=AdcSum>>4;
AdcSum=0;
}// did 16 reads
if ((temp>=(val+1)) || ((temp-1)<=val) ) {
printf("%Lu ", temp );
val=temp;
} // mismatch
}// while
}//main
|
show your schematic....... |
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1615 Location: Central Illinois, USA
|
|
Posted: Mon Apr 01, 2013 8:42 pm |
|
|
gpsmikey wrote: |
Hmmm - 12000 from a 10 bit A/D ? April 1 ?
|
I was just about to say the same thing!
That's awesome resolution for an A/D that only reads back 0 to 0x3FF! (1023d)
-Ben _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
|
SSR
Joined: 09 Nov 2011 Posts: 14
|
|
Posted: Mon Apr 01, 2013 11:59 pm |
|
|
Can any body tell me how the apparent program is averaging values?
May be with this
Code: |
AdcSum+=read_adc();
....
temp=AdcSum/64; |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Tue Apr 02, 2013 1:00 am |
|
|
Yes.
He loops 64 times adding the reading each time, then divides the result by 64.
There is a problem though, that as written the code will always round 'down'.
On the original question, How is the processor meant to 'know' that the pot is not being moved?.
If you stop a pot at a point between two ADC readings, and the ADC is working 'perfectly', then the output _will_ give you a stream of values jumping between the readings each side, with the ratio of the two readings being the distance the actual value is between the points...
It is never going to be still.
Best solution is to have a 'read' button, which you press to adjust the pot. When this is released, the last reading is held, and you stop reading the pot.
Best Wishes |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Tue Apr 02, 2013 1:56 am |
|
|
Quote: | The problem is sometimes even after averaging, resulting value jumps between two consecutive numbers. |
Of course it does.
That's the nature of the beast.
It's the best you can expect!
Mike |
|
|
SherpaDoug
Joined: 07 Sep 2003 Posts: 1640 Location: Cape Cod Mass USA
|
|
Posted: Tue Apr 02, 2013 5:35 am |
|
|
You may have to program in a "threshold". If the new reading is not significantly different from the old reading then ignore it. _________________ The search for better is endless. Instead simply find very good and get the job done. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Tue Apr 02, 2013 5:46 am |
|
|
oops, sorry guys,me think I have to clean my 21 year old keyboard again! Too many coffee spills....sigh..
I reread the OP and it almost sounds like he wants 1000 'random' numbers, generated by twisting a pot to 'create' them. If so, then the numbers can be 'close' or same'. RNGs can dump out the same number twice,after all it is 'random'.
I'd still like to see an example of 'good' versus 'bad' numbers though as I can't read what he really wants.
hth
jay |
|
|
yerpa
Joined: 19 Feb 2004 Posts: 58 Location: Wisconsin
|
|
Posted: Tue Apr 02, 2013 11:58 am |
|
|
You will not be able to accurately select 1000 unique values with a single-turn potentiometer. Even a small fraction of one degree of rotation will change your values by several counts. In addition, the PIC a/d converter is probably specified to be +/- one bit of accuracy, so you will have to throw away the least significant bit anyway.
It seems that eight bits is about the most you can reliably read from a potentiometer. |
|
|
notbad
Joined: 10 Jan 2013 Posts: 68
|
|
Posted: Tue Apr 02, 2013 2:09 pm |
|
|
wow ...thank you everyone for your reply
Here is the schematic but technically its nothing.
The hardware is acting normal. I want a software solution to ignore that edge jump.
@temtronic - the numbers after averaging are like: 511,512,511,512,511 (not always, only sometimes)
@gpsmikey - pot is 10k
@languer - hardware and software filters are in use. The problem is not LSB.
@yerpa - the pot is multi-turn
@SherpaDoug - I need 1000 of those 1024 values so i can't ignore ±1 because that's the resolution i need.
@asmboy - thanks but the code didn't work and I don't understand what it is supposed to do.
Isn’t temp>=(val+1) same as temp>val ?
@Ttelmah - the button would fix this but I need to do it using the pot only.
Quote: | How is the processor meant to 'know' that the pot is not being moved? |
That’s exactly the problem here.
One of my friends told me to pick the greater value of the two, but how should PIC know that the pot is not actually moved down?
Another idea is to accept the new value only if it is repeated 10 times in a row but I don't know how to code it and I'm not sure it would work. |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Tue Apr 02, 2013 4:17 pm |
|
|
You've got a fundamental problem.
You're trying to somehow use the 1024 counts from a 10 bit ADC to create 1000 different frequencies.
It's just not possible, no matter how much filtering you do.
(Either hardware, software, or multiturn pot.)
At some point it's inevitable you're going to be on the edge between two adjacent counts.
It might be possible if you used a higher resolution ADC or accept fewer frequencies.
Suppose you used a 12 bit ADC, i.e. counts from 0 to 4096.
Counts 0,1,2,3 generate frequency 0
Counts 4,5,6,7 generate frequency 1
Counts 8,9,10,11 generate frequency 2 etc.
The problem then is to ensure that the pot is in the centre of each range.
And that the pot is not close to the edge of it's range and likely to wobble between ranges.
One way to achieve this might be to use a system similar to AFC for radio recievers.
Suppose you use a PWM output to create a DC offset to the ADC input.
If the pot is actually set to say 7, the offset pulls the adc input to give either 5 or 6 as ADC output.
If the pot is actually set to 4, the offset pulls the other way to also give 5 or 6 as output.
You then arrange the offset so that it can't pull the ADC output by more than 1 count.
So when the ADC real value is say 9, the count can't be pulled to the range below.
The effect would be that the frequency jumps as the pot is moved, with some hysteresis.
Mike
EDIT You may even get away with a simple resistive D2A conversion.
Coding would go something like:-
If ADC output is in top half of a range then pull ADC input down.
If ADC output is in lower half of a range then pull ADC input up.
Hardware filtering would provide a smoothing effect. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Tue Apr 02, 2013 5:27 pm |
|
|
Just thinking here ...
...but if the purpose is to have an 'input device' choose 1000 'options', then a pot/ADC combo isn't the choice due to physical and electrical constraints. Even a ten turn or 20 turn pot is questionable.
A better option would be to use a quadrature encoder. It'll cost you an extra I/O pin, but 1000 counts, even 4000 counts can be easily had.
Would this be acceptable?
If not, can you rephrase what you're trying to accomplish? The more we know, perhaps we'll see a simple, easy solution!
hth
jay |
|
|
|