Skip to content

Commit

Permalink
Strict LDO dropout (#386)
Browse files Browse the repository at this point in the history
Prior, the LDO dropout would propagate to the output voltage and assume
that the LDO would track. This creates an assertion that the input
voltage is greater than the dropout. Not super strict, only checks that
the input lower bound is greater than the output lower bound + dropout.

Rationale: voltage_out is a spec, and it's not being met. Users can
change the dropout voltage in refinements to tighten bounds (eg, LDO
operating at less than max current) or allow the regulator to go into
tracking.

Also refactors out actual_target_voltage since it's no longer needed.
  • Loading branch information
ducky64 authored Oct 28, 2024
1 parent 36fa559 commit 437c4b4
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 20 deletions.
15 changes: 6 additions & 9 deletions edg/abstract_parts/AbstractPowerConverters.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,25 +101,22 @@ def __init__(self) -> None:
# these device model parameters must be provided by subtypes
self.actual_dropout = self.Parameter(RangeExpr())
self.actual_quiescent_current = self.Parameter(RangeExpr())
self.actual_target_voltage = self.Parameter(RangeExpr())

self.gnd = self.Port(Ground(), [Common])
self.pwr_in = self.Port(VoltageSink(
voltage_limits=RangeExpr(),
voltage_limits=RangeExpr(), # parameters set by subtype
current_draw=RangeExpr()
), [Power, Input])
# dropout voltage is modeled to expand the tolerance range for actual output voltage
self.pwr_out = self.Port(VoltageSource(
voltage_out=( # bounds are lowest of the target voltage or dropout voltage
self.actual_target_voltage.lower().min(self.pwr_in.link().voltage.lower() - self.actual_dropout.upper()),
self.actual_target_voltage.upper().min(self.pwr_in.link().voltage.upper() - self.actual_dropout.lower()),
),
voltage_out=self.RangeExpr(), # parameters set by subtype
current_limits=RangeExpr()
), [Output])
self.gnd = self.Port(Ground(), [Common])

self.assign(self.pwr_in.current_draw,
self.pwr_out.link().current_drawn + self.actual_quiescent_current)

self.require(self.pwr_out.voltage_out.lower() + self.actual_dropout.upper() <= self.pwr_in.link().voltage.lower(),
"excessive dropout")


@abstract_block
class SwitchingVoltageRegulator(VoltageRegulator):
Expand Down
20 changes: 10 additions & 10 deletions edg/parts/LinearRegulators.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def generate(self):
assert suitable_parts, "no regulator with compatible output"
part_output_voltage, part_number, lcsc_part = suitable_parts[0]

self.assign(self.actual_target_voltage, part_output_voltage)
self.assign(self.pwr_out.voltage_out, part_output_voltage)
self.assign(self.lcsc_part, lcsc_part)
self.assign(self.actual_basic_part, False)
self.footprint(
Expand Down Expand Up @@ -89,7 +89,7 @@ def generate(self):
assert suitable_parts, "no regulator with compatible output"
part_output_voltage_nominal, part_number, jlc_number = suitable_parts[0]

self.assign(self.actual_target_voltage, part_output_voltage_nominal * Volt(tol=TOLERANCE))
self.assign(self.pwr_out.voltage_out, part_output_voltage_nominal * Volt(tol=TOLERANCE))
self.footprint(
'U', 'Package_TO_SOT_SMD:SOT-223-3_TabPin2',
{
Expand Down Expand Up @@ -159,7 +159,7 @@ def generate(self):
assert suitable_parts, "no regulator with compatible output"
part_output_voltage_nominal, part_number, jlc_number = suitable_parts[0]

self.assign(self.actual_target_voltage, part_output_voltage_nominal * Volt(tol=TOLERANCE))
self.assign(self.pwr_out.voltage_out, part_output_voltage_nominal * Volt(tol=TOLERANCE))
self.footprint(
'U', 'Package_TO_SOT_SMD:SOT-23-5',
{
Expand Down Expand Up @@ -204,7 +204,7 @@ def __init__(self, output_voltage: RangeLike):
self.assign(self.pwr_out.current_limits, (0, 0.6) * Amp)
self.assign(self.actual_quiescent_current, (50, 80) * uAmp)
self.assign(self.actual_dropout, (0, 0.25) * Volt) # worst-case @ 100mA Iout
self.assign(self.actual_target_voltage, (3.234, 3.366) * Volt)
self.assign(self.pwr_out.voltage_out, (3.234, 3.366) * Volt)
self.footprint(
'U', 'Package_TO_SOT_SMD:SOT-89-3',
{
Expand Down Expand Up @@ -273,7 +273,7 @@ def generate(self):
assert suitable_parts, "no regulator with compatible output"
part_output_voltage, part_number, part_dropout, part_max_current, lcsc_part, basic_part = suitable_parts[0]

self.assign(self.actual_target_voltage, part_output_voltage * Volt)
self.assign(self.pwr_out.voltage_out, part_output_voltage * Volt)
self.assign(self.actual_dropout, part_dropout * Volt)
self.assign(self.pwr_out.current_limits, (0, part_max_current) * Amp)
self.footprint(
Expand Down Expand Up @@ -337,7 +337,7 @@ def generate(self):
assert suitable_parts, "no regulator with compatible output"
part_output_voltage_nominal, part_number, part_dropout, lcsc_part = suitable_parts[0]

self.assign(self.actual_target_voltage, part_output_voltage_nominal * Volt(tol=TOLERANCE))
self.assign(self.pwr_out.voltage_out, part_output_voltage_nominal * Volt(tol=TOLERANCE))
self.assign(self.actual_dropout, part_dropout * Volt)
self.footprint(
'U', 'Package_TO_SOT_SMD:SOT-23-5',
Expand Down Expand Up @@ -408,7 +408,7 @@ def generate(self):
assert suitable_parts, "no regulator with compatible output"
part_output_voltage_nominal, part_number, jlc_number = suitable_parts[0]

self.assign(self.actual_target_voltage, part_output_voltage_nominal * Volt(tol=TOLERANCE))
self.assign(self.pwr_out.voltage_out, part_output_voltage_nominal * Volt(tol=TOLERANCE))
self.footprint(
'U', 'Package_TO_SOT_SMD:SOT-23-5',
{
Expand Down Expand Up @@ -496,7 +496,7 @@ def generate(self):
assert suitable_parts, "no regulator with compatible output"
part_output_voltage, part_number, footprint, jlc_number = suitable_parts[0]

self.assign(self.actual_target_voltage, part_output_voltage)
self.assign(self.pwr_out.voltage_out, part_output_voltage)
if footprint == 'Package_TO_SOT_SMD:SOT-23-5':
pinning: Dict[str, CircuitPort] = {
'1': self.pwr_in,
Expand Down Expand Up @@ -591,7 +591,7 @@ def generate(self):
assert suitable_parts, "no regulator with compatible output"
part_output_voltage, part_number, part_dropout, lcsc = suitable_parts[0]

self.assign(self.actual_target_voltage, part_output_voltage)
self.assign(self.pwr_out.voltage_out, part_output_voltage)
self.assign(self.actual_dropout, (0, part_dropout)*Volt)

self.footprint(
Expand Down Expand Up @@ -659,7 +659,7 @@ def generate(self):
if part[0] in self.get(self.output_voltage)]
assert suitable_parts, "no regulator with compatible output"

self.assign(self.actual_target_voltage, suitable_parts[0][0])
self.assign(self.pwr_out.voltage_out, suitable_parts[0][0])
self.assign(self.pwr_in.voltage_limits, suitable_parts[0][1])
self.assign(self.pwr_out.current_limits, (0, 100)*mAmp)
self.assign(self.actual_quiescent_current, suitable_parts[0][2])
Expand Down
2 changes: 1 addition & 1 deletion edg/parts/VoltageReferences.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def generate(self):
assert suitable_parts, "no regulator with compatible output"
part_output_voltage, part_number, lcsc_part = suitable_parts[0]

self.assign(self.actual_target_voltage, part_output_voltage)
self.assign(self.pwr_out.voltage_out, part_output_voltage)
self.assign(self.lcsc_part, lcsc_part)
self.assign(self.actual_basic_part, False)
self.footprint(
Expand Down
1 change: 1 addition & 0 deletions examples/test_pcbbot.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ def refinements(self) -> Refinements:
]),

(['prot_batt', 'diode', 'footprint_spec'], 'Diode_SMD:D_SMA'), # big diodes to dissipate more power
(['reg_3v3', 'ic', 'actual_dropout'], Range(0.0, 0.3)) # tighter dropout from lower current draw
],
class_refinements=[
(PassiveConnector, JstPhKVertical), # default connector series unless otherwise specified
Expand Down

0 comments on commit 437c4b4

Please sign in to comment.