FOC Reference 07 Rotor position

Sensorless position

Field-oriented control needs the rotor angle. Everything on this site so far has assumed you have it — from an encoder, a resolver, or hall sensors.

Often you cannot. The sensor costs more than the controller, its cable is the least reliable part of the machine, and in a sealed pump or a compressor there is nowhere to put it. So the question becomes whether the angle can be worked out from the only two things a drive already knows: the voltage it applied and the current that resulted.

It can, most of the time. This page is about how, and about the region where it cannot — which is not a gap to be engineered away but a consequence of the physics.

The one idea

Every observer here rests on the same equation. In the stationary frame, the machine’s terminals obey

The first two terms you can compute — and are known, is measured. Anything left over is the back-EMF , generated by the rotor magnets sweeping past the windings. It points perpendicular to the magnet flux, so its direction is the rotor angle:

That is the whole idea. Everything below is a way of extracting without computing that derivative, because differentiating a measured current amplifies noise brutally.

And here is the limitation, visible in the physics rather than in any implementation:

The signal is proportional to speed. At zero speed there is no back-EMF at all, so there is nothing to observe. For the reference machine that is 6.41 V at 1800 rpm, 1.07 V at 300 rpm, and 0.53 V at 150 rpm — by which point it is comparable to the inverter’s own deadtime error and to the uncertainty in . No observer in this chapter escapes that.

Tracking an angle: the PLL

Both observers below produce a vector and need its angle. The obvious answer is atan2, and it is the wrong one — it passes every bit of noise straight through to the angle, and gives no speed estimate.

A phase-locked loop instead drives an internal angle until the error against the observed vector is zero. Since the loop contains an integrator, the output is smooth, the speed estimate comes free, and a brief dropout in the signal makes it coast rather than jump.

The error signal is neat. If the estimate is correct, the back-EMF lies entirely along the estimated q-axis with no d-component at all. So the residual d-component, normalised, is the error:

Feed that to a PI loop and integrate for the angle. Because only the direction of the vector matters, the PLL is completely insensitive to its magnitude — a signal a hundred times weaker locks to the same place.

Observer 1: the flux-linkage observer

Rather than differentiate the current, integrate the voltage. Stator flux is

and the part contributed by the rotor magnets is what remains after removing the part the stator current itself produces:

The flux-linkage observer: measured current and commanded voltage give the back-EMF by subtraction, a leaky integrator gives stator flux, removing the stator's own contribution leaves the magnet flux, and a PLL tracks its angle. ψ s λ m i α , i β measured v α , v β the reference, not a measurement v − R·i the back-EMF itself leaky integrator leads by atan(f c /f e ) ψ − L d ·i leaves the magnet flux PLL tracks the angle θ̂ and ω̂ into Park and inverse Park
No new hardware — it is fed the current it measured and the voltage it asked for, because a drive has no voltage sensor. Every step is a subtraction or an integration, and the only tuning is the one cutoff frequency — which is also the only thing that goes wrong, because the leaky integrator it forces on you leads the ideal one.

points along the d-axis, so its angle is the rotor angle directly. No derivative anywhere.

The integrator is the problem

A pure integrator will not survive contact with hardware. Any DC offset in the measured current or the assumed voltage — millivolts, microamps — integrates without bound and walks the estimate away within seconds.

The universal fix is to make the integrator leaky: replace with . That is a high-pass filter, and it bounds the drift.

It also introduces an error, and the direction catches people out. A true integrator shifts phase by exactly at every frequency. The leaky one shifts by , so its output leads the true flux by

With a 20 Hz cutoff that is 5.7° at 200 Hz electrical, 9.5° at 120 Hz, and 18.4° at 60 Hz. It is a known function of speed, so it can be rotated back out — but backwards, because the filter runs ahead, not behind. Apply the correction the intuitive way and you double the error instead of removing it.

The bench measures this directly. Turn off Compensate phase shift:

SpeedCorrectedUncorrectedPredicted lead
900 rpm4.2°20.0°18.4°
1800 rpm4.0°12.7°9.5°
3000 rpm3.9°9.2°5.7°

On the bench Notice the corrected error is a flat 4° at every speed rather than zero. That residual is not noise and not tuning — it is saliency. The observer subtracts a single , but the machine presents on one axis and on the other. The mismatch is of flux at right angles to the magnet flux, which rotates the estimate by

For the reference machine at 6 A that is 4.8°, and the site’s tests confirm the error scales with and vanishes entirely on a machine with . It is a load-dependent angle error: your observer is better calibrated at light load than at heavy.

Observer 2: the sliding-mode observer

Run a current model of the machine alongside the real one, and drive it with a switching term proportional to the sign of the current estimation error:

If exceeds the peak back-EMF, the estimation error is forced to zero and held there — the estimate slides along the error-is-zero surface. Once it does, must be supplying precisely what the model was missing. So is the back-EMF, recovered without differentiating anything.

The sliding-mode observer: a current model driven by a switching term that forces the modelled current onto the measured one, with the switching term filtered to recover the back-EMF and a PLL tracking its angle. error compared with the measurement recovery filter lags by atan(f c /f e ) back-EMF e α , e β PLL tracks the angle θ̂ and ω̂ into Park and inverse Park i α , i β measured switching term K · sat(error / boundary) current model 1 / (R + sL), driven by z î α , î β the observer’s own v α , v β the reference, not a measurement
A different shape of thing from the flux observer. The loop along the bottom is the part with no equivalent there — this observer closes on its own estimate, which is why its errors feed back on themselves. Note the recovery filter lags, where the flux observer's integrator leads: the two need compensating in opposite directions.

Sliding-mode behaviour is famously insensitive to parameter error, which is the appeal. Two costs come with it:

It chatters. is a switching signal, so recovering a usable back-EMF needs a low-pass filter, and that filter lags by — 21.8° at 120 Hz with a 300 Hz cutoff. This one is a genuine lag, so the correction goes forwards. The two observers on this page need phase corrections in opposite directions, which is a good reason to derive rather than copy.

The gain has to fit the whole speed range. must exceed the peak back-EMF at maximum speed, but that same is enormous compared with the back-EMF at low speed, and the boundary layer then quantises the estimate coarsely. That is the main reason the SMO gives up earlier than the flux observer below.

The comparison

Operating point
Observer
Bridge
Both observers running closed-loop — the controller acts on the estimate, with no privileged access to the true angle. Top: the angles. Middle: the errors, with a ±10° band. Bottom: peak error swept across the speed range, which is the plot that matters.

The sweep is the interesting one. For the reference machine at 6 A:

SpeedBack-EMFFlux observerSMO
3600 rpm12.82 V3.8°2.5°
3000 rpm10.68 V3.9°3.7°
2400 rpm8.55 V3.9°4.8°
1800 rpm6.41 V4.0°9.4°
1300 rpm4.63 V4.1°15.9°
900 rpm3.20 V4.2°40.5°
600 rpm2.14 V4.2°180°
400 rpm1.42 V60.6°180°
250 rpm0.89 V48.2°180°

Three things fall out of it.

The flux observer is flat until it isn’t. 4° from 3600 rpm all the way down to 600 rpm, then a cliff between 600 and 400 rpm. There is no gentle degradation to tune against — it works, and then it does not.

The SMO wins at the top and loses at the bottom. Better than the flux observer above 3000 rpm, because sliding mode shrugs off the parameter mismatch that gives the flux observer its 4° saliency floor. Far worse below 1800 rpm, for the gain-scaling reason above. Neither is simply better.

Both die at around 1–2 V of back-EMF, which for this machine is a few hundred rpm — roughly 10–15% of rated speed. That figure is the useful one to carry around, and it is not specific to these two algorithms.

On the bench Add 1.5% of deadtime and watch the mid-range. At 1800 rpm the flux observer goes from 4.0° to 4.6° — barely anything, because 0.72 V of error against 6.4 V of back-EMF is nothing. The trouble is that the deadtime error is fixed while the back-EMF shrinks with speed, so the two are on a collision course. The deadtime page’s low-speed problem and this page’s low-speed problem are the same problem, and they arrive together.

Starting from rest

If the observer cannot work below a few hundred rpm, and the machine starts at zero, how does anything ever start?

Three answers are in production use.

Open-loop ramp (I-f start). Ignore the rotor. Impose a current vector at a commanded angle and rotate that angle at an increasing rate; if the load is light enough the rotor is dragged along behind it, like a stepper. Once the speed is high enough for the observer to lock, hand over. Simple and universal, but it fails on a high-inertia or high-friction load, and the handover needs care — a mismatch at that instant produces a large transient.

Initial position detection. Before moving at all, apply short voltage pulses in several directions and compare the current responses. On a salient machine the inductance depends on rotor position, so the responses differ, and the pattern identifies the angle — including which magnetic pole is which, from the slight saturation asymmetry. Enough to start smoothly in the right direction.

High-frequency injection. Continuously inject a high-frequency signal on top of the fundamental and track the rotor through the saliency it excites. This one genuinely works at zero speed and at standstill under load, because it does not use the back-EMF at all — it uses a completely different physical property.

The key point is that injection is not a better observer. It is a different measurement principle — saliency rather than back-EMF — chosen precisely because the principle this whole page rests on has run out. No amount of work on the observers above reaches down to standstill, because there is no signal there to observe.

In code

The flux observer, complete:

/* Leaky integration of the back-EMF gives stator flux. */
const float decay = expf(-2.0f * M_PI * cutoff_hz * dt);
flux_a = flux_a * decay + (v_a - Rs * i_a) * dt;
flux_b = flux_b * decay + (v_b - Rs * i_b) * dt;

/* Remove the flux the stator current is making; the rest is the rotor's. */
float rotor_a = flux_a - Ld * i_a;
float rotor_b = flux_b - Ld * i_b;

/* Undo the leaky integrator's phase LEAD — note the negative sign. */
const float f_elec = fabsf(omega_est) / (2.0f * M_PI);
rotate(&rotor_a, &rotor_b, -atanf(cutoff_hz / f_elec));

/* Rotor flux points along d; the PLL wants a q-pointing vector. */
pll_update(&pll, -rotor_b, rotor_a, dt);

Roughly twenty lines and two machine parameters. The difficulty in sensorless control was never the algorithm.

What to take away

  • All of this rests on one equation: whatever the resistive and inductive terms fail to explain is back-EMF, and back-EMF points at the rotor.
  • Track the resulting vector with a PLL, not atan2. It gives you speed, it rejects noise, and it coasts through dropouts.
  • Both observers need a speed-dependent phase correction, and the two go in opposite directions — the leaky integrator leads, the recovery filter lags.
  • The flux observer holds a flat 4° down to 600 rpm on this machine; its floor is saliency and scales with load. The SMO is more accurate at high speed and gives up much earlier at low speed.
  • Every model-based scheme fails at low speed, because the signal is proportional to speed. Expect a floor around 10% of rated.
  • Starting from rest needs a different mechanism entirely: an open-loop ramp, pulse-based position detection, or high-frequency injection.