Smoothing a jittery reading
Hold the wheel still and the reading still wanders: by a count or two on an Uno, by tens of counts on an ESP32. It is the ADC and the wires, not the pot. Averaging 16 reads per value takes most of it out, and costs under 2 ms on an Uno.
A still wheel, a moving number
Run the first read and leave the wheel alone. The number does not sit still. On an Uno it flicks between two or three neighbouring values. On an ESP32 it wanders over tens of counts.
That is not the pot. The wiper is a piece of metal resting on the track, and while the wheel is still, the voltage on SIGNAL is steady. What moves is the measurement: every ADC has a little electrical noise of its own, and the wires between the block and the board pick up more. The ESP32's ADC is known for being noisier than the Uno's.
Averaging
The noise is random: as often above the true value as below it. Add up several reads and divide, and the ups and downs cancel. The scatter falls roughly with the square root of the number of reads, so 4 reads halve it and 16 cut it to a quarter. The numbers in the figure are an illustration of that rule, not a measurement of this block.
The price is time. Each value now takes 16 reads instead of one. On an Uno an
analogRead takes about 0.1 ms, so 16 cost under 2 ms, which nobody turning a
wheel will notice. At 64 the gain is small and the lag starts to show.
Why the sum is a long
On an Uno an int is 16 bits and stops at 32767. Sixteen reads of 1023 add
up to 16368 and fit, but 64 of them do not, and an overflowing sum wraps round
to a negative number without any error. Keeping the sum in a long means
SAMPLES can be changed without thinking about it. The division at the end
brings it back into range.
What averaging cannot fix
An average removes scatter that goes both ways. It does nothing for an error that is the same every time. The ESP32's flat stretches at the two ends of the travel are that kind, and the next article is about them.
The code
The first read, plus a function that adds up SAMPLES reads and divides. It prints the single read and the average side by side, so the Serial Plotter draws both.
/*
Disc Potentiometer - smoothing a jittery reading TK07 / /p/tk07
Wiring. Count from the square pad on the TinkerBlock board, wheel
up, header at the bottom:
GND -> GND
VCC -> 5V on an Uno; 3V3 on an ESP32, ESP32-S3 or Pico
(at one stop, SIGNAL gives your pin whatever VCC is)
NC -> nothing (unconnected on the board)
SIGNAL -> A0 on an Uno, GPIO 34 on an ESP32, GPIO 4 on an
ESP32-S3, GP26 on a Raspberry Pi Pico
Arduino IDE
Tools > Board your board, e.g. ESP32S3 Dev Module
Tools > Port the one that appears when you plug in
Tools > USB CDC On Boot Enabled (ESP32-S3 only)
Tools > Serial Plotter to see both lines
No library needed.
*/
// The pin SIGNAL is wired to.
// Uno: A0. ESP32: 34. ESP32-S3: 4. Pico: 26.
const int POT_PIN = 4;
// What analogRead returns at full scale on your board.
// Uno: 1023. ESP32, ESP32-S3: 4095. Pico: 1023.
const int ADC_MAX = 4095;
const int SAMPLES = 16; // reads per value
int readAveraged() {
long sum = 0; // an Uno's int stops at 32767
for (int i = 0; i < SAMPLES; i++) {
sum += analogRead(POT_PIN);
}
return sum / SAMPLES;
}
void setup() {
Serial.begin(115200);
}
void loop() {
int raw = analogRead(POT_PIN);
int smooth = readAveraged();
Serial.print("raw:");
Serial.print(raw);
Serial.print(" smooth:");
Serial.println(smooth);
delay(50);
}The sum is a long because an int on an Uno stops at 32767: 16 reads of 1023 fit, but raise SAMPLES to 64 and they do not. Open Tools > Serial Plotter at 115200 and hold the wheel still: raw wanders, smooth barely moves.
The same average in MicroPython: sum SAMPLES reads, divide with //. It prints the single read and the average on one line, so Thonny's plotter draws both.
"""
Disc Potentiometer - smoothing, MicroPython TK07 / /p/tk07
Wiring. Count from the square pad on the TinkerBlock board, wheel
up, header at the bottom:
GND -> GND
VCC -> 3V3 (never 5V: at one stop, SIGNAL gives your pin VCC)
NC -> nothing (unconnected on the board)
SIGNAL -> GPIO 34 on an ESP32, GPIO 4 on an ESP32-S3,
GP26 on a Raspberry Pi Pico
Thonny
Run > Configure interpreter MicroPython (ESP32) or
MicroPython (Raspberry Pi Pico)
View > Plotter to see both lines
Nothing to install: machine, sys and time are built in.
"""
from machine import ADC, Pin
import sys
import time
# The GPIO number SIGNAL is wired to. ESP32: 34. ESP32-S3: 4. Pico: 26.
POT_PIN = 4
SAMPLES = 16 # reads per value
pot = ADC(Pin(POT_PIN))
if sys.platform == "esp32": # both ESP32s report "esp32"
pot.atten(ADC.ATTN_11DB) # measure up to about 3.1 V
def read_averaged():
total = 0
for _ in range(SAMPLES):
total += pot.read_u16()
return total // SAMPLES
while True:
raw = pot.read_u16()
smooth = read_averaged()
print("raw:", raw, "smooth:", smooth)
time.sleep_ms(50)There is no Uno here: an Uno cannot run MicroPython. Python's integers do not overflow, so there is no long to worry about. Turn on View > Plotter in Thonny to see the two lines.
When it does not work
Each value is now 16 reads, and the sketch also waits between values. Shorten the delay() before shrinking SAMPLES: the reads themselves are quick. If it still lags, 8 samples is a fair middle.
The average is sitting on the boundary between two numbers, and any noise at all flips it. Keep the last value you used and only change it when the new one differs by more than a few counts. That is called hysteresis, and it is three lines.
A small capacitor, around 100 nF, from SIGNAL to GND filters in hardware what the average filters in code, and the ESP32 ADC article suggests one for long wires. For a thumbwheel on a short cable, the average alone is usually enough and needs no soldering.
More repeatable, not more accurate. Averaging removes scatter that goes both ways. It does nothing about an error that is always the same, such as the ESP32's flat ends or a supply that is not quite 5 V.
What the two stops really read, and how to take your own.
Why the ends are not exact →Edit this page — content/books/disc-potentiometer/smoothing-a-jittery-reading.mdx
Questions about this product
See what other owners have asked, and read their solutions.
Disc Potentiometer
Loading discussions…
Discuss this article
Ask about this page. The answer stays here, on the page it belongs to, for whoever hits the same wall next.