Maker Pro
Maker Pro

Software control of flyback power supply

J

Joel Kolstad

I was curious how one goes about implementing the feedback loop portion of
software that's controlling a flyback architecture switching power supply?
At startup, I'll have a large error voltage since the output is zero (read
in using an 8 bit ADC) and therefore even with moderate gains I'll crank my
PWM output to it's maximum duty cycle (65% in my case). However, when
lightly loaded, the output voltage will shoot _way_ beyond the desired
otuput voltage long before the control loop is run again to regulate things.
(My control loop runs at about 780Hz.)

I'm thinking that rather than doing something like:

DC=P*(Vo-Vref), where DC is the duty cycle of the PWM

....I need to do something more like:

DC=DC+I*(Vo-Vref)

Notice that the first case is the 'P' from 'PID' control whereas the second
case is an 'I only' controller.

Does this sound reasonable? Are there better methods?

Thanks,
---Joel Kolstad
 
J

John Larkin

I was curious how one goes about implementing the feedback loop portion of
software that's controlling a flyback architecture switching power supply?
At startup, I'll have a large error voltage since the output is zero (read
in using an 8 bit ADC) and therefore even with moderate gains I'll crank my
PWM output to it's maximum duty cycle (65% in my case). However, when
lightly loaded, the output voltage will shoot _way_ beyond the desired
otuput voltage long before the control loop is run again to regulate things.
(My control loop runs at about 780Hz.)

I'm thinking that rather than doing something like:

DC=P*(Vo-Vref), where DC is the duty cycle of the PWM

...I need to do something more like:

DC=DC+I*(Vo-Vref)

Notice that the first case is the 'P' from 'PID' control whereas the second
case is an 'I only' controller.

Does this sound reasonable? Are there better methods?

Thanks,
---Joel Kolstad

P+I is probably the best way to stabilize this loop. With an 8-bit ADC
and sundry switcher noise, derivative probably isn't in the game. Your
sample rate is low, so you'd better have a *big* output capacitor if
you hope to have tolerable line:load transient response. Capacitor ESR
will be important to loop stability, too, so buy cheap caps.

Can you digitize the unregulated input? If so, some feedforward tricks
can be done to improve regulation and especially ripple "outside the
loop".

Programmed soft-start is an easy tweak.

I did a bizarre regulator a while back: +200 volts => fet switch =>
huge power resistor => big capacitor bank, with software digitizing
the cap voltage and toggling the fet on and off. The fet gate was
driven through a dc/dc converter. Pics were posted to a.b.s.e. Not
very efficient, but very rugged.


John
 
J

Joel Kolstad

Thanks for the response, John. A couple of comments:

John Larkin said:
P+I is probably the best way to stabilize this loop.

I did take a look at how things should proceed under a 'no load' situation:
At my maximum duty cycle, I transfer 760uJ from the primary side to the
output side on each cycle. To get to the desired output voltage (200V), I
have a 33uF capacitor --> it'll end up with 660mJ in it. Dividing the two,
it'll take 868 switching cycles to fill up (this is all very approximate
neglecting losses, etc.). Cycle rate (operating frequency) is 50kHz. The
ADCs sample rate of ~780Hz gets me a sample every 64 switching cycles... not
so bad after all, eh? The question then becomes... what's a reasonable
starting value for P? (The PWM output is 8 bits as well, so its value
ranges from 0-65%*255=165) It would appear that there'll be a significant
steady-state error if I make it small enough (I'm thinking something like...
1-5!) such that I don't expect I'll be building something unstable. (I.e.,
if I make P=100, then a couple bits of noise on the ADC input is going to
run the PWM all the way from 0% output to 65% -- the maximum I designed
for).

But I can see now that making P=1 or 2 or so will help a lot in initially
getting the thing going (when the error is large).
With an 8-bit ADC
and sundry switcher noise, derivative probably isn't in the game. Your
sample rate is low, so you'd better have a *big* output capacitor if
you hope to have tolerable line:load transient response.

Although I expect the loads to behave non-linearly during startup, I don't
think there'll be many transients during operation.
Can you digitize the unregulated input?

Only with great pain. :)

Hmm... perhaps this is worth simulating in Matlab prior to coding it up and
inadvertently frying something! (Flybacks make me a little nervous... you
remove the load, and cross your fingers the feedback 'catches' the rising
voltage and drops the duty cycle before anything fries...)

---Joel
 
G

Genome

| Thanks for the response, John. A couple of comments:
|
| > P+I is probably the best way to stabilize this loop.
|
| I did take a look at how things should proceed under a 'no load'
| situation:At my maximum duty cycle, I transfer 760uJ from the
| primary side to the output side on each cycle.To get to the desired
| output voltage(200V),I have a 33uF capacitor --> it'll end up with
| 660mJ in it. Dividing the two,it'll take 868 switching cycles to
| fill up (this is all very approximate neglecting losses, etc.).
| Cycle rate (operating frequency) is 50kHz.
|
| The| ADCs sample rate of ~780Hz gets me a sample every 64 switching
| cycles... not so bad after all, eh? The question then becomes...
| what's a reasonable starting value for P? (The PWM output is 8
| bits as well, so its value ranges from 0-65%*255=165) It would
| appear that there'll be a significant steady-state error if I make
| it small enough (I'm thinking something like... 1-5!) such that I
| don't expect I'll be building something unstable.(I.e., if I make
| P=100, then a couple bits of noise on the ADC input is going
| to run the PWM all the way from 0% output to 65% -- the maximum I
| designed for).
|
| But I can see now that making P=1 or 2 or so will help a lot in
| initially| getting the thing going (when the error is large).
|
| > With an 8-bit ADC and sundry switcher noise, derivative probably
| > isn't in the game. Your sample rate is low, so you'd better have
| > a *big* output capacitor if you hope to have tolerable line:load
| > transient response.
|
| Although I expect the loads to behave non-linearly during startup, I
| don't think there'll be many transients during operation.
|
| > Can you digitize the unregulated input?
|
| Only with great pain. :)
|
| Hmm... perhaps this is worth simulating in Matlab prior to coding it
| up and inadvertently frying something! (Flybacks make me a little
| nervous...you remove the load, and cross your fingers the feedback
| 'catches' the rising voltage and drops the duty cycle before anything
| fries...)
|
| ---Joel
|
|

If you accepted an error amplifier then your processing becomes trivial.
You just A/D convert the EA output and throw that into your PWM. If you
gave more information about your power stage then I could throw a
suitable compensation scheme at you.

Basically..... what's your primary inductance and the input voltage. I
can reverse engineer the rest from that. I assume you are operating in
the discontinuous mode and your maximum output power is something like
38W. Thats 760uJ times 50KHz. In fact just the input voltage will do.

If you wanted to go the whole hog then I suppose it would be a simple
(?) matter of coding the error amplifier transfer function. However, as
I say, having an external one will seriously reduce the burden on your
procesor and you might realistically up your sampling rate.

I don't know much about PID controllers other than I think its software
johnny's smoke screen for avoiding proper analysis of feedback and
control systems. Sorry if that sounds a bit harsh.

If it isn't a simple case of modelling the transfer function in
software then I'd approach it something like this.

Watch out, non-programmers pseudo code in operation.

var
<
oldvolts last measured voltage}
newvolts latest measured voltage
diffvolts difference in voltage
errorvolts difference in output voltage from required value
oldcurrent last calculated required output current
newcurrent new calculated required output current
loadcurrent calculated load current
pricurrent required primary current
errorcurrent required current to adjust errorvolts in tcycles
diffcurrent difference between currents
duty required duty cycle for regulationconst
<
vin input voltage
lpri primary inductance
nratio transformer turns ratio
cout output capacitance
vout required output voltage
tcycles time between conversions
Fs switching frequencybegin
AtoD(newvolts) measure latest voltage
diffvolts=newvolts-oldvolts calculate change in voltage
oldvolts=newvolts store for next time
diffcurrent=diffvolts*cout/tcycles calculate load minus supply current
loadcurrent=diffcurrent-oldcurrent calculate load current
errorvolts=newvolts-vout calculate output error
errorcurrent=errorvolts*cout/tcycles calculate current to correct error
newcurrent=errorcurrent+loadcurrent calculate required output current
oldcurrent=newcurrent store for next time
pricurrent=newcurrent/nratio required average primary current
tonsq=0.5*pricurrent*Lpri/vin.Fs squared on time
ton=sqrt(tonsq) on time
duty=Fs.ton required duty cycle
PWM(duty)
end


And if that makes sense...... and hasn't been mangled then I'll be surprised. Call it a first cut.

DNA
 
T

Tim Wescott

Genome said:
"Joel Kolstad" <[email protected]
| Thanks for the response, John. A couple of comments:
|
| John Larkin <[email protected]
| > P+I is probably the best way to stabilize this loop.
|
| I did take a look at how things should proceed under a 'no load'
| situation:At my maximum duty cycle, I transfer 760uJ from the
| primary side to the output side on each cycle.To get to the desired
| output voltage(200V),I have a 33uF capacitor --> it'll end up with
| 660mJ in it. Dividing the two,it'll take 868 switching cycles to
| fill up (this is all very approximate neglecting losses, etc.).
| Cycle rate (operating frequency) is 50kHz.
|
| The| ADCs sample rate of ~780Hz gets me a sample every 64 switching
| cycles... not so bad after all, eh? The question then becomes...
| what's a reasonable starting value for P? (The PWM output is 8
| bits as well, so its value ranges from 0-65%*255=165) It would
| appear that there'll be a significant steady-state error if I make
| it small enough (I'm thinking something like... 1-5!) such that I
| don't expect I'll be building something unstable.(I.e., if I make
| P=100, then a couple bits of noise on the ADC input is going
| to run the PWM all the way from 0% output to 65% -- the maximum I
| designed for).
|
| But I can see now that making P=1 or 2 or so will help a lot in
| initially| getting the thing going (when the error is large).
|
| > With an 8-bit ADC and sundry switcher noise, derivative probably
| > isn't in the game. Your sample rate is low, so you'd better have
| > a *big* output capacitor if you hope to have tolerable line:load
| > transient response.
|
| Although I expect the loads to behave non-linearly during startup, I
| don't think there'll be many transients during operation.
|
| > Can you digitize the unregulated input?
|
| Only with great pain. :)
|
| Hmm... perhaps this is worth simulating in Matlab prior to coding it
| up and inadvertently frying something! (Flybacks make me a little
| nervous...you remove the load, and cross your fingers the feedback
| 'catches' the rising voltage and drops the duty cycle before anything
| fries...)
|
| ---Joel
|
|

If you accepted an error amplifier then your processing becomes trivial.
You just A/D convert the EA output and throw that into your PWM. If you
gave more information about your power stage then I could throw a
suitable compensation scheme at you.

Subtracting a pair of numbers is the least of his concerns. Putting the
whole compensator in analog and sampling it could be done, but is that
the point?
Basically..... what's your primary inductance and the input voltage. I
can reverse engineer the rest from that. I assume you are operating in
the discontinuous mode and your maximum output power is something like
38W. Thats 760uJ times 50KHz. In fact just the input voltage will do.

If you wanted to go the whole hog then I suppose it would be a simple
(?) matter of coding the error amplifier transfer function. However, as
I say, having an external one will seriously reduce the burden on your
procesor and you might realistically up your sampling rate.

Software controllers can be pretty compact and fast. Unless he's
running a 4004, of course. Using a uP with on-board ADC and PWM will
reduce board space, for sure.
I don't know much about PID controllers other than I think its software
johnny's smoke screen for avoiding proper analysis of feedback and
control systems. Sorry if that sounds a bit harsh.

PID control was around long before folks were using microprocessors, and
is what is used for most power supply compensators (or PI, or PD).
_Tuning_ a PID can either be done with smoke and mirrors, or with proper
analysis. See my website for a "software johnny's smokescreen" PID
article along with a serious article on using the z-transform to do
frequency-domain design. The "PID Without a PhD" is one I recommend for
non-critical tasks that can be dinked with safely, but I think you're
better off doing actual analysis in this case.
If it isn't a simple case of modelling the transfer function in
software then I'd approach it something like this.

Watch out, non-programmers pseudo code in operation.

var
<
oldvolts last measured voltage}
newvolts latest measured voltage
diffvolts difference in voltage
errorvolts difference in output voltage from required value
oldcurrent last calculated required output current
newcurrent new calculated required output current
loadcurrent calculated load current
pricurrent required primary current
errorcurrent required current to adjust errorvolts in tcycles
diffcurrent difference between currents
duty required duty cycle for regulation
const
<
vin input voltage
lpri primary inductance
nratio transformer turns ratio
cout output capacitance
vout required output voltage
tcycles time between conversions
Fs switching frequency
begin
AtoD(newvolts) measure latest voltage
diffvolts=newvolts-oldvolts calculate change in voltage
oldvolts=newvolts store for next time
diffcurrent=diffvolts*cout/tcycles calculate load minus supply current
loadcurrent=diffcurrent-oldcurrent calculate load current
errorvolts=newvolts-vout calculate output error
errorcurrent=errorvolts*cout/tcycles calculate current to correct error
newcurrent=errorcurrent+loadcurrent calculate required output current
oldcurrent=newcurrent store for next time
pricurrent=newcurrent/nratio required average primary current
tonsq=0.5*pricurrent*Lpri/vin.Fs squared on time
ton=sqrt(tonsq) on time
duty=Fs.ton required duty cycle
PWM(duty)
end


And if that makes sense...... and hasn't been mangled then I'll be
surprised. Call it a first cut.

DNA

As written (and if I'm not mistaken) this is a differential-only
controller. To get zero DC error you need a PI or PID controller overall.

z - 1
diffvolts(z) = newvolts(z) -------
z

diffcurrent(z) = (cout/tcycles) diffvolts(z)

errorcurrent(z) = (cout/tcycles)(newvolts(z) - vout(z))

z - 1
newcurrent(z) = (errorcurrent(z) + diffcurrent(z)) -------
z

I'm not sure what you were aiming for, but "PID Without a PhD" has code
for a PID controller (general-purpose, so if you used it the meaning of
the signals would get obfuscated). If you're using a very small
processor without a multiplier remember that you can get within 6dB of
your desired gain with simple shifting, and within 3.5 with shifting and
a single add.
 
T

Tim Wescott

Joel said:
Thanks for the response, John. A couple of comments:




I did take a look at how things should proceed under a 'no load' situation:
At my maximum duty cycle, I transfer 760uJ from the primary side to the
output side on each cycle. To get to the desired output voltage (200V), I
have a 33uF capacitor --> it'll end up with 660mJ in it. Dividing the two,
it'll take 868 switching cycles to fill up (this is all very approximate
neglecting losses, etc.). Cycle rate (operating frequency) is 50kHz. The
ADCs sample rate of ~780Hz gets me a sample every 64 switching cycles... not
so bad after all, eh? The question then becomes... what's a reasonable
starting value for P? (The PWM output is 8 bits as well, so its value
ranges from 0-65%*255=165) It would appear that there'll be a significant
steady-state error if I make it small enough (I'm thinking something like...
1-5!) such that I don't expect I'll be building something unstable. (I.e.,
if I make P=100, then a couple bits of noise on the ADC input is going to
run the PWM all the way from 0% output to 65% -- the maximum I designed
for).
-- snip --

This is why you want a PI controller; the integral term gives you zero
DC error which lets you keep the proportional term low enough for good
stability. See my website for some relevant articles.
 
T

Tim Wescott

Genome wrote:

-- snip --
var
<
oldvolts last measured voltage}
newvolts latest measured voltage
diffvolts difference in voltage
errorvolts difference in output voltage from required value
oldcurrent last calculated required output current
newcurrent new calculated required output current
loadcurrent calculated load current
pricurrent required primary current
errorcurrent required current to adjust errorvolts in tcycles
diffcurrent difference between currents
duty required duty cycle for regulation
const
<
vin input voltage
lpri primary inductance
nratio transformer turns ratio
cout output capacitance
vout required output voltage
tcycles time between conversions
Fs switching frequency
begin
AtoD(newvolts) measure latest voltage
diffvolts=newvolts-oldvolts calculate change in voltage
oldvolts=newvolts store for next time
diffcurrent=diffvolts*cout/tcycles calculate load minus supply current
loadcurrent=diffcurrent-oldcurrent calculate load current
errorvolts=newvolts-vout calculate output error
errorcurrent=errorvolts*cout/tcycles calculate current to correct error
newcurrent=errorcurrent+loadcurrent calculate required output current
oldcurrent=newcurrent store for next time
pricurrent=newcurrent/nratio required average primary current
tonsq=0.5*pricurrent*Lpri/vin.Fs squared on time
ton=sqrt(tonsq) on time
duty=Fs.ton required duty cycle
PWM(duty)
end


And if that makes sense...... and hasn't been mangled then I'll be
surprised. Call it a first cut.

DNA

Simply because I'm too lazy to do the math myself -- why the square root?
 
J

Joel Kolstad

Thanks for all the help, Genome and Tim. I'll be gone this weekend but will
be able to get back to implementing this next week.

To answer your questions...

Genome said:
If you accepted an error amplifier then your processing becomes trivial.
You just A/D convert the EA output and throw that into your PWM.

To reduce parts count, I'm using the ADC on-board the microcontroller and
using a 'digital' set point.
If you
gave more information about your power stage then I could throw a
suitable compensation scheme at you.

Sure... it's designed as a 25W supply with a 12V 'nominal' input voltage,
10V 'worst case' input (i.e., it's 25W with 0V input voltage, but 38W if
you really do have 12V around). The primary inductance is ~15.2uH, maximum
current is in the ballpark of 8-10A (depending on worst case/nominal case
input voltage). Output is then supposed to be 200V. The turns ratio of
~7.5:1 (sec:pri) gets me a maximum 'on' duty cycle of ~65%.

(After doing this design, I see why so many manufacturers are tempted to
rate their 12V input power supplies as having rated power output only down
to, say, 11.5V... pretty big drop there from 12V->10V!)
I don't know much about PID controllers other than I think its software
johnny's smoke screen for avoiding proper analysis of feedback and
control systems. Sorry if that sounds a bit harsh.

I understand & generally agree with the sentiment, but when you're building
a 'general purpose' power supply, how can you avoid some amount of
'approximation' (as opposed to rigorous analysis) when you can't reliably
predict exactly what the load (and hence the transfer function) is going to
be? Seems to me this is why PID is used so often -- it tends to behave
'reasonably' under most circumstance, even though I imagine you or other
posters could cite examples where, e.g., a power supply went unstable and
caught fire due to someone giving it a load the designers never anticipated.
Watch out, non-programmers pseudo code in operation.

Thanks, I'll study this on Tuesday!

---Joel
 
G

Genome

| Genome wrote:

[Snip]

| >
| > If you accepted an error amplifier then your processing becomes
trivial.
| > You just A/D convert the EA output and throw that into your PWM. If
you
| > gave more information about your power stage then I could throw a
| > suitable compensation scheme at you.
|
| Subtracting a pair of numbers is the least of his concerns. Putting
the
| whole compensator in analog and sampling it could be done, but is that
| the point?

Not necessarily but you end up with a wider bandwidth more robust system
which,
for me, becomes trivial

| >
| > Basically..... what's your primary inductance and the input voltage.
I
| > can reverse engineer the rest from that. I assume you are operating
in
| > the discontinuous mode and your maximum output power is something
like
| > 38W. Thats 760uJ times 50KHz. In fact just the input voltage will
do.
| >
| > If you wanted to go the whole hog then I suppose it would be a
simple
| > (?) matter of coding the error amplifier transfer function. However,
as
| > I say, having an external one will seriously reduce the burden on
your
| > procesor and you might realistically up your sampling rate.
|
| Software controllers can be pretty compact and fast. Unless he's
| running a 4004, of course. Using a uP with on-board ADC and PWM will
| reduce board space, for sure.

A sample rate of 780Hz isn't fast. The overhead would at most be a
couple of
resistors and capacitors with a SOT23/5 op-amp.

| >
| > I don't know much about PID controllers other than I think its
software
| > johnny's smoke screen for avoiding proper analysis of feedback and
| > control systems. Sorry if that sounds a bit harsh.
|
| PID control was around long before folks were using microprocessors,
and
| is what is used for most power supply compensators (or PI, or PD).
| _Tuning_ a PID can either be done with smoke and mirrors, or with
proper
| analysis. See my website for a "software johnny's smokescreen" PID
| article along with a serious article on using the z-transform to do
| frequency-domain design. The "PID Without a PhD" is one I recommend
for
| non-critical tasks that can be dinked with safely, but I think you're
| better off doing actual analysis in this case.

Granted..... my math is non too brilliant.

| >
| > If it isn't a simple case of modelling the transfer function in
| > software then I'd approach it something like this.
| >
| > Watch out, non-programmers pseudo code in operation.
| >

[Snipped Pseudo Code]

| > And if that makes sense...... and hasn't been mangled then I'll be
| > surprised. Call it a first cut.
| >
| > DNA
| >
| >
|
| As written (and if I'm not mistaken) this is a differential-only
| controller. To get zero DC error you need a PI or PID controller
overall.
|

Perhaps in words.

Calculate the load current based on the previously set supply current
and
change in voltage output from last time to this time.

Calculate the required current to recharge the capacitor to the setpoint
value.

Add these two values.

Calculate the required on time to achieve this total current.

Adjust the duty cycle accordingly.



Note that there are two values being accounted for. Perhaps the PI is
hidden in
there somewhere after all.

| z - 1
| diffvolts(z) = newvolts(z) -------
| z
|
| diffcurrent(z) = (cout/tcycles) diffvolts(z)
|
| errorcurrent(z) = (cout/tcycles)(newvolts(z) - vout(z))
|
| z - 1
| newcurrent(z) = (errorcurrent(z) + diffcurrent(z)) -------
| z
|
| I'm not sure what you were aiming for, but "PID Without a PhD" has
code
| for a PID controller (general-purpose, so if you used it the meaning
of
| the signals would get obfuscated). If you're using a very small
| processor without a multiplier remember that you can get within 6dB of
| your desired gain with simple shifting, and within 3.5 with shifting
and
| a single add.
|
| --
|
| Tim Wescott
| Wescott Design Services
| http://www.wescottdesign.com
 
G

Genome

| Genome wrote:
|
| -- snip --

[bigger snip]
| > pricurrent=newcurrent/nratio required average primary current
| > tonsq=0.5*pricurrent*Lpri/vin.Fs squared on time
| > ton=sqrt(tonsq) on time
| > duty=Fs.ton required duty cycle
| > PWM(duty)
| > end
| >
| >
| > And if that makes sense...... and hasn't been mangled then I'll be
| > surprised. Call it a first cut.
| >
| > DNA
| >
| >
|
| Simply because I'm too lazy to do the math myself -- why the square root?
|

I've probably been too lazy to check my maths.........

Try it this way.

Ipri = Fs.Qpri
Qpri = Ipk.Ton/2
Ipk = Vin.Ton/Lpri

Ipri = Fs.Vin.Ton^2/2Lpri

Ton^2 = 2Lpri.Ipri/Vin.Fs
Ton = SQRT(2Lpri.Ipri/Vin.Fs)

and so on...... so the sum was wrong but the square/square root term is still in there.


DNA

| --
|
| Tim Wescott
| Wescott Design Services
| http://www.wescottdesign.com
 
T

Tim Wescott

Genome said:
| Genome wrote:

[Snip]
-- snip even more --
| Software controllers can be pretty compact and fast. Unless he's
| running a 4004, of course. Using a uP with on-board ADC and PWM will
| reduce board space, for sure.

A sample rate of 780Hz isn't fast. The overhead would at most be a
couple of
resistors and capacitors with a SOT23/5 op-amp.

For a power supply 780Hz may not be fast. The microprocessor will
probably beg to differ. A PID controller can be coded to run in a
relatively few number of clock cycles, so as long as the OP uses the
microprocessor to generate the PWM he won't be able to jack it up much,
even if he does the compensation with analog components.

Certainly with that sample rate he can't go much above a 100Hz
closed-loop bandwidth, but if it's enough to work and he's pinching
pennies (or board space) I don't see why it wouldn't work.

-- snip again --
Perhaps in words.

Calculate the load current based on the previously set supply current
and
change in voltage output from last time to this time.

Calculate the required current to recharge the capacitor to the setpoint
value.

Add these two values.

Calculate the required on time to achieve this total current.

Adjust the duty cycle accordingly.



Note that there are two values being accounted for. Perhaps the PI is
hidden in
there somewhere after all.
-- and again --

I reverse engineered the pseudo code into a block diagram and I didn't
see it, for what that's worth.
 
T

Tim Wescott

Terry said:
-- snip --

Hi Joel,

most smps error amplifiers are really PI controllers - opamp feedback
impedance Zf is usually a cap in parallel with RC. Some smps have a
cap across the upper resistor in the voltage divider - this adds
derivative action, giving a PID controller.

when designing an error amplifier, most people simply decide on the
closed loop bandwidth & phase+gain margins, then calculate the R's
and C's directly. They could, however, reformulate their equations in
terms of Kp, Ki (and Kd), solve for these controller gains, then
calculate R's and C's from the Kp, Ki expressions.

Or use the Kp, Ki and Kd for their sampled-time controller...
conversely IME, many control engineers (motor control in particular)
dont design anything, they just fiddle with Kp, Ki and Kd until the
response looks OK. Their PID controllers tend to have nice user
interfaces, buttons, LCDs etc, so changing gains is trivial and does
not need soldering irons.....but the better engineers design their
controllers too (when the plant is known).

You can get a not-too-bad controller that way -- but you _cannot_ get
the best one, and you _can_ lead yourself down the garden path to a
controller that's only stable at one temperature with one instance of
your plant. You need to exercise a great deal of restraint when tuning
if you're just twiddling the gain knobs.
thats interesting: WHEN THE PLANT IS KNOWN. The "plant" is the smps
power stage transfer function, which is known. the load is indeed
unknown. IMO one of the best books on control systems is "control of
electric drives" W. Leonhard, Springer-Verlag - its all real control
loops, not mathematically "nice" examples.

And if the plant isn't known analytically you can measure it's frequency
response directly and do it all with Bode plot design.

For your case with an unknown load you can try to design the system so
it has no negative resistive component at any frequency. This will be
very tricky with a sampled-time system; you may just want to analyze it
with a number of different load resistors & make sure that it's stable
for all of them.
The advantages of PI(D) vs P control are all about steady-state and
dynamic behaviour. It is easy to show that a controller with
proportional only control has a finite, non-zero steady state error.
This is because the driving signal is just Kp*e where e is the error
signal, Eref-Eactual. For non-zero output, e must be non-zero, ie a
steady state error must exist. As Kp increases, this error gets
smaller, but non-zero. Your error analysis of Kp was great though -
as Kp gets higher, the steady-state error decreases, but the
controller becomes more susceptible to noise. Not only that, but
enough Kp can make the system oscillate - in other words,
over-correct one way, then the other, and so on....the classic
closed-loop oscillation.

you can improve the proportional controller by adding in feedforward
- calculate the steady-state duty cycle based in Vin, and add it to
the output of your P controller (actually this will improve all of
your controllers).

Hear hear.
A PI controller can be shown to have zero error in steady-state. If
the reference changes as a ramp (as opposed to the step it used to
be) a PI controller will follow the ramp with a steady-state error
(control people call this the static velocity error constant, Kve).
PID controllers can follow a ramp with zero error.

Likewise if the reference changes as a parabolic ramp (integral of
ramp, which is integral of step) a PID controller will follow it with
a steady-state error. higher-order controllers can of course follow
this with zero error.

Only if the plant is integrating (i.e. has an internal integrator). A
type-1 loop (one integrator in the forward path) will have zero position
error but a finite velocity error. If your plant is integrating a PID
controller will give you a type-2 look (one integrator in the plant, one
in the controller), which will give you zero velocity error.
In a smps, your reference doesnt change much, so PI control is
usually sufficient, and gives zero error in steady-state.


Because you have a sampled-data controller, the actual closed-loop
bandwidth you can obtain is quite a bit lower than your sample rate.
A mate of mine and I did an interesting experiment a few years ago.
Using a frequency response analyser, we measured the response of an
RC filter (1k, 1uF, Tau=1ms, Fo=159.15Hz), a 1st-order IIR filter
Fs=4kHz using backward difference transform, and the same filter
using a bilinear transform, with and without frequency warping.

The resultant plots are very interesting - I will put it on s.e.d.
The bilinear-transform IIR filter didnt change when frequency warping
was added, as expected given Fs=4kHz, Fo=159Hz. The BLT IIR and RC
gains were identical up to 500Hz, within 2dB at 1kHz, with BLT
droppping to 18dB below RC at 2kHz, as expected (Nyquist frequency).

The BD IIR gain was off by about 1dB at 159Hz (measured Fo=184.3Hz),
2dB above RC at 500Hz, 3dB above RC at 1kHz and 5dB above RC at 2kHz.


Phase, however, is where it got real interesting - BLT IIR was 1
degree more than RC at 500Hz, 2 degrees at 1kHz, and about 5 degrees
at 1900Hz - it shot to hell at 2kHz. Clearly a BLT IIR filter adds
bugger all phase shift right up to nyquist, at which point it turns
to crap.

The BD IIR filter was another story entirely! about 10 degrees LESS
phase shift than RC at 159Hz, 20 degrees less at 400Hz, and it then
started going the wrong way - 44 degrees less phase shift at 1kHz,
about 80 degrees at near 2kHz. This backward-difference transformed
filter is absolute rubbish above about Fs/10, and even then gets
phase wrong by 20 degrees or so.

the difference between a BD IIR and a BLT IIR is a single addition.
no prizes for guessing which approach we used.


Also, dont forget to put an antialiasing filter in your ADC signal
path. Make sure "nothing" comes in above Fs/2, like say switching
noise. Also, if you can, synchronise your ADC sampling with the
centre of your pwm output (easy to do with count-up-count-down ie
symmetric PWM), as that will be as far away as possible from the
switching edges, which are what generates all the noise.

The OP is trying to build something with a minimum of parts. An
anti-aliasing filter would be larger than the linear compensator he's
trying to replace. I'd recommend that you don't forget the aliasing
phenomenon and make sure that there isn't noise at your ADC that will
alias down to DC, and be happy if there isn't. You _will_ see some
offset from your switching frequency being synchronized to your
sampling, but I doubt that'll be a big deal (check).
No reason why your smps closed-loop bandwidth has to be very good - I
worked with a design once that had a 1Hz bandwidth - a moving-coil
meter would show the transient response! As long as it does your
job.....

BTW, go look at what happens to your flyback converter when your
first turn it ON. switch turns on at max. D, charging L up to Ipk (or
thereabouts), dIprim/dt = Vprim/Lprim. During flyback, energy dumps
into UNCHARGED output capacitor Cout through diode D. dIsec/dt =
Vsec/Lsec = (Vout+Vd)/Lsec BUT Vout = 0 so dI/dt is MUCH less than
you expected. Therefore only a small amount of energy gets dumped in
Cout, the rest stays in Lsec (low dIsec/dt means it doesnt discharge
very rapidly). When your switch NEXT turns on, Ip starts off at close
to Ipeak, NOT zero. Eventually Cout charges to Vout, and dIp/dt =
dIs/dt (or thereabouts)

If you do not have a dedicated peak current trip, and instead have a
fixed duty cycle, you WILL blow up your smps - Iprim just keeps
ramping up and up. Sure, each time Vout rises a bit more so dIsec/dt
gets a bit bigger, but it often takes 10-15ms for a flyback to start
up properly, ie a few thousand cycles. Lprim will saturate WAY before
then, probably about the 2nd pulse. This is one of the reasons
soft-start circuits are used. In your micro, slowly ramp D up at
turn-on. It would also be a good idea to incorporate a peak primary
current limit - say a flip-flop + comparator, or maybe your micro can
do that itself somehow.

If you can monitor current that's a good thing. You ought to be able to
calculate the current that you'll generate and limit it in software --
but a sensor would be better.
 
T

Terry Given

Joel Kolstad said:
Thanks for all the help, Genome and Tim. I'll be gone this weekend but will
be able to get back to implementing this next week.

To answer your questions...



To reduce parts count, I'm using the ADC on-board the microcontroller and
using a 'digital' set point.


Sure... it's designed as a 25W supply with a 12V 'nominal' input voltage,
10V 'worst case' input (i.e., it's 25W with 0V input voltage, but 38W if
you really do have 12V around). The primary inductance is ~15.2uH, maximum
current is in the ballpark of 8-10A (depending on worst case/nominal case
input voltage). Output is then supposed to be 200V. The turns ratio of
~7.5:1 (sec:pri) gets me a maximum 'on' duty cycle of ~65%.

(After doing this design, I see why so many manufacturers are tempted to
rate their 12V input power supplies as having rated power output only down
to, say, 11.5V... pretty big drop there from 12V->10V!)


I understand & generally agree with the sentiment, but when you're building
a 'general purpose' power supply, how can you avoid some amount of
'approximation' (as opposed to rigorous analysis) when you can't reliably
predict exactly what the load (and hence the transfer function) is going to
be? Seems to me this is why PID is used so often -- it tends to behave
'reasonably' under most circumstance, even though I imagine you or other
posters could cite examples where, e.g., a power supply went unstable and
caught fire due to someone giving it a load the designers never anticipated.

Thanks, I'll study this on Tuesday!

---Joel

Hi Joel,

most smps error amplifiers are really PI controllers - opamp feedback
impedance Zf is usually a cap in parallel with RC. Some smps have a cap
across the upper resistor in the voltage divider - this adds derivative
action, giving a PID controller.

when designing an error amplifier, most people simply decide on the closed
loop bandwidth & phase+gain margins, then calculate the R's and C's
directly. They could, however, reformulate their equations in terms of Kp,
Ki (and Kd), solve for these controller gains, then calculate R's and C's
from the Kp, Ki expressions.

conversely IME, many control engineers (motor control in particular) dont
design anything, they just fiddle with Kp, Ki and Kd until the response
looks OK. Their PID controllers tend to have nice user interfaces, buttons,
LCDs etc, so changing gains is trivial and does not need soldering
irons.....but the better engineers design their controllers too (when the
plant is known).

thats interesting: WHEN THE PLANT IS KNOWN. The "plant" is the smps power
stage transfer function, which is known. the load is indeed unknown. IMO one
of the best books on control systems is "control of electric drives" W.
Leonhard, Springer-Verlag - its all real control loops, not mathematically
"nice" examples.


The advantages of PI(D) vs P control are all about steady-state and dynamic
behaviour. It is easy to show that a controller with proportional only
control has a finite, non-zero steady state error. This is because the
driving signal is just Kp*e where e is the error signal, Eref-Eactual. For
non-zero output, e must be non-zero, ie a steady state error must exist. As
Kp increases, this error gets smaller, but non-zero. Your error analysis of
Kp was great though - as Kp gets higher, the steady-state error decreases,
but the controller becomes more susceptible to noise. Not only that, but
enough Kp can make the system oscillate - in other words, over-correct one
way, then the other, and so on....the classic closed-loop oscillation.

you can improve the proportional controller by adding in feedforward -
calculate the steady-state duty cycle based in Vin, and add it to the output
of your P controller (actually this will improve all of your controllers).


A PI controller can be shown to have zero error in steady-state. If the
reference changes as a ramp (as opposed to the step it used to be) a PI
controller will follow the ramp with a steady-state error (control people
call this the static velocity error constant, Kve). PID controllers can
follow a ramp with zero error.

Likewise if the reference changes as a parabolic ramp (integral of ramp,
which is integral of step) a PID controller will follow it with a
steady-state error. higher-order controllers can of course follow this with
zero error.

In a smps, your reference doesnt change much, so PI control is usually
sufficient, and gives zero error in steady-state.


Because you have a sampled-data controller, the actual closed-loop bandwidth
you can obtain is quite a bit lower than your sample rate. A mate of mine
and I did an interesting experiment a few years ago. Using a frequency
response analyser, we measured the response of an RC filter (1k, 1uF,
Tau=1ms, Fo=159.15Hz), a 1st-order IIR filter Fs=4kHz using backward
difference transform, and the same filter using a bilinear transform, with
and without frequency warping.

The resultant plots are very interesting - I will put it on s.e.d. The
bilinear-transform IIR filter didnt change when frequency warping was added,
as expected given Fs=4kHz, Fo=159Hz. The BLT IIR and RC gains were identical
up to 500Hz, within 2dB at 1kHz, with BLT droppping to 18dB below RC at
2kHz, as expected (Nyquist frequency).

The BD IIR gain was off by about 1dB at 159Hz (measured Fo=184.3Hz), 2dB
above RC at 500Hz, 3dB above RC at 1kHz and 5dB above RC at 2kHz.

Phase, however, is where it got real interesting - BLT IIR was 1 degree more
than RC at 500Hz, 2 degrees at 1kHz, and about 5 degrees at 1900Hz - it shot
to hell at 2kHz. Clearly a BLT IIR filter adds bugger all phase shift right
up to nyquist, at which point it turns to crap.

The BD IIR filter was another story entirely! about 10 degrees LESS phase
shift than RC at 159Hz, 20 degrees less at 400Hz, and it then started going
the wrong way - 44 degrees less phase shift at 1kHz, about 80 degrees at
near 2kHz. This backward-difference transformed filter is absolute rubbish
above about Fs/10, and even then gets phase wrong by 20 degrees or so.

the difference between a BD IIR and a BLT IIR is a single addition. no
prizes for guessing which approach we used.


Also, dont forget to put an antialiasing filter in your ADC signal path.
Make sure "nothing" comes in above Fs/2, like say switching noise. Also, if
you can, synchronise your ADC sampling with the centre of your pwm output
(easy to do with count-up-count-down ie symmetric PWM), as that will be as
far away as possible from the switching edges, which are what generates all
the noise.


No reason why your smps closed-loop bandwidth has to be very good - I worked
with a design once that had a 1Hz bandwidth - a moving-coil meter would show
the transient response! As long as it does your job.....

BTW, go look at what happens to your flyback converter when your first turn
it ON. switch turns on at max. D, charging L up to Ipk (or thereabouts),
dIprim/dt = Vprim/Lprim. During flyback, energy dumps into UNCHARGED output
capacitor Cout through diode D. dIsec/dt = Vsec/Lsec = (Vout+Vd)/Lsec BUT
Vout = 0 so dI/dt is MUCH less than you expected. Therefore only a small
amount of energy gets dumped in Cout, the rest stays in Lsec (low dIsec/dt
means it doesnt discharge very rapidly). When your switch NEXT turns on, Ip
starts off at close to Ipeak, NOT zero. Eventually Cout charges to Vout, and
dIp/dt = dIs/dt (or thereabouts)

If you do not have a dedicated peak current trip, and instead have a fixed
duty cycle, you WILL blow up your smps - Iprim just keeps ramping up and up.
Sure, each time Vout rises a bit more so dIsec/dt gets a bit bigger, but it
often takes 10-15ms for a flyback to start up properly, ie a few thousand
cycles. Lprim will saturate WAY before then, probably about the 2nd pulse.
This is one of the reasons soft-start circuits are used. In your micro,
slowly ramp D up at turn-on. It would also be a good idea to incorporate a
peak primary current limit - say a flip-flop + comparator, or maybe your
micro can do that itself somehow.



cheers
Terry
 
G

Genome

| Does this sound reasonable? Are there better methods?
|
| Thanks,
| ---Joel Kolstad
|
|

I'd still recommend that you go for a proper control IC. I think Terry Given has mentioned the problem with current limiting and the fact that you have to add some more bits and pieces to sort that out.

I've reverted to html so that things line up, is there another way of doing it?

Anyway.....

One thing you'll need to know is what your power circuit gain is. I believe this is referred to as 'The Plant'.

Here we go 2 3 5.

Average secondary output current, Isave discontinuous operation, is secondary charge per pulse, Qsec, multiplied by operating frequency, Fs

Stuff it, here's a list of my variables/constants.

Isave Average secondary current
Qsec Secondary charge per cycle
Ipks Peak secondary current
Ipkp Peak primary current
Fs Switching frequency
N Turns ratio.... NP/NS
Toff The off time
Ton The on time
Vvea The error amplifier output
Vs The ramp amplitude, if you used an external amplifier the
equivalent would be your A/D reference span. (5V ?)
Lpri Primary inductance

Isave = Fs.Qsec
Qsec = Ipks.Toff/2
Ipks = N.Ipkp
Toff = VIN.Ton/N.VOUT
Ton = Vvea/Fs.Vs
Ipkp = VIN.Ton/Lpri

Taking a deep breath and combining all of that.

Qsec = N.Ipkp.Toff/2
= N.VIN.Ton.Toff/2Lpri
= N.VIN.Vvea.Toff/2Lpri.Fs.Vs
= N.VIN.Vvea.VIN.Ton/2Lpri.Fs.Vs.N.VOUT
= VIN^2.Vvea.Ton/2Lpri.Fs.Vs.VOUT
= VIN^2.Vvea.Vvea/2Lpri.Fs.Vs.VOUT.Fs.Vs
= VIN^2.Vvea^2/2Lpri.Vout.Fs^2.Vs^2

Isave = Fs.VIN^2.Vvea^2/2Lpri.Vout.Fs^2.Vs^2
= VIN^2.Vvea^2/2Lpri.Vout.Fs.Vs^2

Differentiate it with respect to Vvea for the control to output response.

dIsave/dVvea = VIN^2.Vvea/Lpri.VOUT.Fs.Vs^2

Which is your power circuit gain. It's zero order and all things are basically constant apart from the Vvea term. If you assume 100% efficieny then the output power is equal to the input power, POUT=PIN. You need to find a value for Vvea for a range of output powers, maybe.

Input power is energy per cycle multiplied by the switching frequency.

PIN = Fs.Ipkp^2.Lpri/2

Ipkp = VIN.Ton/Lpri
Ton = Vvea/Fs.Vs

Ipkp = VIN.Vvea/Lpri.Fs.Vs

PIN = Fs.(VIN.Vvea/Lpri.Fs.Vs)^2.Lpri/2
= (VIN.Vvea/Vs)^2/2Lpri.Fs

Rearranging and making Vvea the subject....

Vvea = SQRT(2PIN.Lpri.Fs.Vs^2/VIN^2)

Using

PIN = 25W also equal to POUT
Lpri = 15uH
Fs = 50KHz
Vs = 5V
VIN = 12V

Gives

Vvea = 2.55V

Putting that back into the power circuit gain gives

dIsave/dVvea = VIN^2.Vvea/Lpri.VOUT.Fs.Vs^2
= 0.1 A/V

Assuming your 33uF capacitor is ideal, no ESR, then you have a 0.1A/V zero order source driving it. The overall system becomes first order with crossover occuring at...

482Hz.... bugger it this is hard work.

DNA
 
Top