def hysteresis_threshold_ratios_opendrain(r1, r2, rh):
    """
    Same as hysteresis_threshold_ratios(), but for open-drain comparators.
    In contrast to hysteresis_threshold_ratios(), ignores rh for the upper
    threshold.

    Parameters
    ----------
    r1 : float or EngineerIO string
        The top resistor of the divider
    r2 : float or EngineerIO string
        The bottom resistor of the divider
    rh : float or EngineerIO string
        The hysteresis resistor of the divider
    """
    # Normalize inputs
    r1 = normalize_numeric(r1)
    r2 = normalize_numeric(r2)
    rh = normalize_numeric(rh)
    # Compute r1, r2 in parallel with rh
    r2rh = parallel_resistors(r2, rh)
    # Compute thresholds
    thl = unloaded_ratio(r1, r2rh)
    thu = unloaded_ratio(r1, r2)
    return (thl, thu)
Beispiel #2
0
def load_capacitors(cload, cpin="3 pF", cstray="2 pF") -> Unit("F"):
    """
    Compute the load capacitors which should be used for a given crystal,
    given that the load capacitors should be symmetric (i.e. have the same value).

    NOTE: You need to use a stray capacitance value that does NOT
    include the parasitic pin capacitance!

    Based on (C1 * C2) / (C1 + C2) + Cstray
    for C1 == C2 == (returned value) + cpin

    >>> auto_format(load_capacitors, "6 pF", cpin="3 pF", cstray="2pF")
    '5.00 pF'

    Parameters
    ----------
    cload : float
        The load capacitance as given in the crystal datasheet
    cstray : float
        The stray capacitance
    cpin : float
        The capacitance of one of the oscillator pins of the connected device
    """
    cload = normalize_numeric(cload)
    cstray = normalize_numeric(cstray)
    cpin = normalize_numeric(cpin)
    # cload = (C1 * C2) / (C1 + C2) + Cstray where C1 == C2
    # => solve A = (B*B) / (B+B) + C for B
    # => solve A = ((B+P)*(B+P)) / ((B+P)+(B+P)) + C for B
    return (2 * (cload - cstray)) - cpin
Beispiel #3
0
def capacitive_reactance(c, f=1000.0) -> Unit("Ω"):
    """
    Compute the capacitive reactance for a given capacitance and frequency.
    """
    c = normalize_numeric(c)
    f = normalize_numeric(f)
    return 1.0 / (2 * np.pi * f * c)
Beispiel #4
0
def hysteresis_threshold_ratios_opendrain(r1, r2, rh):
    """
    Same as hysteresis_threshold_ratios(), but for open-drain comparators.
    In contrast to hysteresis_threshold_ratios(), ignores rh for the upper
    threshold.

    Parameters
    ----------
    r1 : float or EngineerIO string
        The top resistor of the divider
    r2 : float or EngineerIO string
        The bottom resistor of the divider
    rh : float or EngineerIO string
        The hysteresis resistor of the divider
    """
    # Normalize inputs
    r1 = normalize_numeric(r1)
    r2 = normalize_numeric(r2)
    rh = normalize_numeric(rh)
    # Compute r1, r2 in parallel with rh
    r2rh = parallel_resistors(r2, rh)
    # Compute thresholds
    thl = voltage_divider_ratio(r1, r2rh)
    thu = voltage_divider_ratio(r1, r2)
    return (thl, thu)
Beispiel #5
0
def inductive_reactance(l, f=1000.0) -> Unit("Ω"):
    """
    Compute the inductive reactance for a given inductance and frequency.
    """
    l = normalize_numeric(l)
    f = normalize_numeric(f)
    return 2 * np.pi * f * l
Beispiel #6
0
def normalize_minmax_tuple(arg, name="field"):
    """
    Interprets arg either a single +- value or as
    a 2-tuple of + and - values.
    All vaues 

    If arg is a tuple:
        Return ValueRange(arg[0], arg[1]) (strings are normalized)
    Else:
        Return ValueRange(-arg, +arg) (strings are normalized)

    name is for debugging purposes and shown in the exception string
    """
    # Parse coefficient and compute min & max factors
    if isinstance(arg, tuple):
        # Check length 2
        if len(arg) != 2:
            raise ValueError(
                "If {} is given as a tuple, it must have length 2. {} is {}".
                format(name, name, arg))
        # Parse tuple
        min_value = normalize_numeric(arg[0])
        max_value = normalize_numeric(arg[1])
    else:
        arg = normalize_numeric(arg)
        min_value = -arg
        max_value = arg
    return ValueRange(min_value, max_value)
Beispiel #7
0
def actual_load_capacitance(cext, cpin="3 pF", cstray="2 pF") -> Unit("F"):
    """
    Compute the actual load capacitance of a crystal given:

    - The external capacitance value (use "10 pF" if your have a
    10 pF capacitor on each of the crystal pins)
    - The parasitic pin capacitance

    The value returned should match the load capacitance value
    in the crystal datasheet.

    Based on (C1 * C2) / (C1 + C2) + Cstray

    If yu use a

    >>> auto_format(actual_load_capacitance, "5 pF", cpin="3 pF", cstray="2pF")
    '6.00 pF'

    Parameters
    ----------
    cext : float
        The load capacitor value
    cstray : float
        The stray capacitance
    cpin : float
        The capacitance of one of the oscillator pins of the connected device
    """
    cext = normalize_numeric(cext)
    cstray = normalize_numeric(cstray)
    cpin = normalize_numeric(cpin)
    # cload = (C1 * C2) / (C1 + C2) + Cstray where C1 == C2
    # => solve A = (B*B) / (B+B) + C for B
    # => solve A = ((B+P)*(B+P)) / ((B+P)+(B+P)) + C for B
    ctotal = cext + cpin
    return cstray + ((ctotal * ctotal) / (ctotal + ctotal))
Beispiel #8
0
def cylinder_surface_area(radius, height) -> Unit("m²"):
    """
    Compute the surface area (side + top + bottom)
    """
    radius = normalize_numeric(radius)
    height = normalize_numeric(height)
    return cylinder_side_surface_area(radius, height) + 2 * circle_area(radius)
Beispiel #9
0
def cylinder_side_surface_area(radius, height) -> Unit("m²"):
    """
    Compute the surface area of the side (also called ")
    """
    radius = normalize_numeric(radius)
    height = normalize_numeric(height)
    return 2 * math.pi * radius * height
Beispiel #10
0
def cylinder_volume(radius, height) -> Unit("m³"):
    """
    Compute the volume of a cylinder by its radius and height
    """
    radius = normalize_numeric(radius)
    height = normalize_numeric(height)
    return math.pi * (radius**2) * height
Beispiel #11
0
def top_resistor_by_ratio(rbottom, ratio) -> Unit("Ω"):
    """
    Compute the bottom resistor of a voltage divider given the top resistor value
    and the division ration
    """
    rbottom = normalize_numeric(rbottom)
    ratio = normalize_numeric(ratio)
    return rbottom * (1.0 / ratio - 1.0)
Beispiel #12
0
def unloaded_ratio(r1, r2) -> Unit(""):
    """
    Compute the denominator of the  division ratio of a voltage divider, not taking into account
    parasitic properties or loading
    """
    r1 = normalize_numeric(r1)
    r2 = normalize_numeric(r2)
    return r2 / (r1 + r2)
def unloaded_ratio(r1, r2) -> Quantity(""):
    """
    Compute the denominator of the  division ratio of a voltage divider, not taking into account
    parasitic properties or loading
    """
    r1 = normalize_numeric(r1)
    r2 = normalize_numeric(r2)
    return r2 / (r1 + r2)
def bottom_resistor_by_ratio(rtop, ratio) -> Quantity("Ω"):
    """
    Compute the bottom resistor of a voltage divider given the top resistor value
    and the division ration
    """
    rtop = normalize_numeric(rtop)
    ratio = normalize_numeric(ratio)
    return -(rtop * ratio) / (ratio - 1.0)
Beispiel #15
0
def current_by_power(power="25 W", voltage="230 V") -> Unit("A"):
    """
    Given a device's power (or RMS power) and the voltage (or RMS voltage)
    it runs on, compute how much current it will draw.
    """
    power = normalize_numeric(power)
    voltage = normalize_numeric(voltage)
    return power / voltage
Beispiel #16
0
def resistor_by_voltage_and_current(voltage, current) -> Unit("Ω"):
    """
    Compute the resistance value in Ohms that draws the given amount of
    current if the given voltage is across it.
    """
    voltage = normalize_numeric(voltage)
    current = normalize_numeric(current)
    return voltage / current
Beispiel #17
0
def bottom_resistor_by_ratio(rtop, ratio) -> Unit("Ω"):
    """
    Compute the bottom resistor of a voltage divider given the top resistor value
    and the division ration
    """
    rtop = normalize_numeric(rtop)
    ratio = normalize_numeric(ratio)
    return -(rtop * ratio) / (ratio - 1.0)
def top_resistor_by_ratio(rbottom, ratio) -> Quantity("Ω"):
    """
    Compute the bottom resistor of a voltage divider given the top resistor value
    and the division ration
    """
    rbottom = normalize_numeric(rbottom)
    ratio = normalize_numeric(ratio)
    return rbottom * (1.0 / ratio - 1.0)
Beispiel #19
0
def loaded_ratio(r1, r2, rl) -> Unit(""):
    """
    Compute the denominator of the  division ratio of a voltage divider, not taking into account
    parasitic properties but loading.
    """
    r1 = normalize_numeric(r1)
    r2 = normalize_numeric(r2)
    rl = normalize_numeric(rl)
    return r1 / (r1 + parallel_resistors(r2, rl))
Beispiel #20
0
def power_by_current_and_voltage(current="1.0 A",
                                 voltage="230 V") -> Unit("W"):
    """
    Given a device's current (or RMS current) and the voltage (or RMS current)
    it runs on, compute its power
    """
    current = normalize_numeric(current)
    voltage = normalize_numeric(voltage)
    return current * voltage
Beispiel #21
0
def centrifugal_force(radius: Unit("m"), speed: Unit("Hz"),
                      mass: Unit("g")) -> Unit("N"):
    """
    Compute the centrifugal force of a [mass] rotation at [speed] at radius [radius]
    """
    radius = normalize_numeric(radius)
    mass = normalize_numeric(
        mass) / 1000.0  # mass needs to be Kilograms TODO Improve
    return mass * angular_speed(speed)**2 * radius
def voltage_divider_ratio(rtop, rbot, rload=np.inf) -> Unit(""):
    """
    Compute the division ratio of a voltage divider.
    
    If rload is supplied, additional load (in parallel to R2) is taken into account.
    """
    rtop = normalize_numeric(rtop)
    rbot = normalize_numeric(rbot)
    return rbot / (rtop + parallel_resistors(rbot, rload))
def loaded_ratio(r1, r2, rl) -> Quantity(""):
    """
    Compute the denominator of the  division ratio of a voltage divider, not taking into account
    parasitic properties but loading.
    """
    r1 = normalize_numeric(r1)
    r2 = normalize_numeric(r2)
    rl = normalize_numeric(rl)
    return r1 / (r1 + parallel_resistors(r2, rl))
Beispiel #24
0
def capacitor_charge(capacitance, voltage) -> Unit("C"):
    """
    Compute the total charge stored in a capacitor given:
    - The capacitance in farads
    - The voltage the capacitor is charged to
    The charge is returned in coulombs.
    """
    capacitance = normalize_numeric(capacitance)
    voltage = normalize_numeric(voltage)
    return capacitance * voltage
Beispiel #25
0
def capacitor_charge(capacitance, voltage) -> Quantity("C"):
    """
    Compute the total charge stored in a capacitor given:
    - The capacitance in farads
    - The voltage the capacitor is charged to
    The charge is returned in coulombs.
    """
    capacitance = normalize_numeric(capacitance)
    voltage = normalize_numeric(voltage)
    return capacitance * voltage
Beispiel #26
0
def capacitor_energy(capacitance, voltage) -> Unit("J"):
    """
    Compute the total energy stored in a capacitor given:
    - The capacitance in farads
    - The voltage the capacitor is charged to
    The energy is returned as joules.
    """
    capacitance = normalize_numeric(capacitance)
    voltage = normalize_numeric(voltage)
    return 0.5 * capacitance * np.square(voltage)
def johnson_nyquist_noise_voltage(r, delta_f, T) -> Quantity("V"):
    """
    Compute the Johnson Nyquist noise current in amperes
    T must be given in °C whereas r must be given in Ohms.
    The result is given in volts
    """
    r = normalize_numeric(r)
    delta_f = normalize_numeric(delta_f)
    t_kelvin = normalize_temperature(T)
    return math.sqrt(4 * scipy.constants.k * t_kelvin * delta_f * r)
Beispiel #28
0
def capacitor_energy(capacitance, voltage) -> Quantity("J"):
    """
    Compute the total energy stored in a capacitor given:
    - The capacitance in farads
    - The voltage the capacitor is charged to
    The energy is returned as joules.
    """
    capacitance = normalize_numeric(capacitance)
    voltage = normalize_numeric(voltage)
    return 0.5 * capacitance * np.square(voltage)
def johnson_nyquist_noise_voltage(r, delta_f, T) -> Unit("V"):
    """
    Compute the Johnson Nyquist noise voltage in volts
    T must be given in °C whereas r must be given in Ohms.
    The result is given in volts
    """
    r = normalize_numeric(r)
    delta_f = normalize_numeric(delta_f)
    t_kelvin = normalize_temperature(T)
    return math.sqrt(4 * boltzmann_k * t_kelvin * delta_f * r)
Beispiel #30
0
def temperature_with_dissipation(power_dissipated="1 W",
                                 theta="50 °C/W",
                                 t_ambient="25 °C") -> Unit("°C"):
    """
    Compute the temperature of a component, given its thermal resistance (theta),
    its dissipated power and 
    """
    power_dissipated = normalize_numeric(power_dissipated)
    theta = normalize_numeric(theta)
    t_ambient = normalize_temperature_celsius(t_ambient)
    return t_ambient + power_dissipated * theta
Beispiel #31
0
def __hysteresis_threshold_factors(r1, r2, rh, fn):
    """Internal push-pull & open-drain common code"""
    # Normalize inputs
    r1 = normalize_numeric(r1)
    r2 = normalize_numeric(r2)
    rh = normalize_numeric(rh)
    # Compute thresholds
    thl, thu = fn(r1, r2, rh)
    # Compute factors
    thnom = voltage_divider_ratio(r1, r2)
    return (thl / thnom, thu / thnom)
Beispiel #32
0
def __hysteresis_threshold_factors(r1, r2, rh, fn):
    """Internal push-pull & open-drain common code"""
    # Normalize inputs
    r1 = normalize_numeric(r1)
    r2 = normalize_numeric(r2)
    rh = normalize_numeric(rh)
    # Compute thresholds
    thl, thu = fn(r1, r2, rh)
    # Compute factors
    thnom = unloaded_ratio(r1, r2)
    return (thl / thnom, thu / thnom)
def johnson_nyquist_noise_current(r, delta_f, T) -> Unit("A"):
    """
    Compute the Johnson Nyquist noise current in amperes
    T must be given in °C whereas r must be given in Ohms.
    The result is given in volts
    """
    r = normalize_numeric(r)
    delta_f = normalize_numeric(delta_f)
    t_kelvin = normalize_temperature(T)
    # Support celsius and kelvin inputs
    return math.sqrt((4 * boltzmann_k * t_kelvin * delta_f)/r)
Beispiel #34
0
def actualNoise(density, bandwith) -> Unit("V"):
    """
    Compute the actual noise given:
     - A noise density in x/√Hz where x is any unit
     - A bandwith in ΔHz

    >>> autoFormat(actualNoise, "100 µV", "100 Hz")
    '1.00 mV'
    """
    density = normalize_numeric(density)
    bandwith = normalize_numeric(bandwith)
    return np.sqrt(bandwith) * density
def actualNoise(density, bandwith) -> Quantity("V"):
    """
    Compute the actual noise given:
     - A noise density in x/√Hz where x is any unit
     - A bandwith in ΔHz

    >>> autoFormat(actualNoise, "100 µV", "100 Hz")
    '1.00 mV'
    """
    density = normalize_numeric(density)
    bandwith = normalize_numeric(bandwith)
    return np.sqrt(bandwith) * density
def noiseDensity(actual_noise, bandwith) -> Quantity("V/√Hz"):
    """
    Compute the noise density given:
     - A noise density in x/√Hz where x is any unit
     - A bandwith in ΔHz

    >>> formatValue(noiseDensity("1.0 mV", "100 Hz"), "V/√Hz")
    '100 μV/√Hz'
    """
    actual_noise = normalize_numeric(actual_noise)
    bandwith = normalize_numeric(bandwith)
    return actual_noise / np.sqrt(bandwith)
Beispiel #37
0
def noiseDensity(actual_noise, bandwith) -> Unit("V/√Hz"):
    """
    Compute the noise density given:
     - A noise density in x/√Hz where x is any unit
     - A bandwith in ΔHz

    >>> formatValue(noiseDensity("1.0 mV", "100 Hz"), "V/√Hz")
    '100 μV/√Hz'
    """
    actual_noise = normalize_numeric(actual_noise)
    bandwith = normalize_numeric(bandwith)
    return actual_noise / np.sqrt(bandwith)
Beispiel #38
0
def rotating_liquid_pressure(density: Unit("kg/m³"), speed: Unit("Hz"),
                             radius: Unit("m")) -> Unit("Pa"):
    """
    Compute the pressure in a body of liquid (relative to the steady-state pressure)
    The calculation does not include gravity.

    Also see https://www.youtube.com/watch?v=kIH7wEq3H-M
    Also see https://www.physicsforums.com/threads/pressure-of-a-rotating-bucket-of-liquid.38112/
    """
    density = normalize_numeric(density)
    speed = normalize_numeric(speed)
    radius = normalize_numeric(radius)
    return density * angular_speed(speed)**2 * radius**2
def voltage_divider_current(rtop, rbot, vin, rload=np.inf) -> Unit("V"):
    """
    Compute the current through the top resistor of a voltage divider.
    
    If rload is supplied, additional load (in parallel to R2) is taken into account.
    """
    vin = normalize_numeric(vin)
    rtop = normalize_numeric(rtop)
    vout = voltage_divider_voltage(rtop, rbot, vin, rload=rload)
    # Compute voltage delta across resistor
    vdelta = vout - vin
    # Compute current through resisotr
    return current_through_resistor(rtop, vdelta)
Beispiel #40
0
def _normalize_frequencies(freqs):
    # Normalize freqs: Allow [1.0] instead of 1.0
    if freqs is None:
        raise ValueError("Critical frequencies may not be None")
    # Allow multiple frequencies, but only 1 or 2
    if isinstance(freqs, collections.Iterable) and not isinstance(freqs, str):
        if len(freqs) == 0:
            raise ValueError("Empty frequency list")
        elif len(freqs) == 1:
            return normalize_numeric(freqs[0])
        elif len(freqs) > 2:
            raise ValueError("No more than 2 critical frequencies allowed")
    return normalize_numeric(freqs)
Beispiel #41
0
def barlow_tangential(outer_diameter: Unit("m"), inner_diameter: Unit("m"),
                      pressure: Unit("Pa")) -> Unit("Pa"):
    """
    Compute the tangential stress of a pressure vessel at [pressure] using Barlow's formula for thin-walled tubes.

    Note that this formula only applies for (outer_diameter/inner_diameter) < 1.2 !
    (this assumption is not checked). Otherwise, the stress distribution will be too uneven.
    """
    outer_diameter = normalize_numeric(outer_diameter)
    inner_diameter = normalize_numeric(inner_diameter)
    pressure = normalize_numeric(pressure)
    dm = (outer_diameter + inner_diameter) / 2
    s = (outer_diameter - inner_diameter) / 2
    return pressure * dm / (2 * s)
Beispiel #42
0
def ptx_temperature(r0, r, standard=ptxITS90, poly=None) -> Quantity("°C"):
    """
    Compute the PTx temperature at a given temperature.

    Accepts an additive correction polynomial that is applied to the resistance.
    If the poly kwarg is None, the polynom is automatically selected.
    noCorrection is used for other r0 values. In this case, use a
    custom polynomial (numpy poly1d object) as the poly kwarg.

    See http://www.thermometricscorp.com/pt1000 for reference
    """
    r = normalize_numeric(r)
    A, B = standard.a, standard.b
    # Select
    if poly is None:
        if abs(r0 - 1000.0) < 1e-3: poly = pt1000Correction
        elif abs(r0 - 100.0) < 1e-3: poly = pt100Correction
        else: poly = noCorrection

    t = ((-r0 * A + np.sqrt(r0 * r0 * A * A - 4 * r0 * B * (r0 - r))) /
         (2.0 * r0 * B))
    # For subzero-temperature refine the computation by the correction polynomial
    if isinstance(r, numbers.Number):
        if r < r0:
            t += poly(r)
    else:  # Treated like a numpy array
        t += poly(r) * np.piecewise(r, [r < r0, r >= r0], [1.0, 0.0])
    return t
Beispiel #43
0
def load_capacitors(cload, cstray="2 pF") -> Quantity("F"):
    """
    Compute the load capacitors which should be used for a given crystal,
    given that the load capacitors should be symmetric (i.e. have the same value).

    Parameters
    ----------
    cload : float
        The load capacitance as given in the crystal datasheet
    cstray : float
        The stray capacitance
    """
    cload = normalize_numeric(cload)
    cstray = normalize_numeric(cstray)
    # cload = (C1 * C2) / (C1 + C2) + Cstray where C1 == C2
    # => solve A = (B*B) / (B+B) + C for B
    return 2 * (cload - cstray)
Beispiel #44
0
def ntc_resistance(r25, b25, t) -> Quantity("Ω"):
    """
    Compute the NTC resistance by  temperature and NTC parameters

    Parameters
    ----------
    r25 : float or EngineerIO string
        The NTC resistance at 25°C, sometimes also called "nominal resistance"
    b25: float or EngineerIO string
        The NTC b-constant (e.g. b25/50, b25/85 or b25/100)
    t : temperature
        The temperature. Will be interpreted using normalize_temperature()
    """
    # Normalize inputs
    r25 = normalize_numeric(r25)
    b25 = normalize_numeric(b25)
    t = normalize_temperature(t) # t is now in Kelvins
    # Compute resistance
    return r25 * np.exp(b25 * (1./t - 1./(25. + zero_point_celsius)))
Beispiel #45
0
    def __init__(self, samplerate, freqs, btype="lowpass"):
        """
        Initialize a new filter

        Keyword arguments:
            samplerate: The sampling rate
            freqs: The frequency (for lopass/hipass) or a list of two frequencies
        """
        self.btype = btype
        self.freqs = freqs
        self.samplerate = normalize_numeric(samplerate)
        self.b = None
        self.a = None
        # These will be initialized in iir()
        self.order = None
        self.rp = None
        self.rs = None
        self.ftype = None
        # Normalize freqs: Allow [1.0] instead of 1.0
        if freqs is None:
            raise ValueError("Critical frequencies may not be none")
        if isinstance(freqs, collections.Iterable) and not isinstance(freqs, str):
            if len(freqs) == 1:
                freqs = freqs[0]
            elif len(freqs) == 0:
                raise ValueError("Empty frequency list")
            elif isinstance(freqs[0], str):
                freqs = [normalize_numeric(f) for f in freqs]
        # Allow "4.5 kHz" etc
        if isinstance(freqs, str):
            __freqs_orig = freqs
            freqs = normalize_numeric(freqs)
        self.filtfreqs = self._filtfreq(freqs)
        # Check & store pass type
        if btype == "lowpass" or btype == "highpass":
            if not isinstance(freqs, numbers.Number):
                raise ValueError("Pass-type {0} requires a single critical frequency, not {1}".format(btype, freqs))
        elif btype == "bandpass" or btype == "bandstop":
            if isinstance(freqs, numbers.Number) or len(freqs) != 2:
                raise ValueError("Pass-type {0} requires a two critical frequencies, not {1}".format(btype, freqs))
        else:
            raise ValueError("Invalid pass type '{0}': Use lowpass, highpass, bandpass or bandstop!".format(btype))
def feedback_bottom_resistor(vexp, rtop, vfb) -> Quantity("Ω"):
    """
    Utility to compute the bottom feedback resistor
    in a voltage feedback network (e.g. for a DC/DC converter)

    Parameters
    ----------
    vexp : float
        The voltage at between top and bottom of the voltage divider
    rtop : float
        The known top resistor
    vfb : float
        The feedback voltage that is servoed by the regulator
    """
    vexp = normalize_numeric(vexp)
    rtop = normalize_numeric(rtop)
    vfb = normalize_numeric(vfb)
    # Vo = Vfb * (R1/R2 + 1)
    # solve A = B*((C/D) + 1) for D
    return (vfb * rtop) / (vexp - vfb)
Beispiel #47
0
 def as_samplerate(self, samplerate):
     """
     Convert this filter to a filter with the same frequency response.
     Returns a new filter instance.
     """
     if self.a is None:
         raise NotComputedException()
     samplerate = normalize_numeric(samplerate)
     if samplerate == self.samplerate:
         return self
     filt = SignalFilter(samplerate, self.freqs, self.btype)
     filt.iir(self.order, self.ftype, self.rp, self.rs)
     return filt
Beispiel #48
0
def hysteresis_resistor(r1, r2, fh=0.05):
    """
    Computes the hysteresis resistor Rh for a given
    R1, R2 divider network and a given deviation factor.

    The deviation factor fh represents the one-sided deviation
    from the nominal R1/R2 ratio. The total hysteresis is +-fh,
    i.e 2*fh.

    For example, for fh=0.05, the threshold will be 95% and 105%
    of the nominal ratio respectively.

    For open-drain comparators, fh represents the full deviation
    as the upper threshold is equivalent to the nominal threshold.


    Parameters
    ----------
    r1 : float or EngineerIO string
        The top resistor of the divider
    r2 : float or EngineerIO string
        The bottom resistor of the divider
    fh : float or EngineerIO string
        The deviation factor (e.g. 0.05 for 5% one-sided hysteresis
         deviation from the nominal r1/r2 value)
    """
    # Normalize inputs
    r1 = normalize_numeric(r1)
    r2 = normalize_numeric(r2)
    fh = normalize_numeric(fh)
    # NOTE: We compute rh for the lower threshold only
    thnom = unloaded_ratio(r1, r2)
    ratio_target = thnom * (1. - fh)
    # Compute the resistor that, in parallel to R2, yields
    # a divider with our target ratio
    r2total = bottom_resistor_by_ratio(r1, ratio_target)
    # Solve 1/R3 = (1/R1 + 1/R2) for R2 => R2 = (R1 * R3) / (R1 - R3)
    return (r2 * r2total) / (r2 - r2total)
Beispiel #49
0
def hysteresis_threshold_ratios(r1, r2, rh):
    """
    Calculates hysteresis threshold factors for push-pull comparators

    Assumes that r1 and r2 are used to divide Vcc using a fixed ratio to
    obtain a threshold voltage.
    Additionally, Rh sources or sinks current to the threshold voltage,
    depending on the current state of the comparator.
    Additionally it it assumed that the same voltage (Vcc) that feeds
    the R1+R2 divider is output from the comparator and input to Rh.

    This function computes the (lower, upper) division ratios by
    assuming rh is set either parallel with R1 (upper) or with R2 (lower).

    Returns a tuple (lower, upper) containing floats
    representing the division ratios.

    Parameters
    ----------
    r1 : float or EngineerIO string
        The top resistor of the divider
    r2 : float or EngineerIO string
        The bottom resistor of the divider
    rh : float or EngineerIO string
        The hysteresis resistor of the divider
    """
    # Normalize inputs
    r1 = normalize_numeric(r1)
    r2 = normalize_numeric(r2)
    rh = normalize_numeric(rh)
    # Compute r1, r2 in parallel with rh
    r1rh = parallel_resistors(r1, rh)
    r2rh = parallel_resistors(r2, rh)
    # Compute thresholds
    thl = unloaded_ratio(r1, r2rh)
    thu = unloaded_ratio(r1rh, r2)
    return (thl, thu)
def feedback_actual_voltage(rtop, rbot, vfb) -> Quantity("V"):
    """
    Compute the actual voltage regulator output in a feedback
    servo setup. Returns the Vout voltage.

    Parameters
    ----------
    rtop : float
        The top resistor of the voltage divider
    rbot : float
        The bottom resistor of the voltage divider
    vfb : float
        The feedback voltage
    """
    # Equation: Vout * ratio = vfb
    ratio = unloaded_ratio(rtop, rbot)
    return normalize_numeric(vfb) / ratio
Beispiel #51
0
def summing_amplifier_noninv(v1, v2, r1, r2, rfb1, rfb2) -> Quantity("V"):
    """
    Computes the output voltage of a non-inverting summing amplifier:
    V1 connected via R1 to IN+
    V2 connected via R2 to IN+
    IN- connected via RFB1 to GND
    IN- connected via RFB2 to VOut
    """
    v1 = normalize_numeric(v1)
    v2 = normalize_numeric(v2)
    r1 = normalize_numeric(r1)
    r2 = normalize_numeric(r2)
    rfb1 = normalize_numeric(rfb1)
    rfb2 = normalize_numeric(rfb2)
    return (1.0 + rfb2 / rfb1) * (v1 * (r2 / (r1 + r2)) + v2 * (r1 / (r1 + r2)))
Beispiel #52
0
def __hysteresis_threshold_voltages(r1, r2, rh, vcc, fn):
    """Internal push-pull & open-drain common code"""
    vcc = normalize_numeric(vcc)
    thl, thu = fn(r1, r2, rh)
    return (thl * vcc, thu * vcc)