FOC Reference 06 Implementation

The peripherals it needs

Field-oriented control does not need a fast processor nearly as much as it needs the right peripherals. The whole loop is a few hundred floating-point operations — the hard part is that they must happen at a precise instant relative to the switching, on currents sampled at another precise instant, with the result reaching the bridge coherently on all three phases. Almost all of that is done by hardware you configure once and then leave alone.

This page is the shopping list, and the reasons. The concrete numbers and the failures come from one rig — an NXP MCX-N947 driving a Teknic M-2311P through an FRDM-MC-LVPMSM inverter at 24 V — because a specific board that actually ran is more useful than a generic table. Those are measured or datasheet numbers from that hardware, not outputs of this site’s model.

Platform interconnect: the CPU and its PWM, ADC, comparator and quadrature decoder, wired to the inverter, the shunt amplifiers, the machine and a debug probe. one microcontroller SWD duties ISR six gates 3φ shunts i abc , U dc trip A/B/I disable debug probe SWD — reads RAM while it runs Cortex-M33 150 MHz, the control ISR PWM unit 3 pairs, deadtime comparator over-current trip ADC PWM-triggered quad decoder A/B + index inverter six devices, 24 V link shunt amps gain and bias PMSM 2000 ppr
Everything on this drawing is on a path that closes once per PWM period: gates out, currents back, angle back. The two blocks that are not — the comparator and the probe — are the ones that get left off a board and then wished for. The comparator's line to the PWM unit carries no data; it is a permission being withdrawn, and §2 is about why that matters.

1. A PWM unit with complementary outputs and hardware deadtime

Three submodules, six outputs, centre-aligned.

Complementary means you write one duty per phase and the peripheral generates the inverted signal for the low-side device itself. That matters for more than convenience: the deadtime between the two edges must be inserted by hardware. Software cannot be trusted to hold off a turn-on by hundreds of nanoseconds while an interrupt might land in between, and a leg with both devices on is a short circuit across the DC link.

Centre-aligned rather than edge-aligned, because it is what puts the null vector symmetrically at the start and end of every period — which is what the bridge page shows, and what makes the sampling window in §3 exist at all.

Synchronising the three submodules to one timebase is not optional either. The three carriers must be exactly in phase, or the voltage vector the bridge applies is not the one the modulator computed.

The reload rule, which will bite you

The duty registers are double buffered. A write lands in a holding register and transfers to the active one only at a reload event. That is the mechanism that guarantees all three phases change together on a period boundary rather than mid-pulse — you cannot produce a torque glitch by being slow between two register writes.

The converse is the part that costs a day: while a reload is pending, further writes to the value registers do not take effect. A duty update therefore has exactly one correct shape, and it is not obvious from the register map:

clear any pending reload   (CLDOK)
write the three duties     (VAL2/VAL3 × 3)
arm the transfer           (LDOK)

Here is what that rule does when two pieces of code both write duties in the same interrupt. The figure runs the actual latch model — which write landed, which the hardware discarded, and what the bridge ended up switching on:

The interrupt
Who writes the duties
Six PWM periods. Top: the counter, wrapping at each boundary. Then the writes each interrupt performs, with ✕ where the hardware discarded one. Then the holding register, and the active register the bridge is actually switching on. Slide Starts at towards the end of the period until the boundary falls between the two writers: the discarded write stops being discarded, and a different duty reaches the machine. Nothing in the code changed. Then tick jitter to see it happen intermittently, which is what it looks like from the outside.

The second writer is not overwriting the first. It is being ignored — silently, with no error anywhere — because the first writer armed a transfer and the value registers are locked until that transfer completes. And whether it is ignored depends on where the counter happened to be, which is not a property of either piece of code.

On the rig above, that was exactly the defect. A library began writing duties after the vendor stack in the same interrupt; the vendor driver sets the latch bit at the end of its own write, so the second writer found the registers locked by the first writer’s pending reload. The duty-write winner was effectively random, and the symptom was intermittently impossible physics. Only after clearing the pending reload first did the measured q-axis voltage at 800 rpm (3.2 V) agree with what back-EMF says it must be.

On the bench The obvious lesson is “always clear the pending reload first”, and that is the smaller half of it. Clearing is necessary; it is not sufficient. Put three writers in a period, each of them perfectly disciplined, and the model still produces three different answers — because whichever write happens to precede the boundary is the one that gets carried through.

The rule underneath the story is therefore about counting, not about instructions: exactly one piece of code may own the duty registers. Two writers in the same period is not a race you can win by ordering them carefully, because the hardware, not your code, decides which write survives.

2. Fault inputs wired straight to the outputs

The PWM unit should be able to force its outputs to a safe state from a hardware input, with no CPU involvement — typically from an analogue comparator watching a current shunt.

Two routes from the same shunt voltage to safe gates: a comparator into the PWM unit's disable logic, and an ADC sample into a software limit check. hardware — within a switching cycle software — a period, then a reload over threshold this cycle ≤ one period and one more shunt voltage the current, as a volt comparator threshold in silicon output disable no CPU involved ADC sample once per period ISR limit check software trip gates safe both legs off
Same input, same outcome, three orders of magnitude apart in latency. The hardware path acts part-way through the switching cycle in which the current went too high. The software path cannot act before the next conversion — and then not before the next reload after that. Both are worth having; only one of them is protection.

That is the whole argument for putting over-current protection here rather than in the ISR. At 16 kHz the software path’s worst case is 62.5 µs of a current that is already past its limit, plus the reload that follows it. For a shorted leg that is a long time.

On the rig, the comparator feeding that path is mis-calibrated: it silently chopped the PWM above 2.4 A on a 7.7 A motor. The mapping was therefore cleared deliberately and protection carried in software instead. That is a real downgrade and it is written down as one — the point of naming it here is that “we turned off the hardware protection” is a decision that must survive in documentation, not a comment in a driver.

3. An ADC the PWM can trigger

Not an ADC you read from a timer interrupt. One that the modulator triggers directly.

Low-side shunt measurement only works during the null vector, when all three low-side devices are on and the phase currents are actually flowing through the shunts. Because the pulse is centred on the middle of the period, its complement — that null window — is centred on the period boundary. So the window is not an interval inside the period at all; it straddles the edge between two of them, which is why the conversion is triggered at the counter underflow rather than anywhere that sounds more natural:

What the modulator asks for
What the silicon needs
One PWM period, drawn centred on the boundary rather than on the period — which is the only way the window is visible as one interval instead of two. The shaded band is the null vector; the trigger fires at its middle, starting a chain of four conversions, three currents and the bus. Raise Depth and watch the window close from both sides as the largest duty grows; when the chain no longer fits, the converter is sampling a bridge that is switching. The per-phase bars underneath are the same window measured the other way, as 1 − duty.

The chain that follows is worth getting in the right order:

  1. the PWM’s own compare event triggers conversion,
  2. conversion-complete raises the control interrupt.

So the control law never runs on stale currents, and never runs before the samples it needs exist. Everything on the sensing page about where to place the sampling instant assumes this hardware path.

You need enough channels to take two phase currents plus the DC-bus voltage. Two currents are sufficient — the third follows from Kirchhoff — though which two you use is not arbitrary when duties get extreme, and the figure above shows why: the phase with the largest duty is the one whose window closes first.

On the bench One converter serving the whole drive means the three phases are not sampled simultaneously. One trigger starts a chained sequence — phase a, phase b, phase c, then the bus — and a FIFO watermark interrupt fires once all four are present. That interrupt is the control interrupt.

The skew between the first and last conversion is the price of a single converter, and it is tolerable for a specific reason rather than by hope: inside the null window the machine is freewheeling through the low-side devices, so the phase currents decay only slowly across it. Move the sampling instant out of that window and the same skew stops being harmless.

4. A quadrature decoder, if you have an encoder

A counter that decodes A/B in hardware and captures the index pulse. Decoding quadrature in software works at low speed and then quietly stops working: at 2000 pulses per revolution and 3000 rpm, the edges arrive about every 2.5 µs.

Even in a sensorless drive, an encoder input earns its place on the bench as a witness. On the rig, a sensorless startup once reported a healthy RUN state at 435 electrical rad/s while the shaft stood still — the observer had locked onto a phantom. The frozen encoder count was the only thing on the board that disagreed.

5. A debug path you can read at speed

Not a peripheral of the control loop, but the difference between engineering and guessing. On this rig the serial console’s host-to-target direction was dead — a physical break that no amount of firmware could fix — so every measurement in the report behind this page was taken by reading and writing target memory over SWD while the motor ran.

That turned out to be a better tool than the console would have been, and it is worth designing for deliberately: keep the drive’s state in a small number of known globals, and a debug probe becomes an oscilloscope for your control law.

What it costs, on a real part

QuantityValue on this rig
CoreCortex-M33 at 150 MHz
PWM period62.5 µs (16 kHz)
Control ISR≈ 12 µs, so about 19% of the period
Transport delay≈ one period, sample to applied vector
Encoder2000 ppr, quadrature

The delay in the third row is not a defect of this board — it is the structural consequence of the reload rule in §1. Duties computed from a sample are latched at the following boundary, so the applied vector lags the measurement by about one period. That is the number the timing page turns into a phase-margin budget, and it is why the ISR being 12 µs rather than 30 µs matters far less than you would expect.

What to take away

  • Complementary outputs with hardware deadtime, centre-aligned, on one synchronised timebase. Software cannot be trusted with the interlock.
  • The duty registers are double buffered, and a pending transfer locks them. One writer, always — the count is what makes it deterministic, not the discipline of each writer.
  • Trigger conversions from the modulator, at the boundary, and let conversion-complete raise the control interrupt.
  • Put over-current protection in the comparator, not the ISR. A cycle versus a period is the entire difference.
  • A quadrature decoder and a debug probe both earn their place, and in a sensorless drive the encoder earns it as a witness rather than as a sensor.