Electronics > Projects, Designs, and Technical Stuff

Stabilizing analog read on a potentiometer

(1/5) > >>

Etesla:
Hi all, I am trying to address an issue that pops up from time to time. When I use an ADC on a microcontroller to read a potentiometer, I find that more often than not, the ADC reading fluctuates a lot. For me, this is problematic. What are some ways to minimize ADC reading flickering? I believe that the solution will be in software, as no amount of filtering or caps across the potentiometer seem to help in the case where I have the pot adjusted right between two ADC steps. Is there a common sort of algorithm designed to deal with this, I imagine, fairly common issue? I'm thinking of some sort of averaging and buffer type stuff, but I don't want it to get too complicated. Thanks in advance!

p.s. I would have gone with an encoder, but the PCB is already made with the potentiometers, and I don't have time to make a new one

guenthert:
I see there two distinct issues
i) fluctuations in the value reported by the ADC regardless of the source (typically referred to as "noise")
ii) fluctuations in the voltage when using the potentiometer as a voltage divider.

For i) check your ADC's (or microcontroller in this case) manual for noise specifications.  What you observe might be well within the specs.  The manufacturor might have also recommendations on how to minimize the noise (e.g. seperate analog and digital GND, turning off other facilities of the MCU during conversation, etc.).  And yes, this can be addressed also in software.  Easiest might be to throw away the lowest bits.  If your MCU has a 10b ADC, but you need to distinguish only some 100 potentiometer positions, you can mask the lower three or four bits.  With any luck, that's all you need to do.  Then there's of course averaging and decimation.  Lots of info (and application notes) about that.  Keep in mind that the noise is distributed across a wide spectrum, but the potentiometer is going to be turned only so fast --> digital low pass filter. Google is your friend.

ii) if the potentiometer isn't turned, there shouldn't be any noise (other then Johnson noise of course).  There might be some noise (non-monotonic change of potential at the wiper) when turning.  That can be reduced by connecting a capacity between the wiper and one of the other terminals.

Kleinstein:
Unless there is something really wrong (like missing decoupling, to high a pot value)  there should not be much noise in reading the potentiometer. How much depends on the µC. Normally the pot should use the same reference as the ADC - so both using VCC or both from an external reference.

The usual way to reduce noise is filtering in software, like averaging over several readings. Usually averaging 4 reading could reduce the noise by a factor of 2.   Averaging over a multiple if a power line period (e.g. 16.6 ms or 20 ms) can give additional suppression of power line related hum - however with just a pot this should normally not be an issue.

Nominal Animal:
It is possible the ADC is flipping between two results, because the voltage it measures is between those two values.

Let's say the potentiometer value used is V. Sum N potentiometer samples at regular intervals into S.  If S <= (V-1)×N or S >= (V+1)×N, update V = S/N; otherwise keep V unchanged.

This means that the value you use for each potentiometer only changes every N samples.  You'll need at least a 16-bit variable for each potentiometer, and you might want to use a power of two N (16, 32, 64, 128, or 256) to keep the division simple.  (It also biases zero over 255, as it rounds towards zero.  That is fixable.)

duak:
What microcontroller or A/D are you using?  How many LS bits of noise are you seeing?

Do some values seem to be sticky or more common?  If the A/D is a successive approximation converter without using a Sample and Hold in front of it will tend to give a more noisy data stream.

Others have  suggested stronger or more effective filters by averaging a number of samples and may be needed to get around noisy data.

A code tragment implementing a simple low pass filter with characteristics similar to that of a first order filter is:

 static int result = 0;
 result = (GetAtoDSample() + result) >> 1;

What this does is take the newest sample and adds the previous value and then divides by two.  The previous value is of course half of the previous sample plus half of its previous value, and so on.  If I remember my constants correctly, an RC network is equivalent to the sum of 63.2 % of  the sample and 36.8 % of the previous value but that's a bit harder to do with simple adding and shifting.  Note that the variable result has to be persistant so that it can keep a running average of the samples.

Navigation

[0] Message Index

[#] Next page

There was an error while thanking
Thanking...
Go to full version
Powered by SMFPacks Advanced Attachments Uploader Mod