disc potentiometer/The ends, and when it is wrong/08. Why the ends are not exact
The ends, and when it is wrong · 08 of 9

Why the ends are not exact

On an Uno or a Pico the two stops should read 0 and full scale, or within a few counts of them. On an ESP32 the first few percent of travel read 0 and the last few read 4095 before the wheel reaches its stop, because the ADC stops measuring at about 0.1 V and 3.1 V. The cure is the same everywhere: take your own two stops and map from them.

Where the numbers stop moving

The ends of the range
Your board
Wheel97 %
SIGNAL
3.20 V
Reading
4095
Flat travel
9 %
SIGNAL is 3.20 V, over the roughly 3.1 V the ESP32's ADC reads as full scale with the default settings, so it reads 4095 from here to the stop. The wheel still turns; the number has nowhere left to go.

Pick the ESP32 and slide the wheel towards either end. For most of the travel the reading follows the wheel. In the last few percent at each end it stops moving: 0 at the bottom, 4095 at the top, while the wheel still has a little way to go.

The ESP32's two flat stretches

With the Arduino core's default settings, the ESP32's ADC and the ESP32-S3's read from roughly 0.1 V to roughly 3.1 V. The block gives them 0 V to 3.3 V. So below about 0.1 V there is nothing to read and the answer is 0, and above about 3.1 V there is nothing left to count and the answer is 4095.

On a 3.3 V track that is about 3 % of the travel at the bottom and about 6 % at the top. The exact knees vary from chip to chip, which is why the figure says illustrative and the prose says about. Reading the ADC has the ESP32's side of it. Near the ends the ESP32's ADC is also less linear than in the middle, so the last reading before each flat stretch is the least trustworthy.

The Uno and the Pico

Their ADCs measure all the way from 0 V to their reference, and with VCC on the same supply the stops are the top and bottom of that range. They should read 0 and full scale, or within a few counts.

A few counts short is not a fault. Many pots do not quite put the wiper on the very end of the track at the stops, and nobody has measured this one. The supply at the Uno's ADC reference and at its 5V pin can also differ slightly.

Take your own stops

Every one of these has the same answer: stop assuming the ends are 0 and ADC_MAX, and use the numbers your block actually gives. The sketch keeps the lowest and highest reading it has seen, and maps between them. Turn the wheel to both stops once and from then on 0 % and 100 % are exactly where the number stops moving.

The code

The first read, plus two variables that remember the lowest and highest reading seen. Turn the wheel to both stops once after a reset, and from then on the percentage runs from 0 to 100 exactly between them.

disc_pot_own_stops.ino
/*
  Disc Potentiometer - taking your own stops             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)
    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;

int lowest = ADC_MAX;                  // the lowest reading seen so far
int highest = 0;                       // and the highest

void setup() {
  Serial.begin(115200);
}

void loop() {
  int reading = analogRead(POT_PIN);

  if (reading < lowest) lowest = reading;
  if (reading > highest) highest = reading;

  int percent = 0;
  if (highest > lowest) {
    percent = map(reading, lowest, highest, 0, 100);
  }

  Serial.print(reading);
  Serial.print("   stops ");
  Serial.print(lowest);
  Serial.print(" to ");
  Serial.print(highest);
  Serial.print("   ");
  Serial.print(percent);
  Serial.println(" %");
  delay(100);
}

lowest starts at ADC_MAX and highest at 0, so the first read moves both. The if guards against dividing by zero before the wheel has moved. Once you know your stops, replace lowest and highest with the numbers it printed.

When it does not work

My ESP32 reads 4095 at the stop, not short of it. Is that wrong?

No, that is the usual case. With VCC on 3V3, the stop is 3.3 V, above the roughly 3.1 V the ADC reads as full scale, so it reads 4095 there and for a little way before it. What you lose is not the top number but the last few percent of travel, which all read the same.

My Uno stops at 1020, not 1023.

A few counts short at a stop is common and not a fault. The likely reasons are the wiper, which on many pots does not sit exactly on the end of the track, and the Uno's own 5 V being a little different at the ADC's reference pin. Nobody has measured this part's ends. The sketch below takes whatever yours are.

Can I make the ESP32 read the whole travel?

Not with VCC on 3V3 and the default settings: the ADC simply stops at about 3.1 V. You could give it less than 3.3 V at the top, but for a thumbwheel the few percent lost at each end rarely matter. Mapping from your measured stops makes 0 and 100 land where the wheel stops moving the number.

The lowest and highest reset every time the board restarts.

They are ordinary variables, so they start again at every reset, and the percentage is rough until you have turned the wheel to both stops once. Once you know your block's stops, write them into the sketch as constants and delete the tracking lines.

Where this goes next

Stuck at 0, stuck at the top, wandering or backwards, and where to look for each.

When the reading is wrong

Edit this page — content/books/disc-potentiometer/why-the-ends-are-not-exact.mdx

Community

Questions about this product

See what other owners have asked, and read their solutions.

Ask a question ↗

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.

Browse Modules and blocks on the forum