Skip to content

Commit c8fd285

Browse files
authored
Abstract parts cleanup (#496)
Follow-on to #495, cleans up some of the abstract_parts modules. - Breaks ZenerDiode out of Diode - Deprecates LedDriver abstract class, removes subclasses dependence on this base class by inlining code. Non-backwards compatible (though trivially fixable), refinements will break. - Breaks up PowerConverters into LinearRegulator, SwitchingVoltageRegulator - Moves the BuckConverterPowerPath, BoostConverterPowerPath, BuckBoostConverterPowerPath into circuits - Moves some of the resistor application circuits into the circuits package, especially the functional protection circuits as opposed to type-wrappers
1 parent 0b22c21 commit c8fd285

51 files changed

Lines changed: 1466 additions & 1397 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

edg/abstract_parts/Diode.py

Lines changed: 0 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
from typing import Any, Dict
22
from typing_extensions import override
3-
from deprecated import deprecated
43

54
from ..electronics_interfaces import *
65
from .PartsTable import PartsTableColumn, PartsTableRow
@@ -144,113 +143,3 @@ def _row_generate(self, row: PartsTableRow) -> None:
144143
self.assign(self.actual_current_rating, row[self.CURRENT_RATING])
145144
self.assign(self.actual_voltage_drop, row[self.FORWARD_VOLTAGE])
146145
self.assign(self.actual_reverse_recovery_time, row[self.REVERSE_RECOVERY])
147-
148-
149-
@abstract_block
150-
class ZenerDiode(KiCadImportableBlock, BaseDiode, DiscreteSemiconductor):
151-
"""Base class for untyped zeners
152-
153-
TODO power? capacitance? leakage current?
154-
"""
155-
156-
@override
157-
def symbol_pinning(self, symbol_name: str) -> Dict[str, BasePort]:
158-
assert symbol_name in ("Device:D_Zener", "Device:D_Zener_Small")
159-
return {"A": self.anode, "K": self.cathode}
160-
161-
def __init__(self, zener_voltage: RangeLike) -> None:
162-
super().__init__()
163-
164-
self.zener_voltage = self.ArgParameter(zener_voltage)
165-
166-
self.actual_zener_voltage = self.Parameter(RangeExpr())
167-
self.actual_power_rating = self.Parameter(RangeExpr())
168-
169-
@override
170-
def contents(self) -> None:
171-
super().contents()
172-
173-
self.description = DescriptionString(
174-
"zener voltage=",
175-
DescriptionString.FormatUnits(self.actual_zener_voltage, "V"),
176-
" <b>of spec:</b>",
177-
DescriptionString.FormatUnits(self.zener_voltage, "V"),
178-
"\n",
179-
"power=",
180-
DescriptionString.FormatUnits(self.actual_power_rating, "W"),
181-
)
182-
183-
184-
@non_library
185-
class TableZenerDiode(PartsTableSelector, ZenerDiode):
186-
ZENER_VOLTAGE = PartsTableColumn(Range)
187-
POWER_RATING = PartsTableColumn(Range) # tolerable power
188-
189-
def __init__(self, *args: Any, **kwargs: Any) -> None:
190-
super().__init__(*args, **kwargs)
191-
self.generator_param(self.zener_voltage)
192-
193-
@override
194-
def _row_filter(self, row: PartsTableRow) -> bool:
195-
return super()._row_filter(row) and row[self.ZENER_VOLTAGE].fuzzy_in(self.get(self.zener_voltage))
196-
197-
@override
198-
def _row_generate(self, row: PartsTableRow) -> None:
199-
super()._row_generate(row)
200-
self.assign(self.actual_zener_voltage, row[self.ZENER_VOLTAGE])
201-
self.assign(self.actual_power_rating, row[self.POWER_RATING])
202-
203-
204-
class ProtectionZenerDiode(Protection):
205-
"""Zener diode reversed across a power rail to provide transient overvoltage protection (and become an incandescent
206-
indicator on a reverse voltage)"""
207-
208-
def __init__(self, voltage: RangeLike):
209-
super().__init__()
210-
211-
self.pwr = self.Port(
212-
VoltageSink(voltage_limits=RangeExpr()),
213-
[Power, InOut],
214-
)
215-
self.gnd = self.Port(Ground(), [Common])
216-
217-
self.voltage = self.ArgParameter(voltage)
218-
219-
@override
220-
def contents(self) -> None:
221-
super().contents()
222-
self.diode = self.Block(ZenerDiode(zener_voltage=self.voltage))
223-
self.connect(self.pwr.net, self.diode.cathode)
224-
self.connect(self.gnd.net, self.diode.anode)
225-
self.assign(self.pwr.voltage_limits, (0, self.diode.actual_zener_voltage.lower()))
226-
227-
228-
@deprecated("Use AnalogClampResistor, which should be cheaper and cause less signal distortion")
229-
class AnalogClampZenerDiode(Protection, KiCadImportableBlock):
230-
"""Analog overvoltage protection diode to clamp the input voltage"""
231-
232-
def __init__(self, voltage: RangeLike):
233-
super().__init__()
234-
235-
self.diode = self.Block(ZenerDiode(zener_voltage=voltage))
236-
237-
self.gnd = self.Port(Ground(), [Common])
238-
self.signal_in = self.Port(AnalogSink(), [Input])
239-
self.signal_out = self.Port(
240-
AnalogSource(
241-
voltage_out=self.signal_in.link().voltage.intersect(
242-
self.gnd.link().voltage + (0, self.diode.actual_zener_voltage.upper())
243-
),
244-
signal_out=self.signal_in.link().signal,
245-
),
246-
[Output],
247-
)
248-
self.assign(self.signal_in.current_draw, self.signal_out.link().current_drawn)
249-
250-
self.connect(self.signal_in.net, self.signal_out.net, self.diode.cathode)
251-
self.connect(self.gnd.net, self.diode.anode)
252-
253-
@override
254-
def symbol_pinning(self, symbol_name: str) -> Dict[str, Port]:
255-
assert symbol_name == "edg_importable:AnalogClampZenerDiode"
256-
return {"IN": self.signal_in, "OUT": self.signal_out, "GND": self.gnd}

edg/abstract_parts/LedDriver.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from deprecated import deprecated
55

66

7+
@deprecated("LED API is not stabilized")
78
@abstract_block
89
class LedDriver(PowerConditioner, Interface):
910
"""Abstract current-regulated high-power LED driver.
@@ -30,6 +31,7 @@ def __init__(self, *args: Any, ripple_limit: FloatLike = float("inf"), **kwargs:
3031
self.ripple_limit = self.ArgParameter(ripple_limit)
3132

3233

34+
@deprecated("LED API is not stabilized")
3335
class LedDriverPwm(BlockInterfaceMixin[LedDriver]):
3436
"""LED driver mixin with PWM input for dimming control."""
3537

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
from typing_extensions import override
2+
3+
from ..electronics_interfaces import *
4+
from .Resettable import Resettable
5+
from .VoltageRegulator import VoltageRegulator
6+
7+
8+
@abstract_block_default(lambda: IdealLinearRegulator)
9+
class LinearRegulator(VoltageRegulator):
10+
"""Structural abstract base class for linear regulators, a voltage regulator that can produce some
11+
output voltage lower than its input voltage (minus some dropout) by 'burning' the excess voltage as heat.
12+
13+
Compared to switching converters like buck and boost converters, linear regulators usually have lower
14+
complexity, lower parts count, and higher stability. However, depending on the application, they are
15+
typically less efficient, and at higher loads may require thermal design considerations."""
16+
17+
18+
@abstract_block
19+
class VoltageReference(LinearRegulator):
20+
"""Voltage reference, generally provides high accuracy but limited current"""
21+
22+
23+
class IdealLinearRegulator(Resettable, LinearRegulator, IdealModel):
24+
"""Ideal linear regulator, draws the output current and produces spec output voltage limited by input voltage"""
25+
26+
@override
27+
def contents(self) -> None:
28+
super().contents()
29+
effective_output_voltage = self.output_voltage.intersect((0, self.pwr_in.link().voltage.upper()))
30+
self.gnd.init_from(Ground())
31+
self.pwr_in.init_from(VoltageSink(current_draw=self.pwr_out.link().current_drawn))
32+
self.pwr_out.init_from(VoltageSource(voltage_out=effective_output_voltage))
33+
self.reset.init_from(DigitalSink())
34+
35+
36+
@non_library
37+
class LinearRegulatorDevice(Block):
38+
"""Abstract base class that provides a default model with common functionality for a linear regulator chip.
39+
Does not include supporting components like capacitors.
40+
"""
41+
42+
def __init__(self) -> None:
43+
super().__init__()
44+
45+
# these device model parameters must be provided by subtypes
46+
self.actual_dropout = self.Parameter(RangeExpr())
47+
self.actual_quiescent_current = self.Parameter(RangeExpr())
48+
49+
self.gnd = self.Port(Ground(), [Common])
50+
self.pwr_in = self.Port(
51+
VoltageSink(voltage_limits=RangeExpr(), current_draw=RangeExpr()), # parameters set by subtype
52+
[Power, Input],
53+
)
54+
self.pwr_out = self.Port(
55+
VoltageSource(voltage_out=self.RangeExpr(), current_limits=RangeExpr()), # parameters set by subtype
56+
[Output],
57+
)
58+
self.assign(self.pwr_in.current_draw, self.pwr_out.link().current_drawn + self.actual_quiescent_current)
59+
60+
self.require(
61+
self.pwr_out.voltage_out.lower() + self.actual_dropout.upper() <= self.pwr_in.link().voltage.lower(),
62+
"excessive dropout",
63+
)

0 commit comments

Comments
 (0)