Exemplo n.º 1
0
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
Exemplo n.º 2
0
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]
Exemplo n.º 3
0
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
Exemplo n.º 4
0
class Base(Electrical()):
    diodes = []

    pins = {'v_ref': ('Supply', ['input']), 'gnd': ('Gnd', ['output'])}

    def willMount(self, diodes):
        if type(diodes) != list:
            self.diodes = [diodes]
Exemplo n.º 5
0
class Base(Electrical()):
    pins = {'v_ref': True, 'input': ('Body', ['output']), 'gnd': True}

    def willMount(self):
        self.output = self.input

    def circuit(self):
        pass
Exemplo n.º 6
0
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
Exemplo n.º 7
0
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]
Exemplo n.º 8
0
class Base(Electrical()):
    pins = {
        'v_ref': True,
        'input': ('Some', ['output']),
        'output_n': True,
        'gnd': True
    }

    def circuit(self):
        pass
Exemplo n.º 9
0
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
Exemplo n.º 10
0
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')
Exemplo n.º 11
0
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
Exemplo n.º 12
0
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)
Exemplo n.º 13
0
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
Exemplo n.º 14
0
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
Exemplo n.º 15
0
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
Exemplo n.º 16
0
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
Exemplo n.º 17
0
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
Exemplo n.º 18
0
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
    }
Exemplo n.º 19
0
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
Exemplo n.º 20
0
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
Exemplo n.º 21
0
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
Exemplo n.º 22
0
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
Exemplo n.º 23
0
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
Exemplo n.º 24
0
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
Exemplo n.º 25
0
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
Exemplo n.º 26
0
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
Exemplo n.º 27
0
class Base(Electrical()):
    pass
Exemplo n.º 28
0
class Base(Electrical()):
    """
    """
    def willMount(self, V_out=3.3 @ u_V):
        self.load(V_out)
Exemplo n.º 29
0
class Base(Electrical()):
    """
    """

    pass