Space-vector PWM
The current loop finishes by asking for a voltage vector. It asks in volts, at an arbitrary angle and magnitude, as though the inverter were an ideal three-phase source.
It is not. It is six transistors, and each of the three legs can only be connected to the top rail or the bottom one. There are eight combinations, and that is the complete list of voltages the bridge can produce. Everything else — every angle, every magnitude in between — has to be manufactured by switching between them fast enough that the machine’s inductance averages the result.
This page is about how that averaging is arranged, and about the 15.5% of your DC link that the obvious method throws away.
Eight states, six of them useful
Label each state by which legs are tied high. 100 means phase to the top
rail and , to the bottom.
Six of the eight put different voltages across different phases. Applying
Clarke to each gives six vectors of equal length , spaced
60° apart — through . The remaining two, 000 and
111, tie all three phases to the same rail. The machine sees zero volts across
its terminals in both cases. These are the null vectors, and
, and they are not wasted states — they are the throttle.
Join the six active tips and you get a hexagon. Its interior is precisely the set of average voltages the bridge can synthesise.
Making an arbitrary vector
Any request inside the hexagon falls between two adjacent active vectors. Spend part of the period on each, and the rest on a null vector, and the average is the request.
For a request at angle within its sector, the dwell fractions are
with on the trailing vector, on the leading one, and shared between the two null vectors.
Take the figure’s default: modulation index 0.75, sitting at 30°, so exactly mid-sector. That gives V, and . Symmetric, as it must be by symmetry of the geometry.
Why the limit is a circle, not the hexagon
A steady rotating request traces a circle. To produce it without distortion the whole circle has to fit inside the hexagon — so the binding constraint is the inscribed circle, not the vertices:
For a 48 V link that is 27.71 V peak per phase, against 32 V at the hexagon vertices. The corners are real voltage, and they are reachable — but only in six directions, so a rotating vector cannot use them without distorting.
The 15.5%
Plain sinusoidal PWM sets each phase’s duty from its own reference: . The duty hits 1 when reaches — 24 V on a 48 V link. Compare:
SPWM leaves 15.5% of the achievable voltage unused. On a motor that is 15.5% less speed before field weakening, from hardware you have already bought.
The trick to recover it is almost too simple. Add the same offset to all three duties:
which centres the three references between the rails, then compute duties as before.
A common-mode offset appears identically on all three phase terminals. The star point of an isolated-neutral machine simply floats to follow it, so the differences between phases — the only thing that drives current — are untouched. The machine cannot tell.
Set the modulation index to 1.0 and switch between the two. SPWM clips badly. SVPWM’s duties reach exactly 0.0 and 1.0 and no further — the saddle-shaped waveform touches each rail without ever crossing it. The injected common mode peaks at 6.93 V, 14.4% of the link, and it is a triangular third harmonic: it completes three cycles for every one of the fundamental, which is why it never disturbs a three-phase balanced set.
On the bench Plain SPWM starts clipping above modulation index 0.866 — that is , the ratio of the two limits. If you have inherited a drive that loses the plot somewhere around 87% of full output, check the modulator before you suspect anything else.
Note that it clips near the phase peaks first, not everywhere at once. In the hexagon figure, set the modulation index to 0.9 and spin: the SPWM readout reports “in range” at 30° and “clipped” as the vector swings towards 0°. That is why the symptom is distortion rather than a hard ceiling.
Min-max is space-vector PWM
The two derivations look nothing alike. One decomposes onto basis vectors with trigonometry and a sector lookup; the other takes a max, a min and an average.
They produce identical duty cycles. The min-max form is what production firmware uses — a handful of comparisons instead of a sector branch and two sine evaluations — and the sector construction is how you understand what it is doing.
That equivalence is worth more than an assertion, so the site’s test suite derives the switching sequence independently, by sorting the six gate edges, and checks that the time spent on each vector matches the sector decomposition’s , and across the whole plane. They agree to 1e-9.
The order of the sequence matters
Knowing how long to spend on each vector does not say in what order. Centre each phase’s on-time in the period and the order falls out on its own. For the worked example above:
with the null time split evenly, 12.5% on each of and .
Two properties make this the right sequence, and both are visible in the timing diagram:
Only one leg switches at each transition. Walk the sequence:
000 → 100 → 110 → 111 and back. Every step changes exactly one bit. A
sequence that changed two legs at once would double the switching losses for no
benefit, and inject a much larger common-mode step into the machine.
It is symmetric about the middle of the period. The pattern read backwards is the pattern read forwards, which puts the current ripple’s centroid exactly at the period midpoint. That is what makes it safe to sample phase current at the PWM centre and get the true average without filtering — which is the sampling strategy every drive relies on.
On the bench
Splitting the null time evenly between 000 and 111 is what makes the pattern
symmetric. Uneven splits are a real technique — discontinuous modulation parks
on one null vector to cut switching losses by a third — but they give up the
symmetry, and with it the clean centre-sampling.
Overmodulation
Push the request past the inscribed circle and : the two active vectors alone need more than the whole period, leaving negative null time. Drag the vector past the circle in the figure and the readout goes red.
There is no honest answer here — the bridge cannot do it. What it can do is get
as close as possible, which means clamping and accepting distortion. The
implementation in svpwmDuties clamps each duty to , which is the
simplest and most common choice.
The useful region is between the inscribed circle and the hexagon: modulation index 1.0 to 1.155. Drives that need every last volt at high speed work here deliberately and accept the low-order harmonics that come with it.
In code
/* SVPWM by min-max injection. This is the whole modulator. */
void svpwm(float v_alpha, float v_beta, float vdc, float *duty)
{
/* Inverse Clarke: the three phase references. */
const float va = v_alpha;
const float vb = -0.5f * v_alpha + SQRT3_2 * v_beta;
const float vc = -0.5f * v_alpha - SQRT3_2 * v_beta;
/* Centre them between the rails. */
float vmax = fmaxf(va, fmaxf(vb, vc));
float vmin = fminf(va, fminf(vb, vc));
const float offset = 0.5f * (vmax + vmin);
duty[0] = clamp01(0.5f + (va - offset) / vdc);
duty[1] = clamp01(0.5f + (vb - offset) / vdc);
duty[2] = clamp01(0.5f + (vc - offset) / vdc);
}
No sector lookup, no trigonometry, no dwell times. Load the three results into the timer’s compare registers in centre-aligned mode and the hardware produces the symmetric sequence for you.
What to take away
- The bridge has eight states. Everything between them is made by averaging, and the null vectors are what set the magnitude.
- The linear limit is the inscribed circle, , because a rotating request has to fit in every direction at once.
- Plain SPWM reaches only and wastes 15.5% of the link. Common-mode injection recovers it for three lines of code, and the machine cannot detect the injection.
- Min-max injection and the sector-and-dwell construction are the same modulator. Use the first, understand the second.
- Centre-aligned duties give one switch transition per step and a symmetric pattern, which is what makes centre-of-period current sampling correct.
Next: what deadtime does to all of this, and why the compensation matters most at the speeds where you have the least voltage to spare.