CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

ADC result jumps between two numbers after averaging
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
notbad



Joined: 10 Jan 2013
Posts: 68

View user's profile Send private message

ADC result jumps between two numbers after averaging
PostPosted: Mon Apr 01, 2013 5:57 pm     Reply with quote

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: 9225
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Apr 01, 2013 6:04 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Apr 01, 2013 6:31 pm     Reply with quote

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 ? Very Happy

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

View user's profile Send private message

PostPosted: Mon Apr 01, 2013 7:14 pm     Reply with quote

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

View user's profile Send private message AIM Address

PostPosted: Mon Apr 01, 2013 7:19 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Apr 01, 2013 8:42 pm     Reply with quote

gpsmikey wrote:

Hmmm - 12000 from a 10 bit A/D ? April 1 ? Very Happy


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

View user's profile Send private message AIM Address

PostPosted: Mon Apr 01, 2013 11:59 pm     Reply with quote

Can any body tell me how the apparent program is averaging values?

May be with this Question

Code:

AdcSum+=read_adc();
....

temp=AdcSum/64;
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Tue Apr 02, 2013 1:00 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Apr 02, 2013 1:56 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Apr 02, 2013 5:35 am     Reply with quote

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: 9225
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Tue Apr 02, 2013 5:46 am     Reply with quote

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

View user's profile Send private message Visit poster's website

PostPosted: Tue Apr 02, 2013 11:58 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Apr 02, 2013 2:09 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Apr 02, 2013 4:17 pm     Reply with quote

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: 9225
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Tue Apr 02, 2013 5:27 pm     Reply with quote

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
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group