from math import log10, sqrt
E48 = [
1.00, 1.05, 1.10, 1.15, 1.21, 1.27, 1.33, 1.40,
1.47, 1.54, 1.62, 1.69, 1.78, 1.87, 1.96, 2.05,
2.15, 2.26, 2.37, 2.49, 2.61, 2.74, 2.87, 3.01,
3.16, 3.32, 3.48, 3.65, 3.83, 4.02, 4.22, 4.42,
4.64, 4.87, 5.11, 5.36, 5.62, 5.90, 6.19, 6.49,
6.81, 7.15, 7.50, 7.87, 8.25, 8.66, 9.09, 9.53
]
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
]
E12 = E24 [0:24:2]
def choose_best (value, res_values):
best = None
for p in range (6):
for ent in res_values:
resistor = ent * pow(10, p)
if best is None or abs(value-best) > abs(value-resistor):
best = resistor
return best
def dB_2_ratio(dB):
return pow(10.0, dB/20.0)
def ratio_2_dB(num, denom):
return 20.0 * log10 (num / denom)
def calc_loaded_resistances (total, load, ratio):
# Split a total resistance for a given voltage ratio when loaded by load - quadratic solving
a = -ratio
b = ratio * total - load
c = ratio * total * load
temp = b*b - 4*a*c
lower = (-b - sqrt(temp)) / (2*a)
upper = total - lower
return upper, lower
def parallel (r1, r2):
# utility fn for combining impedances
return r1 * r2 / (r1 + r2)
def calculate_steps(count, step, resistance, res_values, load = 47000.0):
# first calculate ideal resistances in chain
target_ratio = 1.0
ideal_resistors = []
last_upper = 0.0
for i in range(1, count):
target_ratio /= dB_2_ratio (step)
upper, lower = calc_loaded_resistances (resistance, load, target_ratio)
ideal_resistors.append (upper - last_upper)
last_upper = upper
# fit closest available values
actual_resistors = []
for i in range (1, count):
actual_resistors.append (choose_best (ideal_resistors[i-1], res_values))
actual_resistors.append (choose_best (lower, res_values))
# calculate actual attenuation factors, loaded or unloaded
total = 0.0
remaining_resistance = sum (actual_resistors)
i = 1
for act in actual_resistors:
atten = ratio_2_dB (parallel (remaining_resistance, load), total + parallel (remaining_resistance, load))
unload_atten = ratio_2_dB (remaining_resistance, remaining_resistance + total)
print ("%s: %6.2f ohms %5.2f dB loaded by %i, %5.2f dB unloaded" % (i, act, atten, load, unload_atten))
total += act
remaining_resistance -= act
i += 1
print ("total %6.1f ohms" % total)
calculate_steps (32, 2, 50000, E48+E24)
# calculate_steps (32, 2, 50000, E24)