Wednesday, January 13, 2010

3ph Duo Wrap-Up Part 2: Control

This is the conclusion to:
3ph Duo Wrap-Up Part 1: Field-Oriented

And falling squarely in the category of "ZOMG," the unabridged (but barely edited) 78-page Rev0 write-up that does not include specific software implementation at all yet because I am so sick of looking at it:
3ph Duo: 2 x 1kW Brushless Motor Controller
w/ Field Oriented Control
Design Notes [DRAFT]

It does have a lot of other cool stuff, though, including MOSFET selection and analysis, a more detailed F.O.C. explanation, BLDC vs. BLAC analysis, mechanical design, etc. etc. etc. I promise I will update it with some software details when I can stomach it again. Comments greatly appreciated...

When we left off, the controller was just barely able to generate six sine wave PWM outputs (three each for two motors) and estimate the position and speed of the rotor based on Hall effect sensors. Using this position estimate and current sensors, it could also measure the vector current, expressed in the two-dimensional d-q coordinate system we set up to make life easy. The purpose of Part 2 (of 2, thankfully) is to explain what we do with this information that makes field-oriented control so useful.

Part 1 hinted at the purpose of field-oriented control. (No, it's not just for making the motor quieter.) The goal is to place all of the current on the q-axis, right in between magnets, where it can pull hardest on the magnets and produce the most torque. Any current lagging behind onto the d-axis because of motor inductance is not doing useful work. This is now a controls problem.

I've taken just about every controls class at MIT (although I did drop a couple half-way through), so sometimes I take for granted that everyone understands the basics of a feedback control system. But for the sake of fulfilling my New Year's Resolution, I won't. The idea is really simple: You measure a value, in this case current, and compare it to the value you desire. If the desired value is higher than the measured value, you do something that will increase the current. If the desired value is lower than the measured value, you do something that will decrease the current. The result is a corrective action that always tries to bring the measured and desired values together. Textbook feedback loop:

Not that kind of plant. Plant is whatever thing you are controlling.

It's borderline common sense. If the water's too hot, you turn the heat down. If it's too cold, you turn the heat up. If you're good, you can predict the overshoot and preemptively turn the heat down so as not to burn yourself. Eventually, you get to the right temperature. Only by adding math do we manage to make control systems more complicated than that.

Anyway, this is what we can do with both the d-axis and the q-axis current that we figured out how to measure in Part 1. Enter the "synchronous current regulator," a special application of the textbook feedback loop to these types of motor control problems. It's synchronous because it works in the rotating d-q coordinate system we set up before. A block diagram is worth 1,000 words in this case:

Synchronous Current Regulator. Click to enlarge.

Calm down, calm down, it's not that bad. The circle with the M? That's the motor. The triangle? That's the three-phase inverter, i.e. all of the power electronics hardware. Everything else is software. The Park transform? That's the trigonometry part that projects the A, B, and C coil current measurements onto the d-axis and q-axis, just like in Part 1. It needs the rotor position to do so. Then there are two feedback controllers: one for the d-axis and one for the q-axis. The d-axis controller's desired value is always zero. The q-axis controller's desired value is the torque command, and can be positive (accelerate) or negative (brake). The outputs, called PWMs, are switching signals that set the average voltage command on each of the three phases.

Now, that's not exactly what I did, but it's pretty damn close. Here's mine:

Modified Synchronous Current Regulator. Click to enlarge.

The differences are small. Instead of an inverse Park transform to project back from d-axis and q-axis voltage commands to A, B, and C voltage commands, I use the fast-loop sine wave generator that caused so much trouble in Part 1. And instead of a magical rotor position measurement, likely derived from an encoder or resolver, I use Hall effect sensors and interpolation. I chose to do this because cheap motors have Hall effect sensors, not encoders or resolvers.

The feedback loops are the same. Well...not quite. The difference is what comes out of the d-axis and q-axis controllers. Can you spot it? In the standard version, a d-axis and q-axis voltage (PWM) come out, then get tranformed back into values for A, B, and C voltage. This requires more trig in the fast loop...not good for my poor little processor. In the modified version, a phase (angle) and magnitude come out of the d-axis and q-axis controllers, respectively. Phase is a simple shift in the sine big deal. Magnitude is a scaling operation, which, as we saw in Part 1 is still a pain in the ass on a microcontroller with no hardware multiplier, but it's not as bad as more trig. At least it scales all three values equally.

Where the heck did that modification come from? It's actually one of the first things I wrote down, and I never considered doing it anyway else. It's the least processor-intensive and most physically intuitive, IMO, even if it's non-standard. But does it actually work? Well, after about a month of screwing around with software, I finally got to the point where I could run this controller in earnest, under load, with the modified synchronous current regulator. First, here's what happens when the d-axis controller is turned off, meaning no phase angle correction can be implemented...the same as fixed-timing:

This looks very similar to the measurement done in Part 1 on the front motor. As the motor increases in speed, the effect of current lag is more and more pronounced, putting more current on the d-axis. The rear motor shows the effect even more, since it has a higher inductance. The controller tries to keep the q-axis, torque-producing current constant. The result is that the total current, the vector sum of d-axis and q-axis components (or of A, B, and C components), must increase in order to maintain constant torque.

Now the same motor and load with the d-axis phase control on,

Plain as day, the phase advance takes out the d-axis current. Just 13º lead or so is all it takes on this motor at 600RPM. Meanwhile, the q-axis controller makes sure torque is held constant. If you want proof, look at the acceleration times in both cases...they are very similar. But in the case of full d- and q-axis control, the total current is reduced thanks to the zero d-axis component. This is clearly a more efficient operating point.

And just so you don't think I'm pulling your leg, it does work with two motors at the same time:

(Believe me, I did consider leaving this test out and hoping nobody would notice...)

Well there you have it, theorized and confirmed in experiment. The modified synchronous current regulator works. (I honestly was never sure it would, but I would have bet on it.) I can't compare it to the standard synchronous current regulator because the standard version simply would not run on my hardware. But, I did simulate the difference and I can assure you I was pleased with the result. If you don't believe me, read the unabridged version.

And that's the end of the 3ph Duo field-oriented control upgrade. What? Were you expecting some dramatic ending? That's not how things work when 90% of the upgrade is done in software. You do a lot of work for...something that looks the same as it did before. That's why there are no pictures of videos of real things in this post. The only good thing about code is that once you do it, you can copy-paste it for years. (Have you ever wondered where all my data comes from? I never talk about data acquisition software...)

Anyway, now that that's done, I feel the incredible urge to go build something. Something fast.....


  1. Boy, does this take me back to memories of my own EE controls classes. This is really impressive considering the hardware you are running it on!

    Question: did you calculate the efficiency improvement as compared to the standard square wave BLDC controller? For a small battery powered scooter like this, that translates directly into more run time so I'm curious what you're seeing.

  2. Thanks. I haven't done the efficiency calculation. There are just so many variables! In the big write-up, I did look at BLDC vs. sinusoidal, with and without phase advance, at one particular operating point of a made-up motor. If you normalize to output power, sinusoidal control with phase advance has a slight edge. But this is all simulation... What I should really do is run both controllers for 10mins and measure everything.

  3. can u emial me the arduino code 4 it

  4. Hi Shane,
    Great job on the builds.
    Perhaps you could shed some light on the following thought for me - I see that you used a 16 bit MCU to implement FOC. Do you think an 8 bit MCU could also be used to do this? There are some tailor made 8 bit MCUs out there for FOC (like the XC878) but i am talking about a standard 8 bit MCU. If you think it cannot be done, what would be the potential problems with using 8 bit?

  5. I would bet money that it could be done on an 8-bit MCU...for one motor. In fact I have a friend who insists he will do FOC on an Arduino (see above...)

    All you need, hardware-wise, is three PWM-capable compare units on one or more timers, plus some current sensing analog channels.

    You might need to sacrifice the speed of the fast loop. It may not run at the PWM frequency. But that's really totally fine, since that's just an upper limit as the fastest you could possibly modify the outputs anyway. So, you would generate new sine wave values every two or three PWM cycles instead. As for the slow loop with the actual floating-point controllers, it can run at whatever speed is possible.

    I think this is very workable, although I have no real desire to try it. :)

  6. Shane,
    Thanks for the reply.
    I'd like to pry into your FOC knowledge again if I may. I'm interested in using FOC for field weakening as well as torque optimization. Do you think a field weakening effect could be achieved by simply changing the d-axis reference from 0 to a value less than 0? This should give a resultant d-axis vector which decreases as the d-axis reference becomes more negative. I read a section in Meveys' thesis (awesome reference by the way) pg 225-228 that explains this is the general idea. I was wondering, did you try to do this with your scooter motors to extend their base RPM? How do you think the q-axis reference would need to be changed for field weakening? I expect adding field weakening will increase the complexity slightly. Still in the scope of a little 8-bit MCU? Any potential issues that you can see? (Sorry for all the q's - its damn hard to find good answers to these questions).


  7. You're exactly right. Since you already have a d-axis controller running anyway, setting its reference negative is field weakening.

    As you increase the d-axis current, it might be necessary to decrease the q-axis current so that I^2*R losses do not also increase. This will reduce torque, but extend the speed range. How much field weakening you can achieve depends a lot on the inductance of the motor. Haven't tried this on the scooter because it's already dangerously fast.

    There's also a very interesting catastrophic failure mode with field weakening, where the controller fails while in the extended speed range. Then, the back EMF (which is higher than the battery voltage by now) gets applied directly to the inverter. It can destroy the inverter and/or send large bursts of current back into the battery through the flyback diodes. Just something to watch out for.

  8. Shane,

    This project is cool, but your write up is incredible. Thank you so much for the extra effort it took to get all this information out there.

    I would never have thought motor control and timing would be an 'interesting' topic to me, let alone that I might try to make a controller myself. Now I just might.