Stable ADC Readings with Potentiometer

In recent weeks I tried to solve an old problem, a problem that haunts me for some time. I want to use a regular, inexpensive, common, ordinary potentiometer with an ADC. Also an inexpensive, common, ordinary ADC that we can find in almost all microcontrollers these days. And doesn’t matter if we are talking about 8, 16 or 32 bit MCUs…
And I do not want to go crazy. If you tried something like that you know what I mean…
Because I want stable ADC readings with potentiometer. Stable… ie when I do not move the potentiometer knob, the value must to be steady, without the slightest oscillation, (even +/-1). Even if this task seem to be very simple, when we get down to facts, we see that (almost)nothing fits with the theory.

There is no point to review in detail all attempts to solve once and for all this issue. Instead, I will try to summarize my whole experience(and experiments) on this field.

I started with the “classical” schematic for reading a potentiometer.

Hardware measures

  • Good filtration of power supply. I’m not going to put a schematic here, because it depends on actual power source. The idea is that should be well filtered and stabilized.
  • Good filtration of AVcc supply. All microcontrollers that have ADC module also have a pin called AVcc or AVcc (or AVdd ?). It is the power for the ADC (Analog to Digital Converter) and is and it is placed separately to be filtered separately. C2 can be main decoupling capacitor for the MCU, so for AVcc can be used only C1 and L.avcc_filter
  • Capacitor on VREF pin. A capacitor put on VREF (Voltage reference) it is also a technique to reduce ADC noise. aref_cap
  • Potentiometer capacitor. A capacitor with value 1..10uF will stabilize readings also.


Software measures

I made an extensive research about “software ADC filtering”, and I tried various techniques, algorithms and ideas. I must say that I have not found even one solution that works as expected. Finally I decided to try a combination of two algorithms. It’s obvious that at first I tried them separately, but I noticed that work very well together, especially for this goal (stable ADC readings with potentiometers).

  • Olympic average – I met this term in various discussions and I decided to document and try it myself.
  • Exponential Moving Average – this kind of average have the characteristic to “lock” on value. This formula is taken from wikipedia and we will adapt to our goal.ema-wiki We will “translate” this formula to C code as follows (I chose alpha = 0.1  trough some experiments):
    alpha = 0.1 = 1/10 and 1-alpha = 1-1/10 = 9/10; so we can transform this with approximation in integer calculation:
  • Putting all together


The method shows a clear reduction in resolution, but we should not worry at all. No one has such mechanical accuracy so can’t exploit more than 100-150 virtual subdivisions of this kind of analog potentiometer.

Even if the code presented here is for Arduino, it is obvious that it can be used with a C or C++ compiler for a different microcontroller. I started experiments with a STM32F103 (blue pill) and after some progress I switch to AVR because I had this development board made/designed by me, so I was sure of filtering Vdd, AVdd and ARef:


Some practical and economic considerations:

These experiments were started with the thought of making a MIDI controller. Thus appeared the need to use many potentiometers like 16 or 32 or even more. And so we need to use not-so-expensive potentiometer. (In fact I use the most cheaper I can found 🙂 ).
If more precision is neded we can be use a multi-turn potentiometer. I have not tried this. Maybe we can go up with precision and keep more bits to work with. I do not think it would be practical for a MIDI controller, but for other applications (with fewer potentiometers) it can be something interesting.
Or maybe this extended accuracy can be achieved more easily with a rotary encoder. For a MIDI controller I got very good results with rotary encoders. But this is another story … that you can even find in this site …

Updated: February 13, 2017 — 12:44 pm

1 Comment

Add a Comment
  1. The code works fine but there is a little problem.For example if you want to go to 3 then 4 , 4 will send but you cant lock on 4 and go to will miss lock on 4,but 4 will send transiently!!! Is there any solution for that?

Leave a Reply

Your email address will not be published. Required fields are marked *

OpenHardware.Ro © 2017 Frontier Theme