@@ -575,9 +575,6 @@ def __init__(self, input_voltage: RangeLike, output_voltage: RangeLike, frequenc
575575 self .inductor_current_ripple , self .current_limits , self .efficiency ,
576576 self .input_voltage_ripple , self .output_voltage_ripple )
577577
578- # TODO, this is a hack and should be replaced by the actual peak current
579- self .inductor_spec_peak_current = self .Parameter (FloatExpr ())
580-
581578 self .actual_buck_dutycycle = self .Parameter (RangeExpr ()) # possible actual duty cycle in buck mode
582579 self .actual_boost_dutycycle = self .Parameter (RangeExpr ()) # possible actual duty cycle in boost mode
583580 self .actual_inductor_current_ripple = self .Parameter (RangeExpr ())
@@ -596,76 +593,44 @@ def contents(self):
596593
597594 def generate (self ) -> None :
598595 super ().generate ()
599- input_voltage = self .get (self .input_voltage )
600- output_voltage = self .get (self .output_voltage )
601- frequency = self .get (self .frequency )
602- output_current = self .get (self .output_current )
603- inductor_current_ripple = self .get (self .inductor_current_ripple )
604- input_voltage_ripple = self .get (self .input_voltage_ripple )
605- output_voltage_ripple = self .get (self .output_voltage_ripple )
606-
607- # clip each mode's duty cycle to that mode's operating range
608- buck_dutycycle = (output_voltage / input_voltage / self .get (self .efficiency )).bound_to (Range (- float ('inf' ), 1 ))
609- self .assign (self .actual_buck_dutycycle , buck_dutycycle )
610- boost_dutycycle = (1 - input_voltage / output_voltage * self .get (self .efficiency )).bound_to (Range (0 , float ('inf' )))
611- self .assign (self .actual_boost_dutycycle , boost_dutycycle )
612-
613- # Calculate minimum inductance based on worst case values (operating range corners producing maximum inductance)
614- # This range must be constructed manually to not double-count the tolerance stackup of the voltages
615- buck_inductance_min = (output_voltage .lower * (input_voltage .upper - output_voltage .lower ) /
616- (inductor_current_ripple .upper * frequency .lower * input_voltage .upper ))
617- if inductor_current_ripple .lower == 0 : # basically infinite inductance
618- buck_inductance_max = float ('inf' )
619- else :
620- buck_inductance_max = (output_voltage .lower * (input_voltage .upper - output_voltage .lower ) /
621- (inductor_current_ripple .lower * frequency .lower * input_voltage .upper ))
622- min_current = max (0 , output_current .lower - inductor_current_ripple .upper / 2 ) # applies to both modes
623- buck_peak_current = output_current .upper + inductor_current_ripple .upper / 2
624- boost_inductance_min = (input_voltage .lower * (output_voltage .upper - input_voltage .lower ) /
625- (inductor_current_ripple .upper * frequency .lower * output_voltage .lower ))
626- if inductor_current_ripple .lower == 0 : # basically infinite inductance
627- boost_inductance_max = float ('inf' )
628- else :
629- boost_inductance_max = (input_voltage .lower * (output_voltage .upper - input_voltage .lower ) /
630- (inductor_current_ripple .lower * frequency .lower * output_voltage .lower ))
631- boost_peak_current = output_current .upper / (1 - boost_dutycycle .upper ) + inductor_current_ripple .upper / 2
632- inductor_spec_peak_current = max (buck_peak_current , boost_peak_current )
633- self .assign (self .inductor_spec_peak_current , inductor_spec_peak_current )
634-
635- # take intersection of buck and boost inductances, and hopefully they overlap
636- inductance_min = max (buck_inductance_min , boost_inductance_min )
637- inductance_max = min (buck_inductance_max , boost_inductance_max )
596+ buck_values = BuckConverterPowerPath .calculate_parameters (
597+ self .get (self .input_voltage ), self .get (self .output_voltage ),
598+ self .get (self .frequency ), self .get (self .output_current ),
599+ self .get (self .inductor_current_ripple ), self .get (self .input_voltage_ripple ), self .get (self .output_voltage_ripple ),
600+ efficiency = self .get (self .efficiency ), dutycycle_limit = Range (0 , 1 ))
601+ boost_values = BoostConverterPowerPath .calculate_parameters (
602+ self .get (self .input_voltage ), self .get (self .output_voltage ),
603+ self .get (self .frequency ), self .get (self .output_current ),
604+ self .get (self .inductor_current_ripple ), self .get (self .input_voltage_ripple ), self .get (self .output_voltage_ripple ),
605+ efficiency = self .get (self .efficiency ), dutycycle_limit = Range (0 , 1 ))
606+ self .assign (self .actual_buck_dutycycle , buck_values .effective_dutycycle )
607+ self .assign (self .actual_boost_dutycycle , boost_values .effective_dutycycle )
608+
638609 self .inductor = self .Block (Inductor (
639- inductance = ( inductance_min , inductance_max ) * Henry ,
640- current = ( 0 , inductor_spec_peak_current ),
641- frequency = frequency * Hertz
610+ inductance = buck_values . inductance . intersect ( boost_values . inductance ) * Henry ,
611+ current = buck_values . inductor_peak_currents . hull ( buck_values . inductor_peak_currents ),
612+ frequency = self . frequency
642613 ))
643614
644- buck_actual_ripple = (output_voltage .lower * (input_voltage .upper - output_voltage .lower ) /
645- (self .inductor .actual_inductance * frequency .lower * input_voltage .upper ))
646- boost_actual_ripple = (input_voltage .lower * (output_voltage .upper - input_voltage .lower ) /
647- (self .inductor .actual_inductance * frequency .lower * output_voltage .lower ))
615+ # TODO deduplciate w/ ripple code in buck and boost converters
616+ buck_actual_ripple = (self .output_voltage .lower () * (self .input_voltage .upper () - self .output_voltage .lower ()) /
617+ (self .inductor .actual_inductance * self .frequency .lower () * self .input_voltage .upper ()))
618+ boost_actual_ripple = (self .input_voltage .lower () * (self .output_voltage .upper () - self .input_voltage .lower ()) /
619+ (self .inductor .actual_inductance * self .frequency .lower () * self .output_voltage .lower ()))
648620 self .assign (self .actual_inductor_current_ripple , buck_actual_ripple .hull (boost_actual_ripple ))
649621
650622 self .connect (self .switch_in , self .inductor .a )
651- self .assign (self .actual_inductor_current , (min_current , inductor_spec_peak_current )) # peak currents
623+ dc_current_range = self .output_current / (1 - boost_values .effective_dutycycle .upper ) # DC range at worst case boost
624+ self .assign (self .actual_inductor_current , dc_current_range + (self .actual_inductor_current_ripple .upper () / 2 ))
652625 self .connect (self .switch_out , self .inductor .b )
653626 self .assign (self .actual_avg_current_rating , (0 , self .current_limits .intersect (self .inductor .actual_current_rating ).upper () -
654627 (self .actual_inductor_current_ripple .upper () / 2 )))
655628
656- input_buck_min_cap = (output_current .upper * BuckConverterPowerPath .max_d_inverse_d (buck_dutycycle ) /
657- (frequency .lower * input_voltage_ripple ))
658- input_boost_min_cap = ((output_current .upper / (1 - boost_dutycycle .upper )) /
659- (frequency .lower * input_voltage_ripple ))
660629 self .in_cap = self .Block (DecouplingCapacitor (
661- capacitance = Range . from_lower ( max ( input_buck_min_cap , input_boost_min_cap )) * Farad ,
630+ capacitance = buck_values . input_capacitance . intersect ( boost_values . input_capacitance ) * Farad ,
662631 exact_capacitance = True
663632 )).connected (self .gnd , self .pwr_in )
664-
665- # calculated with steady-state ripple
666- output_buck_min_cap = inductor_current_ripple .upper / (8 * frequency .lower * output_voltage_ripple )
667- output_boost_min_cap = output_current .upper * boost_dutycycle .upper / (frequency .lower * output_voltage_ripple )
668633 self .out_cap = self .Block (DecouplingCapacitor (
669- capacitance = Range . from_lower ( max ( output_buck_min_cap , output_boost_min_cap )) * Farad ,
634+ capacitance = buck_values . output_capacitance . intersect ( boost_values . output_capacitance ) * Farad ,
670635 exact_capacitance = True
671636 )).connected (self .gnd , self .pwr_out )
0 commit comments