Skip to content

Instantly share code, notes, and snippets.

@takehironet
Last active December 16, 2020 21:09
Show Gist options
  • Save takehironet/e9ad7fe292f8e235336f0a882850f572 to your computer and use it in GitHub Desktop.
Save takehironet/e9ad7fe292f8e235336f0a882850f572 to your computer and use it in GitHub Desktop.
RCによるチャタリング除去回路の時定数計算
e24 =   [1.0
        ,1.1
        ,1.2
        ,1.3
        ,1.5
        ,1.6
        ,1.8
        ,2.0
        ,2.2
        ,2.4
        ,2.7
        ,3.0
        ,3.3
        ,3.6
        ,3.9
        ,4.3
        ,4.7
        ,5.1
        ,5.6
        ,6.2
        ,6.8
        ,7.5
        ,8.2
        ,9.1]

def list_e(base: int):
    for i in range(0, 24, int(24 / base)):
        yield e24[i]
class Resistor:
    value: float
    tolerance: float

    def __init__(self, value: float, tolerance: float):
        self.value = value
        self.tolerance = tolerance
        
    def max(self) -> float:
        return self.value * (1 + self.tolerance)
    
    def min(self) -> float:
        return self.value * (1 - self.tolerance)

class Capacitor:
    value: float
    tolerance: float
        
    def __init__(self, value: float, tolerance: float):
        self.value = value
        self.tolerance = tolerance
        
    def max(self) -> float:
        return self.value * (1 + self.tolerance)
    
    def min(self) -> float:
        return self.value * (1 - self.tolerance)
from math import pow
from typing import Generator
r = (pow(10, x) for x in range(0, 6))
def cap_range(start, end, series) -> Generator[float, None, None]:
    return (round(x * n, 1) * 10e-12 for n in (pow(10, x) for x in range(start, end)) for x in list_e(series))
resistors = [ round(x * n, 1) for n in r for x in list_e(24)]
capacitors = sum([list(cap_range(1, 6, 6)), list(cap_range(6, 9, 3))], [])
resistor_tolerance = 0.05
capacitor_tolerance = 0.2

V = 5.0
limit_I_R1 = 2e-3
limit_I_R2 = 2e-3
R1_candidates = [ Resistor(value=r, tolerance=resistor_tolerance) for r in resistors if V / r <= limit_I_R1 ]
R2_candidates = [ Resistor(value=r, tolerance=resistor_tolerance) for r in resistors if V / r <= limit_I_R2 ]
T_charge_target = 10e-3
T_discharge_target = 10e-3
import dataclasses
from typing import NewType, List

@dataclasses.dataclass
class Parameters:
    c: Capacitor
    r1: Resistor
    r2: Resistor
    t_charge: float
    t_charge_error: float
    t_discharge: float
    t_discharge_error: float
    t_charge_min: float
    t_charge_max: float
    t_discharge_min: float
    t_discharge_max: float

ParametersList = NewType('ParametersList', List[Parameters])

def candidate_list(max_charge_time_error: float, max_discharge_time_error: float) -> ParametersList:
    return [
        Parameters(
            Capacitor(c, capacitor_tolerance),
            R1,
            R2,
            c * (R1.value + R2.value),
            c * (R1.value + R2.value) - T_charge_target,
            c * R2.value,
            c * R2.value - T_discharge_target,
            c * (1 - capacitor_tolerance) * (R1.min() + R2.min()),
            c * (1 + capacitor_tolerance) * (R1.max() + R2.max()),
            c * (1 - capacitor_tolerance) * R2.min(),
            c * (1 + capacitor_tolerance) * R2.max()
        )
        for R1 in R1_candidates
        for R2 in R2_candidates
        for c in capacitors
#         if abs(T_charge_target - c * (R1.value + R2.value)) < max_charge_time_error and abs(T_discharge_target - c * R2.value) < max_discharge_time_error
        if abs(T_charge_target - c * (1 - capacitor_tolerance) * (R1.min() + R2.min())) < max_charge_time_error and abs(T_discharge_target - c * (1 - capacitor_tolerance) * R2.min()) < max_discharge_time_error
    ]
candidated = candidate_list(0.001, 0.001)
candidated = [
    p for p in candidated
    if p.t_charge_min > T_charge_target and
    p.t_discharge_min > T_charge_target and
#     p.c.value > 100e-9 and
    True
]
candidated = sorted(candidated, key=lambda p: pow(p.t_charge_error, 2) + pow(p.t_discharge_error, 2))
import si_prefix

def format_resistor(r: Resistor) -> str:
    return f'{si_prefix.si_format(r.value, precision=1)}Ω, {si_prefix.si_format(r.min(), precision=1)}{si_prefix.si_format(r.max(), precision=1)}'

def format_capacitor(c: Capacitor) -> str:
    return f'{si_prefix.si_format(c.value, precision=1)}F, {si_prefix.si_format(c.min(), precision=1)}{si_prefix.si_format(c.max(), precision=1)}'

print(f"""
Constraints
===========
V = {si_prefix.si_format(V, precision=1)}V,
Target charging time = {si_prefix.si_format(T_charge_target, precision=3)}sec,
Target discharging time = {si_prefix.si_format(T_discharge_target, precision=3)}sec
Max I_R1 = {si_prefix.si_format(limit_I_R1, precision=3)}A
Max I_R2 = {si_prefix.si_format(limit_I_R2, precision=3)}A

Resistor tolerance = {resistor_tolerance * 100}%
Capacitor tolerance = {capacitor_tolerance * 100}%
=============================
""")
for i, p in ((i, x) for i, x in enumerate(candidated) if i < 10):
    c = format_capacitor(p.c)
    r1 = format_resistor(p.r1)
    r2 = format_resistor(p.r2)
    t_charge = f'{si_prefix.si_format(p.t_charge, precision=3)}s ({si_prefix.si_format(p.t_charge_error, precision=3)}s)'
    t_discharge = f'{si_prefix.si_format(p.t_discharge, precision=3)}s ({si_prefix.si_format(p.t_discharge_error, precision=3)}s)'
    t_charge_min = f'{si_prefix.si_format(p.t_charge_min, precision=3)}s'
    t_charge_max = f'{si_prefix.si_format(p.t_charge_max, precision=3)}s'
    t_discharge_min = f'{si_prefix.si_format(p.t_discharge_min, precision=3)}s'
    t_discharge_max = f'{si_prefix.si_format(p.t_discharge_max, precision=3)}s'
    
    msg = f"""
------------ {i+1} ------------
C = {c}
R1 = {r1}
R2 = {r2}
T_charge = {t_charge} {t_charge_min}{t_charge_max}
T_discharge = {t_discharge} {t_discharge_min}{t_discharge_max}
    """
    print(msg)
Constraints
===========
V = 5.0 V,
Target charging time = 10.000 msec,
Target discharging time = 10.000 msec
Max I_R1 = 2.000 mA
Max I_R2 = 2.000 mA

Resistor tolerance = 5.0%
Capacitor tolerance = 20.0%
=============================


------------ 1 ------------
C = 22.0 nF, 17.6 n~26.4 n
R1 = 2.7 kΩ, 2.6 k~2.8 k
R2 = 620.0 kΩ, 589.0 k~651.0 k
T_charge = 13.699 ms (3.699 ms) 10.412 ms~17.261 ms
T_discharge = 13.640 ms (3.640 ms) 10.366 ms~17.186 ms
    

------------ 2 ------------
C = 15.0 nF, 12.0 n~18.0 n
R1 = 2.7 kΩ, 2.6 k~2.8 k
R2 = 910.0 kΩ, 864.5 k~955.5 k
T_charge = 13.691 ms (3.690 ms) 10.405 ms~17.250 ms
T_discharge = 13.650 ms (3.650 ms) 10.374 ms~17.199 ms
    

------------ 3 ------------
C = 15.0 nF, 12.0 n~18.0 n
R1 = 3.0 kΩ, 2.9 k~3.1 k
R2 = 910.0 kΩ, 864.5 k~955.5 k
T_charge = 13.695 ms (3.695 ms) 10.408 ms~17.256 ms
T_discharge = 13.650 ms (3.650 ms) 10.374 ms~17.199 ms
    

------------ 4 ------------
C = 22.0 nF, 17.6 n~26.4 n
R1 = 3.0 kΩ, 2.9 k~3.1 k
R2 = 620.0 kΩ, 589.0 k~651.0 k
T_charge = 13.706 ms (3.706 ms) 10.417 ms~17.270 ms
T_discharge = 13.640 ms (3.640 ms) 10.366 ms~17.186 ms
    

------------ 5 ------------
C = 15.0 nF, 12.0 n~18.0 n
R1 = 3.3 kΩ, 3.1 k~3.5 k
R2 = 910.0 kΩ, 864.5 k~955.5 k
T_charge = 13.699 ms (3.699 ms) 10.412 ms~17.261 ms
T_discharge = 13.650 ms (3.650 ms) 10.374 ms~17.199 ms
    

------------ 6 ------------
C = 22.0 nF, 17.6 n~26.4 n
R1 = 3.3 kΩ, 3.1 k~3.5 k
R2 = 620.0 kΩ, 589.0 k~651.0 k
T_charge = 13.713 ms (3.713 ms) 10.422 ms~17.278 ms
T_discharge = 13.640 ms (3.640 ms) 10.366 ms~17.186 ms
    

------------ 7 ------------
C = 15.0 nF, 12.0 n~18.0 n
R1 = 3.6 kΩ, 3.4 k~3.8 k
R2 = 910.0 kΩ, 864.5 k~955.5 k
T_charge = 13.704 ms (3.704 ms) 10.415 ms~17.267 ms
T_discharge = 13.650 ms (3.650 ms) 10.374 ms~17.199 ms
    

------------ 8 ------------
C = 15.0 nF, 12.0 n~18.0 n
R1 = 3.9 kΩ, 3.7 k~4.1 k
R2 = 910.0 kΩ, 864.5 k~955.5 k
T_charge = 13.708 ms (3.708 ms) 10.418 ms~17.273 ms
T_discharge = 13.650 ms (3.650 ms) 10.374 ms~17.199 ms
    

------------ 9 ------------
C = 22.0 nF, 17.6 n~26.4 n
R1 = 3.6 kΩ, 3.4 k~3.8 k
R2 = 620.0 kΩ, 589.0 k~651.0 k
T_charge = 13.719 ms (3.719 ms) 10.427 ms~17.286 ms
T_discharge = 13.640 ms (3.640 ms) 10.366 ms~17.186 ms
    

------------ 10 ------------
C = 15.0 nF, 12.0 n~18.0 n
R1 = 4.3 kΩ, 4.1 k~4.5 k
R2 = 910.0 kΩ, 864.5 k~955.5 k
T_charge = 13.714 ms (3.714 ms) 10.423 ms~17.280 ms
T_discharge = 13.650 ms (3.650 ms) 10.374 ms~17.199 ms
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment