PWM and Analog I/O Deep Dive
PWM Isn't Real Analog Output
analogWrite() doesn't produce a variable voltage — it rapidly switches the pin fully HIGH and fully LOW at a fixed frequency (~490Hz or ~980Hz depending on the pin, on Uno/Nano), and the duty cycle (percentage of time spent HIGH) is what you're actually controlling with the 0-255 value. LEDs and motors "average out" this rapid switching into something that looks/feels analog because of thermal/mechanical inertia — an oscilloscope would show you a square wave, not a smooth voltage ramp.
Which Pins Support It
Only pins marked with ~ on the board silkscreen (Uno: 3, 5, 6, 9, 10, 11) support analogWrite() — calling it on a non-PWM pin either does nothing or behaves like digitalWrite() depending on the core, don't rely on that behavior.
PWM Frequency Matters for Motors
The default ~490Hz PWM frequency is audible — you'll hear a faint whine from motors/piezo speakers driven at this rate. For silent motor control, you either need a motor driver IC with its own higher-frequency PWM generation, or you reconfigure the ATmega's timer registers directly to raise the frequency above the audible range (~20kHz+) — this is more advanced and affects delay()/millis() timing if you touch Timer0, so use Timer1/Timer2 registers instead.
Analog Input Resolution
analogRead() gives you 10-bit resolution (0-1023) on classic AVR boards — that's about 4.9mV per step at 5V reference. Compare this to ESP32's 12-bit ADC (0-4095) for finer resolution if precision actually matters for your project (e.g. reading a precision thermistor).
ADC Reference Voltage
By default the ADC reference is the board's supply voltage (5V or 3.3V depending on board). You can switch to the internal 1.1V reference with analogReference(INTERNAL) for higher resolution when measuring small voltage ranges — useful for precision sensor work, but remember every analogRead() after that call is now scaled against 1.1V, not 5V, so update your conversion math.
Reading a Potentiometer Into a PWM Output
void loop() { int raw = analogRead(A0); // 0-1023 int pwmValue = map(raw, 0, 1023, 0, 255); // scale to PWM range analogWrite(9, pwmValue); }This single pattern — analog in, mapped, PWM out — underlies a huge fraction of real Arduino projects: dimmers, motor speed controls, fan controllers.