Pin map (ATmega328P Nano)
| Pin | Function | Hardware |
| D5 | PWM out (own frequency, 8-bit) | Timer0 OC0B, TOP = OCR0A |
| D3 | PWM out (own frequency, 8-bit) | Timer2 OC2B, TOP = OCR2A |
| D8 | PWM in, hardware capture | Timer1 ICP1, free-running 62.5 ns tick |
| D2 | PWM in, interrupt | INT0 any-edge, timestamped with Timer1 |
| A0–A7 | analog in 0–5 V (A6/A7 analog only) | 10-bit ADC, 1 conversion at a time |
| D4 D6 D7 D9 D10 D11 D12 D13 A0–A5 | GPIO in / in+pull-up / out | plain port pins (D13 also drives the LED) |
| D0, D1 | USB serial | do not use |
Why not more PWM outputs: only 6 pins have timer output hardware (D3 D5 D6 D9 D10 D11). A free frequency needs a variable TOP, so Timer0/Timer2 give up their A channel (D6, D11), and Timer1 is dedicated to measuring the inputs (D9, D10 become GPIO). Timer0 no longer drives millis().
PWM out formulas
N = TOP + 1
f = 16 MHz / (PSC × N) T = PSC × N / 16 MHz
K = round(N × duty_permille / 1000), clamped to 1 … N-1 (high counts; 0 % / 100 % are forced static levels)
OCR reg = K − 1 (fast PWM: the pin is high for OCR+1 counts)
duty_act = K / N t_high = K × PSC / 16 MHz V_avg = duty_act × 5 V (after an RC low-pass)
step = 100 / N % eff. res = log2(N) bit f error = (f_act − f_set) / f_set (vs ideal 16.000 MHz)
Smallest prescaler with N ≤ 256 is chosen. N is an integer, so f_act can differ from f_set (up to ~1.5 % just below a prescaler boundary). A ceramic-resonator Nano can be ~0.5 % off 16.000 MHz.
PWM in measurement
edges are timestamped in 62.5 ns ticks (32-bit); per gate window (one poll):
cycles = complete cycles seen Σperiod = sum of their periods Σhigh = sum of their high times
f = cycles × 16 MHz / Σperiod T = Σperiod / cycles duty = Σhigh / Σperiod t_high = Σhigh / cycles
No complete cycle in the window: the page shows the pin level (static high / low) and the time since the last edge. Resolution is 1 tick per period: a 100 kHz input has 160 ticks per cycle (0.6 %). Poll at least every few seconds for very slow signals.
Analog in
V_pin = raw × Vref / 1024 V_in = V_pin × scale scale = (R_top + R_bottom) / R_bottom
Vcc ≈ 1.1 V × 1024 / bandgap_raw (bandgap is only ±10 % accurate: calibrate with a multimeter)
step = Vref / 1024 = 4.9 mV (5 V) or 1.07 mV (1.1 V reference, range 0–1.1 V)
The Nano has no DAC: analog out is PWM + RC filter (e.g. 1 kΩ + 10 µF). Voltages above 5 V are never applied to a pin directly: use a divider for reading, and a MOSFET or op-amp stage for outputs above 5 V.
Serial protocol (115200 8N1, newline-terminated, one reply per command)
| Command | Reply |
S <3|5> <0-1000> duty permille | DUTY pin K N (K = high counts) |
F <0|2> <Hz> (0 = D5, 2 = D3) | FREQ t Hz PSC N + one DUTY line |
I <0|1> PWM-in window (0 = D8, 1 = D2), resets the window | IN ch cycles ΣP ΣH level age_ms |
A [n] all 8 ADC channels, sum of n samples (1–64, default 16) | AIN n s0 … s7 |
V <0|1> ADC reference AVCC / 1.1 V · C bandgap | VREF r · BG 16 sum |
M <pin> <0|1|2> mode in / pull-up / out (D2, D8: in or pull-up only) | PIN pin level mode |
W <pin> <0|1> write (pin must be an output) | PIN pin level mode |
P port snapshot · ? status · R registers | PORT … · STATUS … · REG … |
| anything invalid, overlong (> 31 chars) or out of range | ERR (state unchanged) |
Example: S 5 250 → DUTY 5 31 125 means D5 gets 25.0 % requested; K = 31 high counts of N = 125 (OCR register 30) → 24.8 % actual (step 0.8 %).
Notes
• The Nano RX buffer is 64 bytes: this page sends one command at a time and waits for the reply (slider drags are coalesced). Raw bursts of ~32 commands lose bytes, and a dropped digit silently changes a value.
• Opening the port resets the Nano; pins float for ~1–2 s, then PWM is low and GPIO are inputs. Add pull-downs if the load needs a defined state.
• Pin limits: ~20 mA per pin, 40 mA absolute, ~200 mA total. Never apply more than 5 V (Vcc + 0.5 V) to any pin; Vin (7–12 V) only feeds the regulator.
• Changing a PWM frequency restarts its timer and can give one odd pulse. − / + use the editable step field (min 0.1 %).
• R dumps raw timer/ADC registers; the command-line tools use it to verify the hardware state.