class Base(Electrical()): """ # Filter Some filters made from resistors and capacitors. Those simple RC filters produced gentle highpass or lowpass gain characteristics, with a 6 dB/octave falloff well beyond the −3 dB point. By cascading highpass and lowpass filters, we showed how to ob- tain bandpass filters, again with gentle 6 dB/octave “skirts.” Such filters are sufficient for many purposes, especially if the signal being rejected by the filter is far removed in frequency from the desired signal passband. Some examples are bypassing of radiofrequency signals in audio circuits, “blocking” capacitors for elimination of dc levels, and separation of modulation from a communications “carrier.” * Paul Horowitz and Winfield Hill. "6.2 Passive filters" The Art of Electronics – 3rd Edition. Cambridge University Press, 2015, pp. 391 * TODO: https://www.nutsvolts.com/magazine/article/filter-basics-stop-block-and-rolloff * https://www.nutsvolts.com/magazine/article/filter-design-software ``` vs = VS(flow='SINEV')(V=5, frequency=[1e3, 1e6]) load = Resistor()(1000) filter = Example() vs & filter & load & vs watch = filter ``` """ pins = {'v_ref': True, 'input': ('Signal', ['output']), 'gnd': True} def willMount(self): self.output = self.input def circuit(self): pass
class Base(Electrical()): """# Voltage Double, Tripler, Quadrupler, etc Voltage doubler. Think of it as *two half-wave rectifier circuits* in series. Variations of this circuit by argument Scale exist for voltage triplers, quadruplers, etc. ) ``` vs = VS(flow='SINEV')(V=5, frequency=120) load = Resistor()(1000) doubler = Example() # triplers = Multiplier()(Scale=3, Frequency=120) # quadruplers = Multiplier()(Scale=4, Frequency=120) vs & doubler & load & vs watch = doubler end_time = 50 @ u_ms ``` You can extend this scheme as far as you want, producing what’s called a Cockcroft–Walton generator; these are used in arcane applications (such as particle accelerators) and in everyday applications (such as image intensifiers, air ionizers, laser copiers, and even bug zappers) that require a high dc voltage but hardly any current. * Paul Horowitz and Winfield Hill. "1.6.4 Rectifier configurations for power supplies" The Art of Electronics – 3rd Edition. Cambridge University Press, 2015, pp. 33-35 """ def willMount(self, Scale=2, Frequency=120 @ u_Hz, V_ripple=1 @ u_V): self.load(self.V * self.Scale) def circuit(self): HalfBridge = Rectifier(wave='half', rectifier='full') bridge = self.gnd sections = [] if self.Scale % 2: sections.append((bridge, self.input)) else: sections.append((self.input, bridge)) for block in range(int(self.Scale)): last = sections[-1] scaler = HalfBridge(V=self.V * self.Scale) scaler.gnd += last[0] scaler.input += last[1] sections.append((scaler.input, scaler.output)) self.output += sections[-1][1]
class Base(Electrical()): """ ## PushPull power booster Bipolar follower booster has the usual problem that the follower output can only source current. As with transistor circuits, the remedy is a push–pull booster. * Paul Horowitz and Winfield Hill. "4.3.1 Linear circuits" The Art of Electronics – 3rd Edition. Cambridge University Press, 2015, p.435 """ pins = { 'v_ref': True, 'input': True, 'output': True, 'v_inv': True, 'gnd': True } def circuit(self): up = Bipolar(type='npn')() down = Bipolar(type='pnp')() self.wire_input(up, down) self.output & up.emitter & down.emitter self.v_ref & up.v_ref self.v_inv & down.collector def wire_input(self, up, down): self.input += up.base, down.base
class Base(Electrical()): diodes = [] pins = {'v_ref': ('Supply', ['input']), 'gnd': ('Gnd', ['output'])} def willMount(self, diodes): if type(diodes) != list: self.diodes = [diodes]
class Base(Electrical()): pins = {'v_ref': True, 'input': ('Body', ['output']), 'gnd': True} def willMount(self): self.output = self.input def circuit(self): pass
class Base(Electrical()): """ A Schmitt trigger is a decision-making circuit. It is used to convert a slowly varying analogue signal voltage into one of two possible binary states, depending on whether the analogue voltage is above or below a preset threshold value. A comparator can do much the same job. * https://en.wikipedia.org/wiki/Schmitt_trigger """ def willMount(self, Load=10000 @ u_Ohm, V_on=7 @ u_V, V_off=3 @ u_V): pass
class Base(Electrical()): """ ``` vs = VS(flow='V')(V=5) mcu = Example() vs & mcu.v_ref mcu.gnd & vs watch = mcu ``` """ def willMount(self, series='ATmega8', frequency=5e6 @ u_Hz): pass def circuit(self): mcu = Microcontroller(series=self.series, reset='switch')(V=1, frequency=self.frequency) self.V_max = mcu.V * 2 power = Regulator(via='ic')(V=self.V_max, V_out=mcu.V) self.v_ref & power self.gnd & power.gnd power & mcu supply_indication = power & Led(via='resistor')(diodes=Diode( type='led')(color='green')) usb = mcu & UsbUart(via='atmega16u2')() & Plug(interface='usb', type='b')() interfaces = {} for interface in mcu.mods['interface']: interfaces[interface] = mcu & Plug(interface=interface)( ref=interface) buses = defaultdict(list) for pin in mcu.element.pins: port = re.match(r'([A-Z]{1,3})([0-9]{1,3})', pin.name) if port: port, bit = port.groups() buses[port].append(port + bit) return True for bus in buses.keys(): bus_width = len(buses[bus]) if bus_width > 1: connector = Physical( part='Connector_Generic:Conn_01x0' + str(bus_width), footprint='Connector_PinHeader_2.54mm:PinHeader_1x0' + str(bus_width) + '_P2.54mm_Vertical')(ref=bus) for index, pin in enumerate(buses[bus]): connector[index + 1] & mcu[pin]
class Base(Electrical()): pins = { 'v_ref': True, 'input': ('Some', ['output']), 'output_n': True, 'gnd': True } def circuit(self): pass
class Base(Electrical()): """ This design is used to buffer signals by presenting a high input impedance and a low output impedance. This circuit is commonly used to drive low-impedance loads, analog-to-digital converters (ADC) and buffer reference voltages. The output voltage of this circuit is equal to the input voltage. * http://www.ti.com/lit/an/sboa269a/sboa269a.pdf """ props = { 'via': ['opamp', 'bipolar', 'mosfet'] } def willMount(self, Frequency=100 @ u_Hz): """ V -- Verify that the amplifier can achieve the desired output swing using the supply voltages provided V_signal -- Signal amplitude slew_rate -- The rate of change in the output voltage caused by a step change on the input. """ self.load(self.V) self.V_signal = self.V / sqrt(2) # RMS self.slew_rate = 2 * pi * self.Frequency * self.V def circuit(self): via = self.props.get('via', None) buffer = None if via == 'opamp': """ 1. Use the op-amp linear output operating range, which is usually specified under the AOL test conditions. 2. The small-signal bandwidth is determined by the unity-gain bandwidth of the amplifier. 3. Check the maximum output voltage swing versus frequency graph in the datasheet to minimize slewinduced distortion. 4. The common mode voltage is equal to the input signal. 5. Do not place capacitive loads directly on the output that are greater than the values recommended in the datasheet. 6. High output current amplifiers may be required if driving low impedance loads """ buffer = OpAmp()(frequency=self.Frequency) buffer.input_n & buffer.output & self.output if via == 'bipolar': buffer = Bipolar(type='npn', emitter='follower')() buffer & self.output if buffer: self.input & buffer buffer.v_ref & self.v_ref buffer.gnd & self.gnd else: self.input & self.output
class Base(Electrical()): """**Pulser** Pulse triggered when some event occur. """ width = 0.03 @ u_s pins = {'v_ref': True, 'gnd': True} def willMount(self, width=None, input=None): self.input = input def circuit(self): self.input = self.output = self.input or Net('PulseGeneratorInput')
class Base(Network(port='many'), Electrical()): """ **OR Gate** In this circuit, if either (or several) A or B are high, that respective transistor will turn on, and pull the output high. If both transistors are off, then the output is pulled low through the resistor. """ def circuit(self): for signal in self.inputs: or_gate = Bipolar(type='npn', common='emitter', follow='emitter')(collector=self.v_ref, base=Resistor()(10000), emitter=self.output) signal & or_gate.input pulldown = self.output & Resistor()(10000) & self.gnd
class Base(Electrical()): """# Voltage Divider Voltage dividers are often used in circuits to gener- ate a particular voltage from a larger fixed (or varying) voltage. Voltage divider from `V_(\i\\n)` to `V_(out)` could be implemented in different ways and provide enought current to `Load`. This isn’t as crazy as it sounds; it is possible to make devices with negative “incremental” resistances (e.g., the component known as a tunnel diode) or even true negative resistances (e.g., the negative-impedance converter). * Paul Horowitz and Winfield Hill. "1.2.3 Voltage Dividers" The Art of Electronics – 3rd Edition. Cambridge University Press, 2015, p. 7-8 """ # Props def willMount(self, V=5 @ u_V, V_out=3 @ u_V, Load=0.01 @ u_A): """ V_out -- Note that the output voltage is always less than (or equal to) the input voltage; that’s why it’s called a divider. """ self.load(self.V_out)
class Base(Electrical(), Network(port='two')): """**Transistor Current Source** Happily, it is possible to make a very good current source with a transistor. It works like this: applying `V_b` to the base, with `V_b>0.6 V`, ensures that the emitter is always conducting: `V_e = V_b − 0.6 V` so `I_e = V_e / R_e = (V_b − 0.6 V) / R_e` But, since `I_e ≈ I_(load)` for large beta, `I_(load) ≈ (V_b − 0.6 V) / R_e` * Paul Horowitz and Winfield Hill. "2.2.5 Emitter follower biasing" The Art of Electronics – 3rd Edition. Cambridge University Press, 2015, p. 86 """ pins = { 'v_ref': ('Vref', ['input', 'output']), 'output_n': True, 'gnd': True } def willMount(self, Load=0.001 @ u_A): """ """ self.load(self.V) def circuit(self, **kwargs): generator = Bipolar(type='npn', follow='emitter')() self.V_e = generator.V_je + randint(1, int(u(self.V) / 2)) @ u_V self.V_b = self.V_e + generator.V_je self.R_e = self.V_e / self.I_load generator.collector += self.output_n controller = Divider(type='resistive')(V=self.V, V_out=self.V_b, Load=self.I_load) controller.input += self.v_ref controller.gnd += self.gnd source = controller.output & generator & Resistor()( self.R_e) & self.gnd
class Base(Network(port='two'), Electrical()): """# Diode Bridge A diode bridge is an arrangement of four (or more) diodes in a bridge circuit configuration that provides the same polarity of output for either polarity of input. ``` vs = VS(flow='SINEV')(V=220, frequency=60) load = Resistor()(1000) rectifier = Example() vs & rectifier vs.gnd & rectifier.input_n rectifier.output & load & rectifier.output_n watch = rectifier ``` * Paul Horowitz and Winfield Hill. "1.6.2 Rectification" The Art of Electronics – 3rd Edition. Cambridge University Press, 2015, p. 31-32 """ def willMount(self): """ V_ripple -- Periodic variations in voltage about the steady value frequency -- Input signal frequency """ self.load(self.V) def __series__(self, instance): if self.output and instance.input: self.output._name = instance.input._name = f'{self.name}{instance.name}_Net' self.output += instance.input if self.output_n and instance.input_n: self.output_n += instance.input_n if self.v_ref and instance.v_ref: self.v_ref += instance.v_ref def circuit(self, **kwargs): self.create_bridge() def create_bridge(self): pass
class Base(Electrical()): """ * https://www.nutsvolts.com/magazine/article/the_pid_controller_part_1 * http://www.ecircuitcenter.com/Circuits/op_pid/op_pid.htm * http://www.ecircuitcenter.com/Circuits/pid1/pid1.htm * file:///Users/fefa4ka/Yandex.Disk.localized/%D0%97%D0%B0%D0%B3%D1%80%D1%83%D0%B7%D0%BA%D0%B8/op_amp_pid_paper_MATEC_FORMAT.pdf """ pins = { 'v_ref': True, 'set': ('SetPoint', ['input']), 'sensor': True, 'output': True, 'v_inv': True, 'gnd': True } def willMount(self, Gain=2, Frequency=100 @ u_Hz): pass def circuit(self): params = {'Gain': self.Gain, 'Frequency': self.Frequency} loss = Difference(via='opamp')(**params) proportional = Inverter(via='opamp')(**params) integral = Integrator(via='opamp')(**params) derivative = Differentiator(via='opamp')(**params) self.set & loss.input self.sensor & loss.input_n loss.output & proportional.input & integral.input self.sensor & derivative pid = Summer(via='opamp')(inputs=[proportional, integral, derivative], **params) pid & self.output # Power supply parts = [loss, proportional, integral, derivative, pid] for part in parts: self.v_ref & part.v_ref self.v_inv & part.v_inv self.gnd & part.gnd
class Base(Electrical(), Network(port='two')): """ # Differential amplifier The differential amplifier shown here is a device that compares two separate input signals, takes the difference between them, and then amplifies this difference. In the ideal case the output is entirely independent of the individual signal levels – only the difference matters. The differential amplifier is sometimes called a “long-tailed pair.” To understand how the circuit works, treat both transistors as identical, and then notice that both transistors are set in the common-emitter configuration. Differential amplifiers are important in applications in which weak signals are contaminated by “pickup” and other miscellaneous noise. When both inputs change levels together, that’s a _common-mode_ input change. A differential change is called _normal mode_, or sometimes _differential mode_. ``` # Power supply v_ref = VS(flow='V')(V=10) v_inv = VS(flow='V')(V=-10) # Signals signal_1 = VS(flow='SINEV')(V=0.2, frequency=120) signal_2 = VS(flow='SINEV')(V=0.3, frequency=1200) # Load load = Resistor()(1000) # Amplifier diff = Example() # Network v_ref & diff.v_ref v_inv & diff.v_inv signal_1 & diff.input signal_2 & diff.input_n diff.output & load & v_ref diff.gnd & v_inv.gnd & v_ref.gnd & signal_1.gnd & signal_2.gnd watch = diff ``` * Paul Horowitz and Winfield Hill. "2.3.8 Differential amplifier" The Art of Electronics – 3rd Edition. Cambridge University Press, 2015, pp. 102-104 """ pass
class Base(Network(port='many'), Electrical()): """**AND Gate** If either transistor is turned off, then the output at the second transistor’s collector will be pulled low. If both transistors are “on” (bases both high), then the output of the circuit is also high. """ def circuit(self): v_ref = self.v_ref for signal in self.inputs: and_input = Bipolar(type='npn', follow='emitter')(collector=v_ref, base=Resistor()(10000)) and_input.input += signal v_ref = and_input.output self.outputs = [v_ref] pulldown = v_ref & Resistor()(10000) & self.gnd
class Base(Network(interface=['uart', 'usb']), Electrical()): """ ``` vs = VS(flow='V')(V=5) adapter = Example() vs & adapter.v_ref adapter.gnd & vs watch = adapter ``` """ pins = { 'v_ref': True, 'gnd': True, 'D+': True, 'D-': True, 'RX': True, 'TX': True }
class Base(Electrical(), Network(port='two')): """**Bipolar Transistor Current Mirror** The technique of matched base–emitter biasing can be used to make what is called a current mirror, an interesting current-source circuit that simply reverses the sign of a “programming” current. You program the mirror by sinking a current from Q1’s collector. That causes a `V_(be)` for Q1 appropriate to that current at the circuit temperature and for that transistor type. Q2, matched to Q1, * Paul Horowitz and Winfield Hill. "2.2.5 Emitter follower biasing" The Art of Electronics – 3rd Edition. Cambridge University Press, 2015, p. 86 """ pins = {'v_ref': ('Vref', ['input']), 'output': True, 'gnd': True} def willMount(self, amount=1): """ amount -- Number of different loads R_g -- An easy way to generate the control current `I_(load)` is with a resistor """ self.V_drop = 0 def circuit(self, **kwargs): programmer = Bipolar(type='pnp', follow='collector', common='base')() self.V_drop += programmer.V_je mirror = self.mirror(programmer) load = mirror & self.output def ref_input(self): return self.input def mirror(self, programmer): self.R_g = (self.V - self.V_drop) / self.I_load mirror = Bipolar(type='pnp', follow='collector', common='base')() mirroring = mirror.base & programmer.base generator = Resistor()(self.R_g) sink = self.ref_input( ) & programmer & programmer.base & generator & self.gnd load = self.ref_input() & mirror return mirror.output
class Base(Electrical()): """ This design inverts the input signal, V, and applies a signal gain of -Gain. The input signal typically comes from a low-impedance source because the input impedance of this circuit is determined by the input resistor, R_input. The common-mode voltage of an inverting amplifier is equal to the voltage connected to the non-inverting node, which is ground in this design. """ pins = { 'input': True, 'output': True, 'v_ref': True, 'v_inv': True, 'gnd': True } props = {'via': ['opamp', 'bipolar', 'mosfet']} def willMount(self, Gain=2, Frequency=100 @ u_Hz): self.slew_rate = 2 * pi * Frequency * self.V * Gain * -1 # Transfer function V_output = V_input * (- R_feedback / R_input) def circuit(self): R = Resistor() # Determine the starting value of R_input. # The relative size of R_input to the signal source impedance affects the # gain error. Assuming the impedance from the signal source is low (for example, 100 Ω), set R_input = 10 kΩ # for 1% gain error. source = R(self.R_load * 10) feedback = R(self.Gain * source.value) self.NG = 1 + feedback.value / source.value inverter = OpAmp(boost='bipolar')(frequency=self.Frequency) inverter.v_ref & self.v_ref inverter.input & self.gnd inverter.gnd & self.v_inv self.input & source & inverter.input_n & feedback & inverter.output & self.output
class Base(Network(port='many'), Electrical()): pins = { 'input': True, 'input_n': True, 'output': True, 'v_ref': True, 'v_inv': True, 'gnd': True } props = {'via': ['opamp', 'bipolar', 'mosfet']} def willMount(self, Gain=[2], Frequency=100 @ u_Hz): if type(Gain) == list and len(Gain) == 1: self.Gain = Gain[0] def circuit(self): R = Resistor() R_init = self.R_load * 10 Gain = max(self.Gain) if type(self.Gain) == list else self.Gain # Determine the starting value of R_input. # The relative size of R_input to the signal source impedance affects the # gain error. Assuming the impedance from the signal source is low (for example, 100 Ω), set R_input = 10 kΩ # for 1% gain error. feedback = R(Gain * R_init) summer = OpAmp()(Frequency=self.Frequency) summer.v_ref & self.v_ref summer.input & self.gnd summer.v_inv & self.v_inv for index, signal in enumerate(self.inputs): Gain = self.Gain[index] if type(self.Gain) == list else self.Gain source = R(feedback.value / Gain) signal & source & summer.input_n summer.input_n & feedback & summer.output & self.output
class Base(Network(port='many'), Electrical()): """ **NOT Gate — Inverter** Here a high voltage into the base will turn the transistor on, which will effectively connect the collector to the emitter. Since the emitter is connected directly to ground, the collector will be as well (though it will be slightly higher, somewhere around VCE(sat) ~ 0.05-0.2V). If the input is low, on the other hand, the transistor looks like an open circuit, and the output is pulled up to VCC """ def circuit(self): new_outputs = [] for signal in self.inputs: inverted = Net('LogicInverted') inverter = Bipolar(type='npn', common='emitter', follow='collector')( collector = Resistor()(1000), base = Resistor()(10000) ) inverter.v_ref += self.v_ref inverter.gnd += self.gnd circuit = signal & inverter & inverted new_outputs.append(inverted) self.outputs = new_outputs
class Base(Electrical(), Network(port='two')): """**Switch** Switch connected series to the signal. """ pins = { 'v_ref': True, 'input': 'ControlP', 'input_n': 'ControllerN', 'output': 'LoadP', 'output_n': 'LoadN' } def willMount(self, V_ref=15 @ u_V): if not self.gnd: self.gnd = Net() self.load_block = Virtual()(input=self.output, output=self.output_n) self.load(self.V_ref) def circuit(self): pass
class Modificator(Electrical()): """ This design amplifies the input signal, `V`, with a signal gain of `Gain`. The input signal may come from a high-impedance source (for example, MΩ) because the input impedance of this circuit is determined by the extremely high input impedance of the op amp (for example, GΩ). The common-mode voltage of a non-inverting amplifier is equal to the input signal. """ pins = { 'input': True, # The input impedance of this circuit is equal to the input impedance of the amplifier. 'output': True, # Avoid placing capacitive loads directly on the output of the amplifier to minimize stability issues 'v_ref': True, 'v_inv': True, 'gnd': True } def willMount(self, Gain=2, Frequency=1e3 @ u_Hz): # Calculate the minimum slew rate required to minimize slew-induced distortion self.Slew_rate = 2 * pi * self.V * Frequency def circuit(self): R = Resistor() amplifier = OpAmp()(frequency=self.Frequency) self.v_ref & amplifier.v_ref self.v_inv & amplifier.gnd # Using high-value resistors can degrade the phase margin of the circuit and introduce additional noise in the circuit. feedback = R( self.R_load * 10 ) # Common principle to use much larger input impeadance compared to load before amplifier TODO: Why? source = R(feedback.value / (self.Gain - 1)) self.input & amplifier.input self.gnd & source & amplifier.input_n & feedback & amplifier.output & self.output
class Base(Electrical()): """# Decay to equilibrium The product RC is called the time constant of the circuit. For `R_s` in ohms and `C_g` in farads, the product RC is in seconds. A `C_g` microfarad across `R_s = 1.0kΩ` has a time constant of 1 ms; if the capacitor is initially charged to `V_(out) = 1.0 V`, the initial current `I_(out) = 1.0 mA`. At time `t = 0`, someone connects the battery. The equation for the circuit is then `I = C * (dV) / (dT) = (V_(i\\n) - V_(out)) / R_s` with solution `V_(out) = V_(i\\n) + A * e ^ (-t / (R_s * C_g))` ``` vs = VS(flow='PULSEV')(V=5, pulse_width=0.2, period=0.4) load = Resistor()(1000) delay = Decay()(V=5, V_out=3, Time_to_V_out=0.1) vs & delay & load & vs watch = delay ``` The constant `A` is determined by initial conditions: `V_(out) = 0` at `t = 0`; therefore, `A = −V_(i\\n)`, and `V_(out) = V_(i\\n) * (1 − e ^ (−t / (R_s * C_g)))` Once again there’s good intuition: as the capacitor charges up, the slope (which is proportional to current, because it’s a capacitor) is proportional to the remaining voltage (because that’s what appears across the resistor, producing the current); so we have a waveform whose slope decreases proportionally to the vertical distance it has still to go an exponential. To figure out the time required to reach a voltage `V_(out)` on the way to the final voltage `V_(i\\n)`: `t = R * C * log_e(V_(i\\n) / (V_(i\\n) - V_(out)))` * Paul Horowitz and Winfield Hill. "1.4.2 RC circuits: V and I versus time" The Art of Electronics – 3rd Edition. Cambridge University Press, 2015, pp. 21-23 """ def willMount(self, V_out=5 @ u_V, Time_to_V_out=5e-3 @ u_s, reverse=False): """ reverse -- Reverse capacitor connection """ self.load(self.V_out) self.Power = self.power(self.V, self.R_load / 2) def circuit(self): current_source = Resistor()(self.R_load / 2) discharger = Capacitor()( (self.Time_to_V_out / (current_source.value * log(self.V / (self.V - self.V_out)))) @ u_F ) if self.reverse: self.input & current_source & self.output self.gnd & discharger & self.output else: self.input & current_source & self.output & discharger & self.gnd
class Modificator(Electrical()): """ The integrator circuit outputs the integral of the input signal over a frequency range based on the circuit time constant and the bandwidth of the amplifier. The input signal is applied to the inverting input so the output is inverted relative to the polarity of the input signal. The ideal integrator circuit will saturate to the supply rails depending on the polarity of the input offset voltage and requires the addition of a feedback resistor, R_feedback, to provide a stable DC operating point. The feedback resistor limits the lower frequency range over which the integration function is performed. ``` # Power supply v_ref = VS(flow='V')(V=10) v_inv = VS(flow='V')(V=-10) signal = VS(flow='SINEV')(V=0.2, frequency=120) load = Resistor()(1000) # Amplifier inverter = Example() # Network v_ref & inverter.v_ref v_inv & inverter.v_inv signal & inverter.input inverter.output & load & v_ref inverter.gnd & v_inv.gnd & v_ref.gnd & signal.gnd watch = inverter ``` This circuit is most commonly used as part of a larger feedback/servo loop which provides the DC feedback path, thus removing the requirement for a feedback resistor. * http://www.ti.com/lit/an/sboa275a/sboa275a.pdf """ pins = { 'input': True, 'output': True, 'v_ref': True, 'v_inv': True, 'gnd': True } def willMount(self, Q=100, Frequency=1e3 @ u_Hz): pass def circuit(self): """ C_integrator -- `(integrator) = 1 / (2 * pi * (sensor) * (Frequency))` """ R = Resistor() # Set R_input to a standard value sensor = R(100 @ u_kOhm) # Calculate C_integrator to set the unety-gain integration frequency. integrator = Capacitor()( (1 / (2 * pi * sensor.value * self.Frequency)) @ u_F) # Calculate R_feedback to set the lower cutoff frequency a decade less than the minimum operating frequency feedback = R( (10 / (2 * pi * integrator.value * self.Frequency / self.Q)) @ u_Ohm) self.H = -1 / (sensor.value * integrator.value) # Select an amplifier with a gain bandwidth at least 10 times the desired maximum operating frequency buffer = OpAmp()(Frequency=self.Frequency * self.Q) buffer.connect_power_bus(self) self.input & sensor & buffer.input_n & ( feedback | integrator) & buffer.output & self.output self.gnd & buffer.input
class Base(Electrical()): pass
class Base(Electrical()): """ """ def willMount(self, V_out=3.3 @ u_V): self.load(V_out)
class Base(Electrical()): """ """ pass