BUCK CONVERTER

← all examples · interactive version of jupyter/buck.ipynb · voltage regulators
VDDH
SWITCH A (D)
L
C
LOAD R
CONTROL
POWER STAGE
SIMULATION
The averages are taken over the second half of the run, as in the notebook. R·C and the switching period are four decades apart here, so waiting out the startup transient and resolving the ripple in one run is expensive — hence the warm start. Untick it for the notebook's cold start.
V_o
VDDH·D
RIPPLE V_o
RIPPLE I_L
I_L / I_o
EFFICIENCY
STATE
Inductor current I_L
Load current I_o
Output voltage V_o
Switch A
Measured, as you sweep D

WHAT YOU ARE LOOKING AT

A synchronous buck converter, simulated the most literal way possible: step through time, work out which switch is on, integrate the inductor current, integrate the output voltage, repeat. No averaged model, no small-signal approximation — just the two state equations

V_o = (1/C) ∫ (I_L − I_o) dt    I_L = (1/L) ∫ V_x dt

written as a loop. The output voltage settles near VDDH·D, and the reason is almost embarrassingly simple: in steady state the average voltage across an inductor must be zero, so the switch node's average — which is VDDH for a fraction D of the time and zero otherwise — has to equal V_o.

Two things the averaged model in a textbook will not show you, and this one will. The startup transient: the L and C form a resonant tank with almost nothing damping it, so switching on into a discharged output produces an inductor current far larger than anything in steady state. And the settling time: that tank rings for a long time, so an average taken too early is not an average of anything.

THINGS WORTH TRYING

THE PYTHON

for i in range(1,N):
    ts = t[i]

    # Model switch
    if(ts % T < dtc*T):
        pmos = 1
    else:
        pmos = 0

    dt = (t[i]-t[i-1])

    # Current voltage across the inductor
    vx[i] = pmos*(VDDH) - Rs*ix[i-1] - vo[i-1]

    # Current in inductor, trapezoidal approximation of area
    ix[i] = ix[i-1] + 1/L * (vx[i] + vx[i-1])/2*dt

    io[i] = 1/R * vo[i-1]
    vo[i] = vo[i-1] + 1/C * ((ix[i] + ix[i-1])/2 - (io[i] + io[i-1])/2)*dt

Source: jupyter/buck.ipynb. The integration is the notebook's, verbatim. Building this page turned up a real problem in that notebook, since fixed: it averaged over the second half of a 10 µs run while R·C is 1 ms, so the tank was still ringing and it printed a negative efficiency. Its settled mode now starts at the operating point and runs long enough to mean something. You can still reproduce the old behaviour here by unticking the warm start and shortening t_end. For the same power stage under a completely different control scheme, see the PFM buck.