Analog in, PWM out
analogRead() turns a voltage into a number from 0 to 4095, but the ESP32’s ADC is not a straight line: at its default 11 dB setting it reads 0 below about 0.15 V, is fairly straight up to about 2.45 V, then bends over and stops at 4095 near 3.1 V. Each chip is also a few percent off. analogReadMilliVolts() uses the calibration stored in the chip and gives millivolts. analogWrite() does the reverse with PWM.

Open this lesson in the labFree, in your browser, no account needed.
How it works
Wiper at 50 % → 1.65 V.
A straight 0–3.3 V line would give 2048. This board's ADC gives about 2207: the curve starts at about 0.15 V, and this chip's gain is -2.2 % off.
analogReadMilliVolts() corrects both and reads close to 1650 mV (Espressif: ±60 mV between 150 and 2450 mV after calibration, worse above).
map(raw, 0, 4095, 0, 255) sets the PWM duty, so the LED brightness follows the raw number.
Try it on the bench
- Turn the pot all the way down: raw stays at 0 until about 0.15 V.
- Turn it right up: raw reaches 4095 before the wiper reaches 3.3 V.
- Open the Serial Monitor (select U1) to watch the numbers stream.
Parts on the bench
- Bench power supply
- ESP32 DevKit
- USB charger / port
- Potentiometer
- Resistor
- LED
In the course
Zen’s Electronics Design Mastery, module “Microcontrollers & Embedded”.