How can the Arduino Uno support up to 12 servos if it only has 6 digital PWM pins?

The Servo library doesn't use PWM. When you call write() it computes a pulse width in microseconds and stores it in a global array. Then there is a single timer that regularly triggers an interrupt which changes the output signals according to each channel's desired pulse width.

You can find the source code below : Github link


The 6 PWM pins use the built in UART on the ATmega328P to produce their output. This makes the pulses very fast for a higher quality "analog" output. Because servo's communicate at a slow enough speed, they can be driven using software interrupts. Software interrupts go away from the code you're executing and run code included with the servo library. This code uses standard means to change the state of the pins. By doing it using interrupts rather than using the UART you waste some processing time but gain the ability to drive more servos.