September 29, 2018

Controlling Phase Current Harmonics with FOC and AFC

I was playing with my thermal test motor, and noticed that at high speeds, some pretty significant harmonics showed up in the phase currents.  Here's an example with an obvious 5th harmonic - I'm commanding 20A, peak, and the harmonics add a couple amps of ripple on top of that:

This ripple shows up because there's a 5th harmonic in the motor's flux linkage (and therefore back-emf).  From the perspective of the field-oriented control, these harmonics at the phases show up as AC disturbances on the D/Q voltages.  The two current loops will try to squash these disturbances, but it's ability to do so depends on the current loop bandwidth and the magnitude of the disturbances.  Since both the magnitude and frequency go up with motor speed, even  really high-bandwidth current loops have trouble keeping up.  For example, in the scope shot at the top, the current loop had around 2 kHz closed-loop bandwidth.  The motor's electrical frequency was 300 Hz, so the harmonic (in D/Q) was at 1.8 kHz, so the controller couldn't quite reject it.

So how exactly do harmonics in the flux linkage at each phase show up when transformed into D and Q?  In the sinusoidal flux linkage case with no position-varying inductance, the motor's dynamics in the D/Q frame is exactly the classic voltage equations:

$$V_{d} = Ri_{d} + L\frac{di_{d}}{dt}  - \omega Li_{q}$$
$$V_{q} = Ri_{q} + L\frac{di_{q}}{dt}  + \omega Li_{d} + \omega\lambda$$

Where \(L\) is the synchronous inductance, \(R\) is the synchronous resistance, \(\omega\) is the (electrical) angular velocity, and \(\lambda\) is the peak flux linkage of one phase.

In the equations above, the flux linkage of a single phase \(\lambda_{p}\) is assumed to be of the form \(\lambda_{p} = \lambda \cos(\theta)\), where \(\theta\) is the rotor angle.  Other phases will have an offset of \(\pm \frac{2\pi}{3}\).

If the flux linkage has a fifth-harmonic in it, for a single phase it looks like \(\lambda \cos(\theta) + \lambda_{2}\cos(5 \theta) \).  With the fifth harmonic in flux linkage, the voltage equations in D and Q become:

$$V_{d} = Ri_{d} + L\frac{di_{d}}{dt}  - \omega Li_{q} + 5\omega\lambda_{2}\sin(6\theta)$$
$$V_{q} = Ri_{q} + L\frac{di_{q}}{dt}  + \omega Li_{d} + \omega\lambda - 5\omega\lambda_{2}\cos(6\theta)$$

(I have no interest in doing tedious trig and algebra by hand, so I wrote a Mathematica script to do the transforms analytically for me.)

That's interesting  - a fifth harmonic at the phases shows up as a 6th harmonic through the transforms.  It turns out, a 7th harmonic at the phases also shows up as a 6th harmonic through the transforms - just with both positive sine and cosine components, rather than positive sine negative cosine.  11 and 13 show up as 12, and so on.  Also (although this may be more intuitively obvious), odd multiples of 3 disappear through the transforms.

Just to confirm, here's the output when plugging a fifth harmonic into my motor simulator, using the the other motor parameters from the U12 and same controller gains as the hardware.

Phase currents:

D and Q axis currents, as well as rotor angle.  You can count the 6 periods in the AC component of the current per electrical cycle.

So what if you want to control out those harmonics?  Or add in harmonics of your own, for some reason?  If you know how the voltages of the harmonics appear on the D and Q axes, theoretically you could feed-forward them out, but there's a more interesting way to closed-loop deal with them, without knowing the specific amplitude of phasing of the harmonic, just it's frequency.

Introducing Adaptive Feedforward Cancellation.  This is a weird technique which was briefly introduced at the very end of 2.14, which has the seemingly magical property of giving your controller infinite gain at a specific frequency - i.e. it will perfectly track a signal at that frequency, or perfectly reject a disturbance at that frequency.  AFC is probably most well-known for its use in things like hard-disk read heads, which have to follow very fine tracks of data on the hard drive platters.  Since the platters have some runout as they spin, the read-head has to track in the presence of periodic disturbances.  Interestingly, AFC is a lot like field oriented control: FOC gives your controller infinite gain at the fundamental electrical frequency of your motor, letting you track sinusoidal currents of much higher frequency than the bandwidth of your current controllers.

Here's a block diagram of how AFC works, taken from the paper "Adaptive feedforward cancellation viewed from an oscillator amplitude control perspective".  \(r(t)\) is the reference (current, in my case), and \(d(t)\) is a disturbance (back-emf harmonics, in my case), and \(y(t)\) is the control effort (D or Q voltage in my case).

And here's how the AFC(s) are integrated into the control loop.  The red box is your normal feedback controller (in my case the PI current controllers for D and Q current).

The AFC works kind of like a pair of integrators on the sine and cosine components of the periodic part of the error.  If there's zero error \(e(t)\), the AFC outputs the sum of \(\cos(\omega t)\cdot (\text{cos integral})\) and \(\sin(\omega t)\cdot (\text{sin integral})\), which is some sinusoidal thing.  If there is some error, the portion of it at the same frequency as \(\omega\) doesn't average to zero when multiplied by the \(\cos(\omega t)\) or \(\sin(\omega t)\)'s before the integrators.  The integrators then integrate up to whatever value drives the  \(\omega\) frequency component of the error to zero.

The slight modification to get this to work for motor currents is changing the \(\omega t\) to be \(\theta\), the electrical angle of the motor.  The periodic disturbances are not a fixed frequency in time, they are a fixed frequency in state. 

This basically just works.  Implementing a 6th harmonic AFC on both the D and Q current loops completely eliminates the 5th harmonic in phase currents.  Here's the simulation result:

Phase currents:

D/Q currents:

And here's what the integrators in the AFC do:

There's one simple addition to the controller which makes it behave a little better.  The magnitude of the harmonic voltage is proportional to how fast the motor is spinning - so if the motor is accelerating, the magnitude is increasing, and the AFC integrators are constantly playing catch-up.  This means that at a constant acceleration, there will be a constant error in the AFC:

The AFC still does a pretty good job even at high acceleration, but how well it does depends on how large the AFC gain is.  Below you can see the integrators ramping up with speed:

The simple fix for this is to divide the error by angular velocity before integrating, and then multiply by angular velocity at the end of the AFC calculations.  This way, the AFC integrators integrate up to the harmonic in the flux linkage, which is constant, rather than the back-emf, which is proportional to speed.  Honestly, this change doesn't make a huge difference, because the time constant of the integrator can be quite fast compared to how fast the motor can accelerate, but it's kind of cool none the less:

Now the integrators just converge to constants, even as the motor accelerates:

Pseudo-code implementation:

h = 6.0f;  // Harmonic number
k_afc = 100;  // AFC Gain - larger gain converges faster

s = sin(h*theta);
c = cos(h*theta);

i_error = i_ref - i;
if(abs(thetadot) > 1) //avoid dividing by zero
 afc_cos_int += dt*i_error*k_afc*c/thetadot; 
 afc_sin_int += dt*i_error*k_afc*s/thetadot;
afc_out = thetadot*(s*afc_sin_int + c*afc_cos_int);

i_error = i_ref - i + afc_out;  //Now use this error in the PI current loop.

And here it is after implementing on the hardware:

The AFC behaves a little strangely when the voltage saturates (causing higher harmonics to show up), and I haven't put any effort into fixing that, but for most operating points it works quite well.

Here's an FFT of the phase current at the beginning of the post.  There are significant components at 5, 7 and 11 times the electrical frequency:

And here's the FFT after adding an AFC at 6 times the electrical frequency:

In addition to canceling out harmonics, you can use this technique to add in harmonics of your own, or track periodic current references.

For example, a typical way to cancel out cogging torque is to add in an AC component to your Q-axis current reference which tries to cancel out the cogging torque.  The controller's ability to track this reference depends on how fast the motor is spinning, and its bandwidth.  But if you add in an AFC at the cogging frequencies, the AFC just takes care of tracking the cogging current.

Or if you want to add certain harmonics at the phases, you can do so by taking the dq0 transform of the harmonics you want, then adding those to your D/Q current references with an AFC to track them.  Say, for example, you wanted your phase currents to be more trapezoidal, you could take the transform of the trapezoidal waveform, use that as your D/Q current references, and add AFCs at the first few Fourier coefficients in order to track the reference at high speed.


  1. Are you using the classic FOC strategy for non-salient poles motors (idref=0, iqref=some current command in order to get desired torque)? because graphs show id current values close to -15A in steady state.

    1. For SPM motors, usually yes (although for these motors, there's slight saliency at very high currents, so you can get like 1.5% extra torque by shifting some current to the -D axis...). And for my robot stuff, I never operate near the field-weakening region.

      High D-axis currents are a nice way of testing motor controllers without attaching a load to the motor.

  2. Are you the author of "A Low Cost Modular Actuator for Dynamic
    Robots"!? You are genius! I am from China, it's such an amazing thing for me to find your paper and your blog. Keep UP!

  3. Great article, Ben!
    Just a small note: According to your Mathematica script and similar calculation I did some time ago, both harmonic terms must be negative in the dq-voltage equations. Just for the correctness of the model, it doesn't matter for the AFC anyway.
    Keep up the good work!

  4. What is the purpose of removing the ripples from the current? Does this improve the motor performance? Does it noticeably reduce torque ripple?

    It seems to me that reducing the current ripple will add more ripple in the phase voltages. When reaching the edge of the available voltage, this causes issues and you mention this. Do you have a strategy for dealing with this, or does your system have enough headroom (or inversely, low speed/torque) to avoid problems?

    This system must see an error to respond to, so it is always reactive. Do you think the error is so predictable it can be changed into a feed-forward system instead?

    I have not seen your complete implementation, but I would expect some issues to arise around zero speed. Did you encounter any issues at standstill?

    Btw, the link to the paper is not working any more.

    1. There were a few motivations
      - the ripple current can cause extra losses by several mechanisms - extra resistive losses, and extra eddy current losses as well.
      - Cancelling out all the harmonics doesn't necessarily reduce torque ripple (if the motor has these harmonics, that means it's not sinusoidal in the first place and will inherently have torque ripple with sinusoidal currents), but the same controller lets you add in your own harmonics, which could be used to smooth out torque ripple. Or, for example, if you wanted to cancel out cogging torque at high speeds, this would perform much better than trying to track a periodic current command that cancels out the cogging with the usual field oriented control setup.

      - Yes, you are correct that it has issues when you run out of voltage. Fundamentally there's nothing that can be done once the voltage is saturated, so probably the right strategy is to just disable the harmonic compensation near the voltage limit.

      - The whole point of AFC is that it can compensate a periodic error without any lag, so it's not really reactive in the typical sense. There's a time constant associated with the AFC integrators reaching the levels to compensate the periodic disturbance, but once it's converged, it basically acts like a feed-forward to cancel out the harmonics.

      - No issues at standstill.

  5. Great article! Could you please provide the name/title of the paper? The link does not work anymore and it would be a very interesting reading. Thanks.

    1. Updated the post. The paper is "Adaptive feedforward cancellation viewed from an oscillator amplitude control perspective". There's a short journal version of the paper, as well as a full PhD thesis with the same title by the same author.

  6. Great article!
    I have the same current waveforms but at low speeds rather than higher speed, I measured the back emf at the low speeds and it came out pure sin with 1.4% THD max.
    Do you know what could be the reason for this waveform? Thanks.

    1. Is this with closed-loop current control, or applying open-loop sinusoidal voltages? If it's open-loop, nonlinearity in the output voltage from dead time will cause non-sinusoidal currents for sinusoidal PWM duty cycles - that's the first thing that comes to mind. You could try locking the rotor or driving fixed inductors to completely remove back-emf from the equation.

      If this is closed-loop (and the control controller it's doing a good job tracking), maybe there is current sensor nonlinearity? Then the controller would think the currents are nice and sinusoidal, but if you measure with a current probe you would see harmonics.