disc potentiometer/Using the number/06. A percentage and a brightness
Using the number · 06 of 9

A percentage and a brightness

Divide the reading by ADC_MAX and you have the wheel's position as a fraction, the same on every board. Scale it to 100 and it is a percentage; scale it to 255 and it is a PWM duty that sets a TK01 XL LED's brightness.

Divide by ADC_MAX

A reading on its own means nothing until you know the board. 2048 is half-way on an ESP32 and past full scale on an Uno. Divided by ADC_MAX it becomes the wheel's position as a fraction, and a fraction is the same on every board.

One reading, two uses
Your board
Wheel40 %
ADC_MAX
4095
Percent
40 %
Duty
103 / 255
The wheel gives 1665 of 4095. Divided by 4095 that is 40 %, and scaled to 255 it is a duty of 103. On a 3.3 V board the TK01 is dimmer at every duty than on an Uno; that is the LED, not the pot.

Everything a pot is used for starts there. A percentage is the fraction times 100. A brightness is the fraction times 255, because that is the top of analogWrite. A menu choice is the fraction times the number of items.

map() does the arithmetic

map(reading, 0, ADC_MAX, 0, 100) scales a number from one range to another. It multiplies before it divides, in a 32-bit long, which matters twice. Divide first in whole numbers and every reading below full scale becomes 0. Multiply in an int on an Uno, where an int stops at 32767, and 1023 × 255 overflows.

map() drops the remainder rather than rounding, so 99.9 % prints as 99. For a display that is usually what you want: 100 only at the stop.

A second block

The LED is a TK01 XL LED, on the pin the XL LED book uses on an Uno, D9. On the others it moves to a pin that is free alongside the pot's: GPIO 25 on an ESP32, GPIO 5 on an ESP32-S3, GP15 on a Pico. Its GND goes to GND with the pot's, and its two NC pins stay unconnected. It has no VCC pin: the PWM pin powers it.

Turn the wheel and the LED follows. On a 3.3 V board it is dimmer at every setting than on an Uno, for reasons that are the LED's own. Why it is dimmer on 3.3 V works it out.

The code

The first read, plus two map() calls: one to a percentage for the serial monitor, one to 0..255 for analogWrite on the LED's pin.

disc_pot_brightness.ino
/*
  Disc Potentiometer - a percentage and a brightness     TK07 / /p/tk07

  Wiring. Count from the square pad on each TinkerBlock board, header
  at the bottom. TK07 Disc Potentiometer:

    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

  TK01 XL LED: GND -> GND, both NC -> nothing, and
    SIGNAL -> D9 on an Uno, GPIO 25 on an ESP32, GPIO 5 on an
              ESP32-S3, GP15 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;

// The pin the TK01's SIGNAL is wired to.
// Uno: 9. ESP32: 25. ESP32-S3: 5. Pico: 15.
const int LED_PIN = 5;

void setup() {
  Serial.begin(115200);
  pinMode(LED_PIN, OUTPUT);
}

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

  int percent = map(reading, 0, ADC_MAX, 0, 100);
  int duty = map(reading, 0, ADC_MAX, 0, 255);

  analogWrite(LED_PIN, duty);          // 0 is off, 255 is fully on

  Serial.print(percent);
  Serial.print(" %   duty ");
  Serial.println(duty);
  delay(50);
}

Keep POT_PIN, ADC_MAX and LED_PIN to the values in the comments for your board. The LED pin must be one analogWrite can drive; every one listed is. analogWrite sets the pin up itself, but the pinMode line costs nothing and makes the wiring obvious.

When it does not work

The LED is dim even at full scale on my ESP32.

That is the LED, not the pot. A TK01 on a 3.3 V pin gets a fraction of the current it gets on an Uno, because its blue LED takes about 3 V and leaves very little for its resistor. The XL LED book's article on 3.3 V works it out.

The percentage jumps between two values when I leave the wheel alone.

The reading is sitting on the edge between two whole percentages and the jitter is flipping it. Averaging the reading, in the next article, calms it. So does printing only when the value has changed by two or more.

Why map() and not reading / ADC_MAX * 100?

Integer division. In C, reading / ADC_MAX is 0 for every reading below full scale, so the whole expression is 0. map() multiplies first, in a long, which also stops reading * 255 overflowing an int on the Uno.

The LED looks fully bright from half-way round.

The eye is not linear: equal steps of duty look like big steps at the bottom and no steps at the top. A gamma curve evens it out, and the XL LED book has the table and the reason.

Where this goes next

Why the number wanders with the wheel held still, and the average that stops it.

Smoothing a jittery reading

Edit this page — content/books/disc-potentiometer/a-percentage-and-a-brightness.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