Finally came round making my first power electronics project, and would like comments/feedback. As part of a 48V DC to 120V AC inverter I made a 2-phase boost converter to try things out with. It uses homemade litz-wound MPP-core (0055550A2 cores from Magnetics, mu=26).
Oooh, fancy!
The embedded STM32F303 opamps seemed to be absolute garbage with 10mV input offset, and weird artifacts when outputting near the GND rail. By the time they started outputting anything, the current is already at 1A. I manually twiddled the trimmers in the opamps to fix it, the internal calibration routines didn't make it any better. Did anyone have a similar issue? No matter what I do I am unable to reach datasheet performance, even with randomly twiddling the high and low trim values.
Easy, add a bias resistor from +3.3V to PH1/2_I_SENSE to bias it up off from GND.

Probably a good lesson to not rely on MCU internals too much, especially analog ones. They're often crap. It's a minor miracle that 12+ bit ADCs are even possible, let alone reasonable. Read the datasheet very, very carefully, then read the manual(s) and peripheral docs, then read the datasheet again, then read the errata.
Other things to watch out for -- poor POR (particularly on slowly rising supplies), poor VREF (ATMEGAs most notoriously), differential receivers with uselessly little CM range (even proper ADCs, the fast differential-input ones; FPGAs, and some MCUs, with LVDS or similar interfaces), etc. Most anything Microchip, analog and digital included (PIC, etc.; excepting Atmel, at least for now).
And not really a bug because it's well documented, but different from usual: ST's crystal oscillators tend to be quite weak, so need a higher impedance crystal, and smaller shunt capacitors, than most. I guess that's not relevant here as you aren't using it, but still something else to watch out for.
Because of the opamp's DC offsets, it was possible to lose regulation since at no-load condition, there was a minimum duty cycle below which the peak current mode control wouldn't go, outputting unlimited voltage (bye-bye Rigol e-load
). How is this fixed usually? Some sort of burst mode control? How would that look like in C code?
Again, offsetting the input will help, but also, you didn't have a hard voltage limit or anything?
This is kind of one of many reasons why I still haven't written a software/hybrid controller yet. I will eventually, but it definitely hasn't been necessary. There are too many complexities in the systems themselves, and too many edge cases in the software, to write one with a reasonable guarantee of operation. All it takes is a few flipped bits and it's off in la-la land and the output explodes or whatever.
A very good idea is to add logic gates between the MCU and gate drivers, so that a hardware disable function can be implemented. This should be driven by a fault latch, which is reset when a hardware failure signal fires, and only cleared by a suitable sequence of operations from software -- at that, an ongoing sequence, so it serves as a watchdog timer.
Typical hardware detection events would be: leaving an output on too long; letting a switch carry more than some maximum peak current; letting the input or output voltage rise too far (speaking of which, keep the input in mind when you move to synchronous mode operation -- it's a boost and buck at the same time!); maybe a hard thermal limit, external fault input signal, supply UVLO, etc. Lots of possibilities. The less software, and the less high-complexity hardware, involved in each, the better.
Ideally you'd have hardware that just runs everything by itself, and the MCU just tells it how much current or voltage to run at. You could drop in a pair of UC3842s and use them in this way -- strap the error amp as an inverting follower and set its current setpoint from a DAC. It runs the oscillator and switch by itself from hardware functionality alone. (UC3842 family exactly, isn't the easiest to synchronize with phase interleave, and takes a somewhat high CS voltage (1V nominal max, of course you can use the pull-up trick to ease it a bit, or preamp it), so this might not be a directly applicable example.)
I digress...

As for burst mode -- you need an accumulator to store state (in this case, probably the PI control's integrator). However it's done, there's some range of input values where the output (PWM compare register) does not change but remains fixed at some minimum value, or is disabled completely (set to zero or whatever).
The minimum pulse width vs. disabled condition might be by direct timing (the input value could be turned into a PWM signal generated at a fractional clock rate), or as part of a feedback loop (hysteretic control) in which case the feedback variable will realize the same function (namely, the control integrator will hunt). Or both (the fractional rate PWM could actually be a sigma-delta converter?).
if (pid_output >= PWM_MINIMUM) {
PWM_COMPARE = pid_output;
} else if (pid_output >= PWM_MINIMUM / 2) {
PWM_COMPARE = PWM_MINIMUM; // set to minimum pulse width
} else {
PWM_COMPARE = 0; // disable PWM channel
}
And also clamp to a PWM_MAXIMUM, so you don't accidentally, y'know, leave a switch latched on forever or something.

Maybe not strictly necessary for a peak current mode control -- the current simply rises until you switch it, and if it never hits a useful let alone dangerous current, who cares? -- but can be helpful to soften some edge cases.
Efficiency wise, it doesn't seem to be too bad for a first pass with some tweaks, but I want to get to 97% at least when going 48V->170V. The inductors' AC resistance at 100Khz is about 0.25Ohm at 100Khz reported by a Bode 100, and only ~40mOhm at DC. Is there a better way to wind them to get AC losses down? Currently it's 3 layers of Litz. Would synchronous rectification help here? (I'm moving to sync anyway because I need bidirectionality, really hope it helps).
Core datasheet:
https://www.mag-inc.com/Media/Magnetics/Datasheets/0055550A2.pdfWhat is that, 63 turns I count? So 111uH nominal, and 15A at -20% saturation, 25A at -50%.
And 48V 600W is 12.5A, but I don't know what minimum input voltage might be.
At 100kHz, CCM, 96V output, that's 125uVs peak flux change, or 30mT flux density. They give a figure of 0.8W/cc or 4.27W dissipation at 100mT and 100kHz; if this follows square law, then your dissipation should be around 0.5W, more at high duty cycle but maybe not much more than a watt.
125uVs / 111uH = 1.1A peak, or about 56 VAR; dissipating <1W means a Q of >56.
And X_L = 70 ohms so a Q of >56 implies ESR < 1.24 ohms.
0.25 ohm, albeit at a very small signal level I suppose, seems very fortuitous, and is in the right order of magnitude.
I wouldn't have bothered with Litz as the AC resistance doesn't matter much -- again, you're only doing 50 VA or so.
And yes, you can think of a switching circuit in RF or AC terms just fine -- I don't know that many authors use VARs as a working figure, but it can be defined just as well here as anywhere else. There are some sqrts missing because of the waveforms (current is triangular), or you can do it by harmonics (Fourier series of square and triangle waves of some duty cycle, Parseval's theorem), also ideally you'd check losses for each harmonic because the inductor itself isn't perfectly linear with frequency and amplitude, but also if it's nonlinear, how do those harmonics interact, arggh?!..., but anyway even if it's just a ballpark, it's the same shaped ballpark for every non-resonant SMPS so it's useful for comparison.
Are there any easy (Engineer-oriented, not research papers) to understand resources to design an optimized compensator for this kind of thing? I can easily understand peak current mode control, but the outer voltage loop design is a bit of a mystery. 2p2z, lag compensators, maybe I just need to convert a type 3 compensator to digital domain somehow?
The various types are still single order overall, so just consist of different coefficients of accumulating to a register with feedback, and differencing against previous samples (but not accumulator chains, or many previous samples). There are simple transforms between lumped equivalents (error amp compensators in s or F domain) and DSP expressions (Z domain).
So for example, at most two biquads and an integrator might be used (with one biquad, or simpler, being typical); though the coefficients for that form might be nontrivial to solve from a circuit, and a more closely equivalent form might be preferred.
I don't know if anyone really does DSP control this way, with traditional signal filtering rather than PID, but there is a lot of compatibility in their response so I don't see that being a problem. Signal filters are just on my mind as I recently implemented a thing. Whichever works.
It's hard or impossible to solve for compensator parameters without academic background; IIR filters especially as their polynomials lie within the unit circle, not just the left half plane. Polynomials are the problem space here, so it's at least not your fault that solutions are difficult to work with.

I mean, all filters can be represented by polynomials in some way, I think, given enough generality. The exception for FIR filters is more that they're actually pretty easy to understand as a convolution process, which maybe sounds scary until you've seen how it works.
Next steps are: slope compensation, it's wayyy too chaotic for my liking when it comes to the subharmonic oscillations, since this is always operating at ~75% duty cycle. Tests at full power (600W with both phases interleaved continuous, 1200W peak). Experiments with different inductor designs and other parts.
So, two things --
1. App notes always say 50% duty, because appnotes are almost always written by interns, or 2nd rate engineers ("those that can, do..."?). What they mean to say is CCM. Which in the usual simplified setup, is 50% duty, for a boost with Vout = 2 Vin, or flyback with Vin = Vout, or... Well yeah, doesn't matter what the exact duty is, that's stupid, what matters is its relation to Vout/Vin, or whatever x/(1-x) variation applies to the topology in question.
2. You're running way too low a ripple fraction for peak current mode anyway. 600W output for 56 VAR switching energy? 1.1A ripple for 12.5A input? Same thing, ~9% ripple fraction. Great for keeping inductor losses down -- hence the low VARs -- but PCM goes chaotic in CCM, and you can introduce slope compensation but it's really not putting you very far down, you can go to 50%, maybe 30% ripple fraction without the current limiting behavior getting too terrible. Beyond that, you should really consider using smaller inductors (which will have to be much higher Q, of course, among other things*), or average current mode or something like that.
*The input and output ripple go up accordingly. Boost output filter cap ripple is always at least 100% (i.e. 0 to Ipk), but it goes up noticeably with ripple fraction, while boost input ripple is simply inductor ripple. In other words, the VARs from the inductor are stirred through the supply. The AC voltage drops on the capacitors are supposed to be small, so the VARs they deliver are much lower, but their Qs are much lower too (electrolytics top out at maybe 5 or so) so they can get quite hot in the process. Just another way of saying, mind your ripple ratings, of course!
Average current mode is very easy to implement. Read the inductor current with an ADC. Doesn't have to be synchronized with the switching frequency, though if you can sample mid-cycle (to get the mean current, aliasing the AC ripple to zero), or 2*Fsw (so the AC ripple is measured just perfectly, and can be decimated to zero with a two-sample average), that's nice. Anyway, run an error amp on that, to control inductor current to the setpoint, then control the setpoint with a voltage error amp to regulate voltage. Done. Can't be simpler, just two cascaded loops. No comparators, no nonlinear switching, no latches, just a PWM oscillator. Easier to phase-interleave, I would suppose.
The hard part then is measuring inductor current. You can measure switch current, and infer inductor current during the off phase, but this breaks at low currents -- in DCM. (You also won't be able to sample exactly in the middle, for some sufficiently narrow pulse width. Or it'll all be transients, which have to be blanked, or at least filtered out.)
You can measure diode current and add it to switch current. Connect a current transformer in series with the diodes. CT secondary is wired-OR, using a diode, into a common burden resistor which can be a portion or whole of R19 and R20. Thus the diode current sense adds to the switch current sense. Downside, there's a transient gap where neither current is quite right (especially if the CT has shitty resonances in it), and it doesn't work at very low duty cycle (where the diode current is active for so long, the CT doesn't have time to reset its flux).
Or you can measure inductor current directly. If the supply doesn't need to be common ground, add a low side shunt resistor. If it is, you can use a high side current sense amp, or Hall effect sensor. I would prefer the latter, since it works to quite high supply voltages with no worries. HE sensors do tend to have poor bandwidth, which limits response time and means your filter network should have less bandwidth than it -- but that's quite fine as, with so much inductance, you have a loop bandwidth probably crossing over at Fsw/5 or less, and most sensors have 100kHz or more BW.
You might have to rewire your circuit to use ACM control, or if the STM32 has enough analog mux options maybe not even that. The current transformer method would be, eh, not terrible to hack in, otherwise the Hall effect sensor can be wired in wherever and R19/20 DNP'd to make the connections.
Finally, for the bridge, you may consider snubbing, perhaps a quasi-resonant rate snubber or something? It can be hard to use these, just in general, for one, but also when you don't have conveniently split supplies or whatever. They also tend to need a lot of components, so the sheer component body and lead lengths accumulate so much stray ESL that they aren't effective anymore. Not a slam dunk, just something to look into.
Tim