diff --git a/edg/abstract_parts/OpampCircuits.py b/edg/abstract_parts/OpampCircuits.py index 2b0a7a4d9..1cf848e41 100644 --- a/edg/abstract_parts/OpampCircuits.py +++ b/edg/abstract_parts/OpampCircuits.py @@ -363,8 +363,9 @@ class IntegratorInverting(OpampApplication, KiCadSchematicBlock, KiCadImportable From https://en.wikipedia.org/wiki/Operational_amplifier_applications#Inverting_integrator: Vout = - 1/RC * int(Vin) (integrating over time) - Series is lower and tolerance is higher because there's a cap involved - TODO - separate series for cap, and series and tolerance by decade? + 1/RC (in units 1/s or Hz) is the integrator gain. + One intuitive interpretation is, for a DC input, one period of the frequency + is the time it takes for the output voltage to change by the input voltage. """ @override @@ -387,7 +388,7 @@ def symbol_pinning(self, symbol_name: str) -> Dict[str, BasePort]: } return mapping[symbol_name] - def __init__(self, factor: RangeLike, capacitance: RangeLike, *, series: IntLike = 6, tolerance: FloatLike = 0.05): + def __init__(self, gain: RangeLike, capacitance: RangeLike): super().__init__() self.amp = self.Block(Opamp()) @@ -398,23 +399,23 @@ def __init__(self, factor: RangeLike, capacitance: RangeLike, *, series: IntLike self.output = self.Port(AnalogSource.empty()) self.reference = self.Port(AnalogSink.empty()) # negative reference for the input and output signals - self.factor = self.ArgParameter(factor) # output scale factor, 1/RC in units of 1/s + self.gain = self.ArgParameter(gain) # 1/RC in units of 1/s self.capacitance = self.ArgParameter(capacitance) - self.actual_factor = self.Parameter(RangeExpr()) + self.actual_gain = self.Parameter(RangeExpr()) @override def contents(self) -> None: super().contents() self.description = DescriptionString( - "factor: ", - DescriptionString.FormatUnits(self.actual_factor, ""), + "gain: ", + DescriptionString.FormatUnits(self.actual_gain, ""), " of spec: ", - DescriptionString.FormatUnits(self.factor, ""), + DescriptionString.FormatUnits(self.gain, ""), ) - self.r = self.Block(Resistor((1 / self.factor).shrink_multiply(1 / self.capacitance))) + self.r = self.Block(Resistor((1 / self.gain).shrink_multiply(1 / self.capacitance))) self.c = self.Block(Capacitor(capacitance=self.capacitance, voltage=self.output.link().voltage)) self.import_kicad( @@ -427,7 +428,7 @@ def contents(self) -> None: }, ) - self.assign(self.actual_factor, 1 / self.r.actual_resistance / self.c.actual_capacitance) + self.assign(self.actual_gain, 1 / self.r.actual_resistance / self.c.actual_capacitance) class SummingAmplifier(OpampApplication): diff --git a/edg/abstract_parts/PowerCircuits.py b/edg/abstract_parts/PowerCircuits.py index b77ce7c8a..d72ea6850 100644 --- a/edg/abstract_parts/PowerCircuits.py +++ b/edg/abstract_parts/PowerCircuits.py @@ -237,12 +237,21 @@ def contents(self) -> None: voltage=(0 * Volt(tol=0)).hull(self.pwr_in.link().voltage), ) ) + + # because PMOS is source-referenced from vin, calculate the Vgs from GND by subtracting from Vin + # however, we can't calculate a fixed Vgs range for all Vin, since it would be overly restrictive, + # so instead we calculate ratios at the Vin corners, then take the intersection of the ratios + # this may generate intermediate negative ratios, but the intersection should clamp those + # for reasonable target_vgs + vgs_ratio_low = (self.pwr_in.link().voltage.lower() - self.target_vgs) / self.pwr_in.link().voltage.lower() + vgs_ratio_hi = (self.pwr_in.link().voltage.upper() - self.target_vgs) / self.pwr_in.link().voltage.upper() + # dV/dt over a capacitor is I / C => I = Cgd * dV/dt # then calculate to get the target I: Vgs,th = I * Reff => Reff = Vgs,th / I = Vgs,th / (Cgd * dV/dt) # we assume Vgs,th is exact, and only contributing sources come from elsewhere self.div = self.Block( ResistiveDivider( - ratio=self.target_vgs.shrink_multiply(1 / self.pwr_in.link().voltage), + ratio=vgs_ratio_low.intersect(vgs_ratio_hi), impedance=(1 / self.target_ramp).shrink_multiply( self.drv.actual_gate_drive.lower() / (self.cap_gd.actual_capacitance) ), diff --git a/examples/UsbSourceMeasure/SourceMeasureControl.kicad_sch b/examples/UsbSourceMeasure/SourceMeasureControl.kicad_sch index 96b9cba45..b3a67537e 100644 --- a/examples/UsbSourceMeasure/SourceMeasureControl.kicad_sch +++ b/examples/UsbSourceMeasure/SourceMeasureControl.kicad_sch @@ -6838,7 +6838,7 @@ (hide yes) ) ) - (property "Value2" "factor=1/4.7e-6*Ratio(tol=0.15)," + (property "Value2" "gain=100/4.7*kHertz(tol=0.15)," (at 113.03 101.346 0) (effects (font @@ -6846,7 +6846,7 @@ ) ) ) - (property "Value3" "capacitance=1*nFarad(tol=0.1))" + (property "Value3" "capacitance=10*nFarad(tol=0.1))" (at 113.03 103.632 0) (effects (font @@ -9786,7 +9786,7 @@ (hide yes) ) ) - (property "Value2" "ratio=10*Ratio(tol=0.05))" + (property "Value2" "ratio=5*Ratio(tol=0.05))" (at 237.49 128.016 0) (effects (font diff --git a/examples/UsbSourceMeasure/UsbSourceMeasure.net b/examples/UsbSourceMeasure/UsbSourceMeasure.net index 78a9fdff8..f9ae6d627 100644 --- a/examples/UsbSourceMeasure/UsbSourceMeasure.net +++ b/examples/UsbSourceMeasure/UsbSourceMeasure.net @@ -176,8 +176,8 @@ (property (name "edg_path") (value "ramp.div.top_res")) (property (name "edg_short_path") (value "ramp.div.top_res")) (property (name "edg_refdes") (value "R2")) - (property (name "edg_part") (value "0603WAF2203T5E (UNI-ROYAL(Uniroyal Elec))")) - (property (name "edg_value") (value "±1% 1/10W Thick Film Resistors 75V ±100ppm/℃ -55℃~+155℃ 220kΩ 0603 Chip Resistor - Surface Mount ROHS")) + (property (name "edg_part") (value "0603WAF6803T5E (UNI-ROYAL(Uniroyal Elec))")) + (property (name "edg_value") (value "±1% 1/10W Thick Film Resistors 75V ±100ppm/℃ -55℃~+155℃ 680kΩ 0603 Chip Resistor - Surface Mount ROHS")) (sheetpath (names "/ramp/div/") (tstamps "/043901b1/02770144/")) (tstamps "0c0c02fd")) (comp (ref "R3") @@ -188,8 +188,8 @@ (property (name "edg_path") (value "ramp.div.bottom_res")) (property (name "edg_short_path") (value "ramp.div.bottom_res")) (property (name "edg_refdes") (value "R3")) - (property (name "edg_part") (value "0603WAF6803T5E (UNI-ROYAL(Uniroyal Elec))")) - (property (name "edg_value") (value "±1% 1/10W Thick Film Resistors 75V ±100ppm/℃ -55℃~+155℃ 680kΩ 0603 Chip Resistor - Surface Mount ROHS")) + (property (name "edg_part") (value "0603WAF2203T5E (UNI-ROYAL(Uniroyal Elec))")) + (property (name "edg_value") (value "±1% 1/10W Thick Film Resistors 75V ±100ppm/℃ -55℃~+155℃ 220kΩ 0603 Chip Resistor - Surface Mount ROHS")) (sheetpath (names "/ramp/div/") (tstamps "/043901b1/02770144/")) (tstamps "175b043f")) (comp (ref "Q2") @@ -1628,8 +1628,8 @@ (property (name "edg_path") (value "control.int.c")) (property (name "edg_short_path") (value "control.int.c")) (property (name "edg_refdes") (value "C52")) - (property (name "edg_part") (value "CL10B102KB8NNNC (Samsung Electro-Mechanics)")) - (property (name "edg_value") (value "50V 1nF X7R ±10% 0603 Multilayer Ceramic Capacitors MLCC - SMD/SMT ROHS")) + (property (name "edg_part") (value "0603B103K500NT (FH(Guangdong Fenghua Advanced Tech))")) + (property (name "edg_value") (value "50V 10nF X7R ±10% 0603 Multilayer Ceramic Capacitors MLCC - SMD/SMT ROHS")) (sheetpath (names "/control/int/") (tstamps "/0bec0302/028e014c/")) (tstamps "00640064")) (comp (ref "R35") @@ -2180,8 +2180,8 @@ (property (name "edg_path") (value "control.imeas.rg")) (property (name "edg_short_path") (value "control.imeas.rg")) (property (name "edg_refdes") (value "R54")) - (property (name "edg_part") (value "0603WAF5601T5E (UNI-ROYAL(Uniroyal Elec))")) - (property (name "edg_value") (value "±1% 1/10W Thick Film Resistors 75V ±100ppm/℃ -55℃~+155℃ 5.6kΩ 0603 Chip Resistor - Surface Mount ROHS")) + (property (name "edg_part") (value "0603WAF1202T5E (UNI-ROYAL(Uniroyal Elec))")) + (property (name "edg_value") (value "±1% 1/10W Thick Film Resistors 75V ±100ppm/℃ -55℃~+155℃ 12kΩ 0603 Chip Resistor - Surface Mount ROHS")) (sheetpath (names "/control/imeas/") (tstamps "/0bec0302/062a0210/")) (tstamps "014d00da")) (comp (ref "Q9") diff --git a/examples/test_usb_source_measure.py b/examples/test_usb_source_measure.py index ce1085136..77f86a3b8 100644 --- a/examples/test_usb_source_measure.py +++ b/examples/test_usb_source_measure.py @@ -547,7 +547,7 @@ def contents(self) -> None: (self.ramp, self.cap_conv), _ = self.chain( self.vusb, imp.Block( - RampLimiter(target_vgs=(3.7, 19) * Volt) + RampLimiter(target_vgs=(3.5, 17.5) * Volt) ), # avoid excess capacitance on VBus which may cause the PD source to reset imp.Block(DecouplingCapacitor(47 * uFarad(tol=0.25))), )