Showing posts with label FOC. Show all posts
Showing posts with label FOC. Show all posts

Tuesday, March 26, 2013

Motor Dave is Back! (And so am I...mostly.)

I took a bit of a break from blogging to move across the country.


Loading up my cube during the coldest day of the year in Boston.
I escaped the Northeast right before the string of major snow storms and am now based in sunny Seattle at a company called Freefly Systems where I will be...doing pretty much the same thing I did in academia, over-engineer motor and control systems. I may occasionally re-post some cool videos from the job, but for the most part this blog will remain dedicated to my personal projects.

Some brief updates:

My custom-built glass table survived the trip, somehow:

The right angle joints rotate up to protect the corners of the glass. I totally designed it this way...
Pro-level ratchet strapping.
And I finally have enough room to put all four chairs around it!
If you ever find yourself needing to move a 100lb slab of glass across the country, let me know and I'll give you some tips.

I now own a car:

It's a bit wet in Seattle, actually....
If you don't believe me, figure out what this is a picture of.
Well, I own some fraction of a car...maybe 25%? More than I used to, anyway. Unlike Boston, It's pretty much a requirement for getting around. I haven't owned a car since high school and the car I had back then was worth less than my computer, so I'm glad to finally have something (hopefully) reliable and fun.

My Tesla coil in now only 3-4 orders of magnitude less impressive than a oneTesla:



I intentionally did not ship my coil with the rest of my possessions because I wanted to work on it a bit more before I left. (I promised Clare Fairchild that it would make some form of sparks before I left.) All systems seem to be working as expected up to this test which was at 48V DC input, so still low power. I carefully wrapped and shipped the coil separately so that I can continue to work on it here, when I get the chance, tuning it and turning the power up so that it can break out on its own. Once I get some respectable arcs, I will take another stab at writing a MIDI parser so it can play music.

tinyKart is a wreck, but it's getting a complete overhaul:

What
the
fuck 
happened
here?
Pretty much every part is covered two years worth of dirt deposited by snow and rain, including the most recent stretch of endurance laps run during a severe downpour at Maker Faire NY. Besides that, the damage report consists of: both pulleys and motor shafts (destroyed), one drive belt (destroyed), two spindles (bent), one brake mount (bent), both chassis plates (bent), and at least one full set of tires. Basically, the whole thing needs to be taken apart, cleaned, and fixed. However, that gives me the chance to do something I've wanted to do for a while: paint it.

Multirotor-assisted primer drying. Very effective.
It's done a lot more than we originally thought it would, so a bit of maintenance is definitely in order. It might take a bit of time to get it all back together properly, but when it is, it will look much better than it ever has, I think.

Lastly, Motor Dave is back! Dave Wilson, "Motion Products Evangelist" at Texas Instruments, has returned to the bloggernet as well with a new series on how to tune your PI controller, starting with Part I here. It's specific to the typical nested PI controllers involved in motor control (current, speed, position). If you haven't read his previous series, The Ten Commandments of Digital Control, you should. It starts here. I went to a TI workshop co-hosted by Dave about a year ago when TI's BLDC solution, InstaSPIN, was relatively new. At the time he hinted that there might be a future version: InstaSPIN FOC. Well, it's here now!

If you've been following my blog for a while, you probably have seen my many many posts of Field-Oriented Control, sensored and later sensorless implementations thereof. One thing I've not been very good with is putting out hardware that other people can easily access and play around with to try out this powerful motor control technique, without messing around with a lot of low-level code. (I like messing around with low-level code, but I can totally understand why most people hate that part.)

Anyway, you can now buy a kit for $300 that has enough power to drive a small electric vehicle motor and is loaded with a thorough FOC code library. Alternatively, you can just buy the control card with FOC library and develop your own high-power inverter stage. Or you can just buy the TMS320F28069 microcontroller with built-in FOC library and use it in your own hardware.

Though I haven't dug too deeply into the code, the basis for InstaSPIN FOC, and particularly the FAST observer, seems somewhat similar to the flux estimating structure I've used in my own sensorless routine. Flux is a nice quantity to observe, since it isn't speed-dependent like back EMF. The tricky part is keeping the observer happy at low speeds where not much rotor position information is available. InstaSPIN FOC seems to handle this situation using a "forced-angle" startup routine but then can also transition back through zero speed seemlessly when properly tuned.

I'm not sure it would cause me to deviate from making my own FOC software, but it's definitely something worth checking out. 

Saturday, September 8, 2012

Excellent Video Presentation on Field Oriented Control

Here's a really great video presentation on Field Oriented Control (FOC) by Dave Wilson of Texas Instruments:


I was lucky enough to see this presentation live at a TI workshop in the spring. It covers all the basics of (sensorless) FOC, which is what most of my motor controllers are using now. By itself, it's probably not enough to write an FOC controller from scratch, but combined with the other information on TI's Motor Blog, most of the important techniques are covered. Of course, for any gaps there is still the ultimate guide to brushless motors, James Mevey's 2009 Masters Thesis.

In case you're wondering how the back EMF observer in this presentation compares to the dirt-simple flux observer I've been using in all of my FOC code, here's roughly one page of math converting between them:


The conclusion is that my dirt-simple flux observer differs from the back EMF observer in the presentation by only a second-order low-pass filter (2DLPF). This is pretty amazing since the structure of the two observers, and even the quantity that they are observing, seem so different. 

The properties of the extra 2DLPF are determined by the PI controller gains in the current error feedback of the back EMF observer. Higher gains give a lower time constant and faster tracking, but also more sensitivity to current sensor noise. My flux observer doesn't have this degree of freedom; it trusts the current sensor all the time and is therefore more susceptible to noise on that signal. (It's the extreme case of the feedback gains being very high.)

Speaking of flux observers...I promise I will write up my Gen. 1 sensorless algorithm soon...

Friday, July 13, 2012

FFv1.1 Ground Firmware Testing / FFv1.2s

Charles was kind enough to volunteer his daily mode of transportation for motor controller testing:

Read: The previous controller melted, or something.
Melonscooter, so named for the "melon-sized" Turnigy C8080-170 brushless motor that drives it, has been through a lot of motor controllers. The C8080-170 no longer exists, but the longer variant, the C80100-130 is now available through Leaders Hobby (what you get if you send "HobbyKing" forward and backward through Google translate a few times) under the EMP brand name. I used to think this was the hardest motor to drive, within the set of small EV traction motors. Used to. Then I met this insane thing:

FreeFly David's custom e-bike motor.
After attempting to drive this two-turn monster e-bike motor with only marginal success, the C8080-170 looks rather tame. Especially since Melonscooter has fixed gearing and no freewheel, so it's entirely possible to kick start it. That, and the low-cogging 12-slot/14-pole configuration make it seem more feasible. The C8080-170's resistance (21mΩ line-to-line) and inductance are very low, but I had already pushed the overcurrent latching fault to 200A to deal with the current ripple on David's e-bike motor, so again this seems relatively manageable.

It looks much more legit with a 3d-printed case.
FFv1.1 is still undersized for the C8080-170 motor. Additionally, since Melonscooter runs a 40V battery pack, I'm using one of the FFv1.1 boards with the relatively wimpy 60V FETs (IPB034N06N3 G). Based on the e-bike testing, I decided the maximum phase current they would be able to handle for acceleration would be about 50A. At 3.4mΩ per FET, the conductive losses at 50A phase current add up to (3/2)*(50A)²*(0.0034Ω) = 12.7W. Add to that the switching losses, current sense resistor dissipation, and other parasitic resistances, and the power stage might be dissipating 20W or so of heat, which is a lot for a board with no heat sinks.

Tuning the sensorless FOC parameters for the C8080-170 took surprisingly little time, partially because I'm getting used to the steps required and partially because I already have good measurements of inductance, resistance, and back-EMF constant from this motor. It also helps that it could be push-start, since adjusting the open-loop ramp start takes a while. After a few iterations of parameter adjustment, it was ready for test driving:


It's way quieter than usual, due to the sinusoidal drive voltage. The current is low for what the C8080-170 can handle, so the acceleration is nothing spectacular. Although, due to a software error the acceleration currents in the video exceeded 50A by a bit. You can see the wireless data-logging software running in the video, but I stupidly overwrote all the test drive data, so I'll have to capture it again later.

The peak flux amplitude was about 5.5mWb. Multiply by 7 pole pairs to get the per-phase back-EMF constant, about 0.042V/(rad/s). That's peak line-to-neutral volts. Invert, divide by two, and convert units to get the approximate Kv: 124rpm/Vdc. This is substantially lower than the 170rpm/Vdc the motor gets with BLDC-style square wave control. Less speed per volt, more torque per amp.

The next step for FFv1.1 ground firmware testing will be upgrading to nicer FETs and improving heat sinking a bit. One FET option is the proven 75V IRFS3107-7, used on Cap Kart's half-bridge and the Victor 883107-7 controller. These have already shown that they can handle 75A acceleration current with no trouble. An even lower resistance option would be the 60V IPB017N06N3 G. It also has half the gate charge of the 3107-7, so it will cut down on the switching losses. I'm not sure I would use it with a 12S LiPo (44.4V nominal, 50.4V fully charged) system, but the current 60V FETs have proven sufficient for 12S A123 (39.6V nominal, 43.2V fully charged).

On to smaller things...

FFv1.1 (and v1.0, really, since it was virtually the same) have been very successful so far. The DRV8301 magic chip has proven its worth, since I have yet to see any noise problems at all. The target application for FFv1.0 and v1.1 was large multirotor motors, specifically for the CineStar 6, and I designed them with 20-30A continuous motor phase currents in mind. With good heat sinking or air cooling, they can probably handle 50A continuous phase current. But now I realize that it might be useful to have a smaller, lighter version for things in the 10-15A continuous phase current range. So it's time for a new revision, FFv1.2s:


The logic and gate drive sections of the board are exactly the same as v1.0 and v1.1. The power section has been entirely redone to use six Power SO-8 FETs. Power SO-8s are increasingly common thin, leadless SMT packages for power MOSFETs. There are a huge variety of lower-voltage FETs in this package including some amazing ones like the Si7192DP at 30V/1.9mΩ. They're also easy to heat sink from the top surface, since they're very thin. So even though the power stage looks disproportionately small, it should be able to handle a decent amount of power.

My target application for these is the smaller multirotor motors, such as the ones on my Talon quad. The FFv1.1 boards have already shown significant increase in efficiency on the Talon quad, but they eat up all their advantage by being much heavier than the Turnigy controllers it normally uses (65g from FFv1.1 vs. 19g for the Turnigy Plush 18A). I don't know if I'll get all the way down to 19g, but FFv1.2s should be close to that. Even though the board area is only 33% smaller, the weight should shrink by a lot more with the thin FETs and smaller capacitors.

Because the logic and gate drive section is the same as FFv1.1, it will still be a full-featured sinusoidal FOC setup with wireless capability through the XBee. (For minimum cost/weight configuration, the XBee will be left off, but it's useful to have the header there for wireless programming/debugging.) As usual, I will post the relevant design files pending testing.

Monday, June 18, 2012

Get down from there, flux. You're not DC. You're not even a real measured quantity.

I recently fixed a nagging problem with the flux estimator, maybe the key part of my sensorless field-oriented control method. I'm in the process of writing up my current approach to sensorless control, so I've finally been generating some nice figures (ones that aren't made in PowerPoint) that will hopefully explain some of the math better than I can in words. Here's what the flux estimator looks like:

I guess if you use LabView this is what the code looks like too...
The flux estimator takes the phase voltage and phase current as inputs, and runs them through the constitutive equation for a round-rotor permanent magnet motor:


The result of the integral form of the equation is the phase flux linkage. This, like back EMF, contains information about the position of the rotor. Unlike back EMF, it doesn't vary with speed, which makes it a nicer quantity to estimate in most cases.

Doing an integration in software on real signals is not always practical. Ideally, the voltage and current are purely AC signals. But in real life they may have some DC offset for a variety of reasons. The current sensors may not be well-zeroed. Even so, the zero value may drift and there will always be at least some offset at the minimum resolution of the sensor. The voltage comes directly from the known PWM values, but it could also be biased due to rounding or other numerical issues.

Any bias on the input signals would cause a pure integrator to ramp the output up to infinity. For that reason, it's common to implement an integrator as a low-pass filter instead. At high frequencies, the a low-pass filter with the appropriate gain behaves the same as a pure integrator. That gain happens to be exactly the same as the time constant. Another way to think about it is that it's a pure integrator in series with a high-pass filter. This lead to the same transfer function and behavior: integrating frequencies above cutoff but attenuating any DC bias.

Attenuate...but not eliminate. 

The pseudo-integrator's DC gain is the time constant of the low-pass filter. So, although it won't ramp off to infinity, there will still be some DC bias in the flux estimate and it will get worse as the time constant for the low-pass filter is increased. This creates a bit of a trade-off, since increasing the time constant can help improve the low-speed performance of the flux estimator but will cause more flux estimate bias. Here's what the flux estimate looked like on the CineStar 6 QC-3328 motors at approximately hover speed:


There are a few things to notice. One is that the current waveforms are offset by at least 1-2A. (Look at the maximum and minimum current on each phase.) With a nominal phase resistance of 46mΩ and a filter time constant of 6ms, that would lead to a flux bias of (2A)(46mΩ)(6ms) = 552μWb. This is almost half of the expected flux amplitude, and it shows in the flux waveform, which is shifted up by quite a bit. The flux estimator has a saturation parameter, set to 1500μWb, and you can see the top of the waveform being clipped in this data.

Before attempting to reduce the current sensor offset, I took out the easier problem, which is the voltage offset. The 3-phase sinusoidal voltages are generated according to an 8-bit sine look-up table (LUT) which stores 256 numbers between 0 and 255 that trace out the amplitude of a sine wave. As it turns out, the actual average of these numbers is 127.5, not 127. This alone could shift the flux waveform up by (0.5/255)(25V)(6ms) = 294μWb. Just by switching to more precise math when calculating the voltage on each phase, I was able to eliminate this source of offset immediately:


The clipping of the flux linkage waveform at 1500μWb is no longer present, but there's still a good amount of bias. The next step I took was to have the current sensors auto-zero at the start of the program. It's an obvious and common thing that I neglected to do mostly because I kept saying, "I'll do it later," and I didn't realize how much it would matter to the flux estimator. After adding in a simple auto-zeroing routine, the flux is now back to dead center:


There's an interesting pattern present in this data which I think was caused by sitting at a very steady speed for pretty much the entire capture. Maybe now that the flux waveform isn't being clipped, things settle in to a more regular pattern. Or maybe I just happened to sit at exactly the right RPM for aliasing like this to occur. Either way, to confirm that it wasn't a problem I had just introduced, I redid the test and varied the speed a lot more:


Here, the current is more varied because I was accelerating and decelerating a lot. But the flux waveform is still clean and centered around zero. I wasn't sure how much this fix would improve the performance of the sensorless position estimate. For sure, you can hear the effects of the waveform clipping on certain motors. Here's a GIF of all three flux/current waveforms to better show the difference:


The third, most unbiased flux estimate also produces the most uniformly-spaced and scaled current signals, which is probably a good thing in terms of efficiency. The flux zero-crossings will be evenly spaced, which should improve the position estimate and the FOC. Initial bench tests seem good, but I'm really looking forward to putting the improved version on all six ESCs and doing another CineStar flight test, this time with a Watt Meter.

Sorry for the boring all-math post. But it was interesting to see an immediately obvious cause-effect relationship in this quick and simple fix.

Thursday, April 19, 2012

Sensorless Start-Up / Speed Control

It's spring demo season again. I'll be at the Cambridge Mini Maker Faire on Friday, along with the MITERS crew, with an assortment of projects. Come check it out. Follow-up post to come.

For now, time for a massive multi-controller update. The Sensorless, Sine-Commutated Field-Oriented Current Control (SSCFOCC) algorithm I've been working on has been sufficient abstracted now that I can develop for it on two different motor controllers (3ph v3.1 and FFv1.0) at the same time. (3ph v4.0 is coming soon and DirectDrive v1.0 still exists, I promise...)

Before I start developing new hardware and potentially writing a entirely different sensorless control algorithm, though, there were some loose ends I wanted to clean up in the current algorithm. Once these points are addressed, I will go back and write up a summary of my first-generation sensorless code since by now it's too complex for individual blog posts.

But First...


More Position Filtering

Loose End #1 was a problem with the rotor position estimating filter used to clean up the rotor angle at high speeds. I added this at the end of the last sensorless post and even though it immediately improved the high-speed performance of FFv1.0 on the hexrotor motors, there was a weird side-effect on the flux vs. angle graph. The flux estimate would begin to lead the rotor angle estimate at high speeds, which should not happen since the rotor angle estimate is derived from the flux estimate. The flux vs. angle curve should be constant. What the?

After staring at the code for a little while, I identified this a rather complex software error on my part tracing all the way back to a subtlety of BWD's sensored FOC code... I'll spare you the details, but I fixed it and now the flux estimate is much nicer:

Pneu Scooter w/ 3ph v3.1. Compare to unfiltered flux estimate.
Much of the "noise" from the 2d plot is shown to be offset at low speed (<200rpm).
Hexrotor motor with FFv1.0. Compare to the unfiltered flux estimate.
And in nauseating pseudo-3d.
The low-speed offset is a known issue having to do with the fact that the integrator at the heart of the flux estimate is implemented as a low-pass filter. There is also a phase offset in the flux estimate resulting from this practical non-ideality:


Since this is a known offset, it could potentially be subtracted off. Or the low-pass filter could be designed such that at the start-up routine exit speed, the offset is less than 15º or so. For the data above, that would be about 150rpm. Speaking of start-up routines...

Start-Up

Loose End #2 was the lack of any start-up routine for either controller. I've been putting it off for a number of reasons. For one, Pneu Scooter really doesn't need a start-up routine. The sensorless algorithm has no trouble picking up the rotor speed at as low as 50rpm and that's well within single-kick speeds:

One kick gets to 75rpm, at which point the flux estimator has locked in.
Also, Pneu Scooter really doesn't have enough torque to justify a no-kick start-up routine. Even at peak current (40A), the acceleration is something like 150rpm/s. The sensorless start-up will achieve far less than peak torque, though, since it won't have the benefit of optimum current vector placement. So it could mean a couple seconds of balancing on a barely-moving scooter while the speed ramps up. It's just much more natural to kick start.

FFv1.0 and the hexrotor motors, on the other hand, almost definitely need a start-up routine. Even though in this video, a very large (14x4.7SF) prop starts cleanly and quickly with no start-up routine at all. The command PWM goes high enough that the motor is forced to do something, and by luck it gets kicked in the correct direction at sufficient speed for the flux estimator to lock in. But this is unreliable (works maybe 50% of the time) and inelegant, so it should really have a slow-ramping startup routine as well.

Maybe the real reason I haven't implemented a start-up routine yet is because it's easy. At least, the most obvious way of doing it is easy. Lacking position information, there isn't much choice in how to drive a brushless motor: it becomes a coarse stepper. Except with sinusoidal commutation it can be like a microstepping coarse stepper, which is still pretty smooth. The point is, the only way to drive it with no knowledge of the rotor position is to put current in somewhere and wait long enough to know that the rotor has most likely reached the position you told it to go to. With that in mind, I wrote a simple start-up routine with four states:
  1. IDLE: Wait at zero speed until the user commands a positive torque or speed.

  2. PARK: Place current vector at a fixed angle and wait for some time for the rotor to reach a stable position.

  3. RAMP: Rotate the current vector with a constant angular acceleration that is sure to be achievable by the rotor given the amount of current commanded and the estimated load inertia.

  4. RUN: After a certain speed, switch to sensorless field-oriented control using the rotor angle predicted by the flux observer.
The ramp state here differs a little from BLDC-style sensorless start-up routines that use six-step voltage-mode commutation. Since this ramp state is still current controlled, the possibility for variable user-commanded acceleration during "open-loop" start-up is present. The angular acceleration of the ramp is linked to the amount of current commanded. If you go light on the throttle, the ramp takes longer.

Since the load inertia can't be exactly known, the start-up ramp acceleration has to be conservatively chosen. The start-up torque will therefore be significantly less than the run torque, and the efficiency will be very low. This is a common trait of sensorless start-up algorithms and the best way to minimize the effect is probably to get out of start-up as soon as possible. Transitioning to closed-loop sensorless control at 5-10% of the maximum speed seems to be achievable.

Anyway, enough hypothesizing. Here is my first shot at a sensorless start-up for Pneu Scooter, the harder of the two challenges:


The ramp goes from 0 to 150rpm in about 3 seconds with 30A commanded current. This is about 50% of the acceleration that would be expected from closed-loop control, so it feels sluggish for the first three seconds. But, it is smooth and transitions cleanly to run-state closed-loop control at 150rpm. Making the ramp faster results in pole slipping, so this is about as good as it will get.

One option for improving the start-up is to get out of the ramp state earlier. The flux estimator is able to pick up the rotor movement at as low as about 25-50rpm, so waiting around until 150rpm sounds silly. But, the low-pass filter-induced phase lead is still very high at those speeds, so the transition doesn't work reliably. It's clear that the low-pass filter time constant and the ramp exit speed are coupled in this way. Something to think about for future optimization.

Another option is to use more current. This doesn't help the efficiency, but it will create a faster ramp. 60A for a short period of time shouldn't hurt the motor or controller, but I'll wait for 3ph 4.0 to test that.

Start-up for the hexrotor motors is a much simpler problem. For one, they have essentially no load at start-up when the prop is moving too slowly to create significant thrust or drag. The performance of the controller is also not at all dependent on low-speed torque characteristics since the minimum RPM seen in flight will be well above the run-state threshold. Here's a very light ramp (<5A) for the 14x4.7SF prop:


The threshold for transitioning from ramp state to run state is 600rpm, and once it transitions to run state the torque increases dramatically. The ramp can afford to be much faster without slipping poles, but for the purpose of reaching a safe idle speed for the prop, it almost doesn't matter. Note that the speed goes directly to idle speed, 1,000rpm, and sits there. That brings me to...

Speed Control

Loose End #3 is speed control for FFv1.0. Pneu Scooter, as a vehicle, is happy with current (torque) control. But for the hexrotor, the master controller may want to command an exact speed for each rotor. Speed is directly related to static thrust (though not linearly). Steady-state current is also related to static thrust (close to linearly). But with inertial transients to deal with, the performance of a speed-based controller might be better.

Actually, the simple way to do "speed" control is to directly vary the PWM duty cycle, bypassing the current control entirely. This controls speed because motor speed is approximately proportional to applied voltage, which is controlled by the PWM duty cycle. As it turns out, it's definitely possible with the modified Synchronous Current Regulator (mSCR) to use this control mode, bypassing the q-axis current controller but leaving the d-axis (phase) controller working. This gives the benefits of FOC (dynamically adjusted motor timing) but the simplicity of direct PWM control. In fact, this was what I used for the first few tests of FFv1.0. Here's some data showing it executing step "speed" commands:


At each step, the q-axis and d-axis current spike due to the inertia of the motor and prop. But, the back EMF brings the q-axis current back to a steady-state value as the prop speeds up or slows down, and the mSCR adds or subtracts from the phase to bring the d-axis current back to zero.

The benefits of direct PWM magnitude control are simplicity and robustness. With current limiting to prevent the spikes from damaging components, I think this could be a pretty good way to run a multirotor controller. It's how most ESCs operate, so it would feel normal. But, it has several downsides:

  1. It can't achieve minimum rise time. The step in voltage magnitude will give only as much current as the motor resistance will allow. A smarter controller could slew the motor faster using a voltage that is higher than the steady-state value at the target speed.

  2. It can't accommodate minor difference in motors/ESCs/props. If one motor is slightly weaker than the others, it will spin slower under PWM magnitude control. The master attitude controller's integral term can correct for this, but why rely on this?

  3. Motor speed is only roughly proportional to applied voltage. The actual speed depends on the back EMF, which is V-IR. At higher loads, the speed per applied volt is lower. Does this matter? Maybe not, since none of this is linearly proportional to thrust anyway.
A classical approach to true speed control would be to wrap an outer PID control loop around everything:


The speed control loop, a generic PID with saturation, feeds the q-axis current reference a value between the maximum braking current and the maximum accelerating current, depending on the speed error. The d-axis controller is still simply trying to maximized torque per amp by adjusting motor phase. (The more I think about it, the more the mSCR strategy makes sense in this regard.)

This video shows the start-up and PID-based speed control for FFv1.0 with the 14x4.7SF props:


The nice thing about PID control is that it's easy to understand and easy to tune. Unfortunately, the load in this case is very nonlinear. As the speed increases, the damping due to propeller drag goes up. So, the step response changes depending on the speed:

Real data from the 14x4.7SF prop.
From 1,000-2,000rpm, the chosen gains exhibit a lot of overshoot. From 4,000-5,000rpm, they're overdamped. With this data as a starting point, I made a quick simulation including the nonlinear prop load. Another nice thing about PID is that it's very easy to work with in a Simulink:

This is what grad students do all day.
After some shady parameter estimation, I could almost predict the step response shapes:


The real-life response is actually a bit faster than the simulated response, for some reason. Not going to complain about that. But, they're both pretty slow overall. The motors never reach peak current during speed steps. The slew rate can and should be much faster for the best possible speed command tracking. By tweaking the gains in Simulink, I can now get a feel for which way they should be pushed in real life to speed up the response and kill off some overshoot.

I also think there's a better way. This post is already quite long so I'll have to save that for next time, but there is a hint of it in the Simulink diagram...

For now, I leave you with a Kramnikopter that I bought for basically nothing and will be doing absolutely zero custom development for:

Yay, not-complicated flying things.

Wednesday, February 29, 2012

Flying Flux v1.0

New speed record: 9 days between motor controller designs.

3ph v4.0 was finished up last week, and even though it's an x.0 and I sometimes have bad luck on new major versions, I am pretty confident in the design overall. Pushing the 3ph line back to optically-isolated gate drive puts it in the same class as some of my most reliable controllers to date, such as Cap Kart's half-bridge, the Victor 883107-7, and 3ph v2.1. It's a low-risk modification that I think will pay off in cleaner analog signals and higher reliability.

And now that 3ph has become the stable design, I need a new experimental design. I've been meaning to try out a motor controller based on the Texas Instruments DRV8301 since it came out. This "everything chip" combines a three-phase gate driver with two current shunt amplifiers, an on-board gate drive supply with charge pump, and a separate buck converter for powering external logic. It seems too good to be true.

I've also been meaning to build an motor controllers to satisfy the requirements of RC aircraft, which is no easy task. I am much more at home with vehicle controllers where I can afford the weight of giant heat sinks, and the volume of separate logic and power boards, and the cost of fully-isolated gate drivers. But my RC friends have been urging me to try to execute advanced BLDC control with the power density and economics of commercial ESCs.

And then there's this:


Some clever people sent me a Cinestar 6 hexrotor frame, complete with motors, knowing that I wouldn't last long before deciding to build custom ESCs for it. To be fair, the commercial ESC that goes with it, a MikroKopter BL-Ctrl v2.0, is way more compact than anything I would make. But, it's an ATmega168/328-powered-square-wave-drive-ESC-with-direct-battery-voltage-derived-discrete-component-gate-drive that I can't bring myself to use.

So then, Shane, stop hiding behind massive heat sinks and low-RPM vehicle motors and design an ESC:

Introducing: Flying Flux v1.0
A quick overview of the features:
  • MOSFETS: IRFS3107-7 (75V) or IRFS3004-7 (40V), depending on the application. I love the D2Pak-7's. Cap Kart (all 300A of it) runs through four of these in parallel. There will be no heat sink other than the copper on the board and the wires coming off it, so I'm entirely relying on the low Rds to keep it cool. It's a heat-shrink-to-waterproof-style design.


  • Gate Drive: DRV8301, the everything chip, a 2A gate driver and a risky bet. I'm generally not a fan of everything chips because they put power and signal together in a way that makes EMI isolation very difficult. But it can't be any worse than driving MOFET gates directly with an ATmega328, right? I hope?


  • Current Sense: Two phase return current shunts, plus the internal amplifiers on the DRV8301. This is my first attempt at using current shunts instead of Hall effect sensors. Pros: potentially more accurate, conducive to synchronous sampling. Cons: Not isolated. That risk seems to roll up into the overall DRV8301 risk.


  • Logic Supply: The last trick up the DRV8301's sleeve, an on-board buck converter. It already has an internal gate drive supply, but this extra buck converter can be used to power the logic at 5V. It's compact and relatively beefy: up to 1.5A output.



  • Micro: Would I use anything other than an STM32F103 at this point? I can directly port SSCFOCC over to this controller, although it will need considerably work to get up to the commutation frequency required to drive high-speed outrunners (target: 1200Hz). This is the first motor controller I've done with an integrated STM32F103, not on its own separate logic board. Noise is by far my biggest worry. Every pin going toward the gate driver has a resistor in series with it and I do my best to keep the grounds separate, but I won't sleep as well as I do with optically-isolated gate drive and separate logic boards.



  • Inputs: Here is where this controller is much more capable than any of my previous ones. In order to accommodate as many possible applications as possible, I included every input I could think of. On the left side of the controller, there are three multi-purpose inputs that can be used for Hall effect sensors or A/B/Z encoder tracks or phase voltage sensing (on board) or as general purpose analog or digital I/O. On the top of the board are UART, I2C, analog, and PWM inputs for control. I2C and UART outputs can be used to send data back to the master controller. Oh, and I snuck on one more option:

    On-board XBee.
    The board can be programmed either with a standard FTDI adapter or no-touch over XBee. I was a little annoyed to find out the the FTDI adapters don't use RTS and DTR, the two useful signals for triggering the bootloader. They use CTS and DTR, and CTS can't really do anything. Why, Sparkfun, why? I guess it matches the FTDI cable. Why, FTDI, why? Anyway, this necessitates a boot mode button for wired programming. The XBee can handle DTR and RTS, so it can do completely wireless no-touch programming.
That's the design in a nutshell. As usual, I will post the schematic and build files once it's confirmed to be not DOA. It was a very complex routing job, but strangely cleaner/easier than 3ph v4.0. I think I was just on a roll from having designed two controllers in a row. I also learned a new EAGLE trick, which I call a bus rotation. Picture this scenario: you have four related signals (e.g. VCC, GND, TX, RX) and you want to change their order  for more convenient routing, specifically by shifting the sequence by one. You could do this with vias, but if you're right on top of something and can't spare the opposite layer space:

1206 resistor network to the rescue.
Of course, the goal will be to demonstrate SSCFOCC in a direct side-by-side comparison to a commercial square wave commutation, fixed-timing ESC. One nice thing about propellers (as opposed to scooters) is that they provide a very repeatable load that is (in the case of static thrust, as on a multirotor) only a function of RPM. So, I will consider the project a success if I can run the same motor and prop to the same RPM with less power input than a square-wave controller at optimal timing. Or maybe, to demonstrate the benefits of field-oriented control, run at several different RPMs in a reasonable operating range and show greater total efficiency.

There's a lot of work to be done on the way to that goal, though. So far, I haven't had much success with high-RPM field-oriented control. My RC car sort-of did it, but that was with Hall effect sensors and the rotor angle was still way off, so the efficiency sucked. I believe it's mostly a matter of filters and control, accounting for any sources of lag that the field-oriented control doesn't automatically take up. That, and pushing the control loop up to 32kHz, should be able to make it work. Fun.

For now, I can at least take a short break from EAGLE while I wait for the boards.

Monday, February 20, 2012

3ph v4.0

I've finally nailed down working Sensorless Sine-Commutated Field-Oriented Current Control (SSCFOCC) for Pneu Scooter, and I promise I will write up this (relatively) simple algorithm sometime soon before moving on to more complex closed-loop observers and other controls-y things that won't be of much practical advantage over this simple one, at least not for a while.

In the mean time, I've also finished the v4.0 design for my scooter-sized (~48V/40A) motor controller, with some tweaks to make it more optimized for SSCFOCC:


It's the same physical dimension as 3ph v3.1 (3.90"x1.55"), so it will be a drop-in replacement for the controller currently in Pneu Scooter. Other things that have not changed:
  • MOSFETs: This design still uses the GWM series miniature 3-phase full bridge modules from IXYS. Specifically, the GWM100-01X1, although it could also use the GWM160-0055X1 or the GWM200-004P3. They're hard to find, but I've stockpiled enough to survive until the end of the world.

  • Logic: Still using the STM32F103 on a Wootstick 2.0 because why would I change that?

  • Current Sensors: Two phase current and one DC current sensor using the ACS714 Hall-effect current sensors. They measure +/-30A, so in order to get to full operating current I can selectively bypass them with one or two 0.001Ω, 1% resistors each.
One thing that has changed is the current sensor layout. SSCFOCC relies on the current measurements to make an estimate of the rotor position, so cleaning up the current sensor signals as much as possible was one of my goals in this design. I know from experience that they pick up massive amounts of PWM noise. Better hardware and software filtering, as well as synchronous current sampling, have definitely helped. But it would be nice to tackle some of the noise at the source, with better layout around the current sensors:


It's a fact of life that the current sensors, particularly the phase current ones, need to be located directly adjacent to high dV/dt switching nodes. High dV/dt leads to capacitive coupling, and one way to protect sensitive traces from capacitive coupling is to shield them with ground planes. So, in an effort to minimize capacitively-coupled PWM noise on the current sensor signal wires, I did my best to shield the signal side of the ACS714's and the traces returning to the logic part of the board with ground. I don't know how much it will help, but it probably can't hurt.

The next big change is a return to optically-coupled gate drive. 3ph v1.x and v2.x, as well as most of my other motor controllers, have used optically-coupled gate drive. 3ph v3.0 and v3.1 used the IR21844 half-bridge drivers instead for compactness and low cost. But, this was before I realized that bootstrapped optically-coupled gate drive is possible and you don't need expensive high-side power supplies for everything. So with cost less of an issue, it just became a matter of stuffing six HCPL-3120 gate drive optocouplers onto the board. The half-bridge unit looks like this:


The input AHI is a 3.3V logic signal directly from the STM32F103. If AHI is high, the high-side optocoupler LED turns on. If AHI is low, the low-side optocoupler LED turns on. If AHI is high impedance, neither LED turns on and the half bridge is disabled. R69 and C54 form a low-pass filter that sets the shoot-through delay. Each gate gets a gate resistor, a pull-down resistor, and a 17V Zener diode. D2 is the bootstrap diode for the high-side driver.

The last big change is the addition of phase voltage sensing. To do this, I added a quad op-amp configured as a differential amplifier to measure Va, Vb, Vc, and the DC bus voltage with respect to power ground. One unit looks like this:


Differential measurement with respect to power ground (COM) should be more accurate when high currents push power ground and signal ground apart.

Phase voltage sensing opens up a number of interesting opportunities for 3ph v4.0. One is simple block-commutated sensorless, where one phase is left undriven (which I can do now, thanks to the tri-state-able optocoupled gate drive) and the back EMF is directly measured. I'm not sure why I would want to do this, other than for direct comparison to more advanced sensorless techniques with the hardware as a control.

Besides block commutation, measuring phase voltage may also be useful for rolling-start, which is something I do a lot on the scooter. Right now, I have to push against the resistance of the shorted motor until the current sensors pick up enough information to derive the rotor position. It finds itself at a very low speed, so this isn't a big deal. But, with phase voltage sensing, I could leave the phases off and use the back EMF measurement to do the same. The practical advantage is that you can freely kick up to any speed before applying power.

Another thing phase voltage sensing might be useful for is online or offline calibration, where the back EMF is measured and used to estimate the motor's torque constant or other parameters. At very least, it could be used as a single-purpose scope to make a plot of the motor's back EMF waveform, which is informative by itself.

All these extra features made the board a bit of a nightmare to route, with one of the highest component densities I've ever done:

Top.
Bottom.
I managed to cram the entire 15V and 5V power supply on the bottom layer, this time with ceramic capacitors. The six gate drive optocouplers barely fit on the top layer above the MOSFET. All the filters and logic are on the top layer under the STM32 board. There are also still inputs and filters for Hall effect sensors, even though I mostly plan to use this for sensorless control.

I'll sent these boards out right after the holiday weekend and as usual, post the schematics and other files when I confirm they work. Of course, the first sub-version of my boards are usually doomed to failure (3ph v2.0 and v3.0 didn't last very long, whereas v2.1 and v3.1 were great) so we'll see what happens.