I want to build a 32 steps series attenuator but can't find a spreadsheet for calculating the resistor values. Goldpoint only have the values for 24 steps. Could anyone help please?
Please also recommend the brand / type resistor for the attenuator. Is SMD type resistor good?
Please also recommend the brand / type resistor for the attenuator. Is SMD type resistor good?
Code:
1: 10500.00 ohms -2.05 dB
2: 8200.00 ohms -4.07 dB
3: 6490.00 ohms -6.09 dB
4: 5100.00 ohms -8.09 dB
5: 4020.00 ohms -10.07 dB
6: 3160.00 ohms -12.02 dB
7: 2610.00 ohms -14.05 dB
8: 2050.00 ohms -16.06 dB
9: 1620.00 ohms -18.06 dB
10: 1300.00 ohms -20.09 dB
11: 1000.00 ohms -22.05 dB
12: 820.00 ohms -24.07 dB
13: 649.00 ohms -26.09 dB
14: 510.00 ohms -28.09 dB
15: 402.00 ohms -30.07 dB
16: 316.00 ohms -32.02 dB
17: 261.00 ohms -34.05 dB
18: 205.00 ohms -36.06 dB
19: 162.00 ohms -38.06 dB
20: 130.00 ohms -40.09 dB
21: 100.00 ohms -42.05 dB
22: 82.00 ohms -44.07 dB
23: 64.90 ohms -46.09 dB
24: 51.00 ohms -48.09 dB
25: 40.20 ohms -50.07 dB
26: 31.60 ohms -52.02 dB
27: 26.10 ohms -54.05 dB
28: 20.50 ohms -56.06 dB
29: 16.20 ohms -58.06 dB
30: 13.00 ohms -60.09 dB
31: 10.00 ohms -62.05 dB
32: 39.00 ohms to ground
total 49960.5 ohms
Code:
from math import log10
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):
best = None
for p in range (6):
for ent in E48:
resistor = ent * pow(10, p)
if best is None or abs(value-best) > abs(value-resistor):
best = resistor
for ent in E24:
resistor = ent * pow(10, p)
if best is None or abs(value-best) > abs(value-resistor):
best = resistor
return best
TOTAL_RESISTANCE = 50000
STEP = 2.0
STEP_COUNT = 32
def dB_2_ratio(dB):
return pow(10.0, dB/20.0)
def calculate_steps(count, step, resistance):
total = 0.0
remaining_resistance = resistance
target_resistance = resistance
for i in range(1, count):
target_resistance = remaining_resistance / dB_2_ratio (step)
ideal_resistor = remaining_resistance - target_resistance
actual_resistor = choose_best (ideal_resistor)
total += actual_resistor
remaining_resistance -= actual_resistor
atten = 20.0 * log10 (remaining_resistance / resistance)
print ("%s: %6.2f ohms %5.2f dB" % (i, actual_resistor, atten))
print ("%s: %6.2f ohms to ground" % (count, choose_best (remaining_resistance)))
print ("total %6.1f ohms" % total)
calculate_steps (STEP_COUNT, STEP, TOTAL_RESISTANCE)
BTW thin-film SMT are metal film, which are the most linear, but usually more expensive.
My code uses both E48 and E24 values, which might be an issue, can easily rework it.
My code uses both E48 and E24 values, which might be an issue, can easily rework it.
Loaded or unloaded?
A 100k pot is likely to be "loaded" in most systems unless a high-Z buffer is right after it.
For UN-loaded: re-write your dB as voltages. 0 -2 -4 -6 -8... becomes 0 0.794 0.631 0.501 0.398...
Say 100k. Then from -2dB tap to ground must be 100k*0.794 or 79.4k, and the 0 to -2 resistor must be 100k-79.4k or 20.6k. Go on from there.
Some cheats and checks. -6(.02)dB is half. So you know the sum of resistors above -6 must be 50k, and the sum below -6 must be 50k. Likewise -20 is 1/10 so top is 90k and bottom is 10k; -40dB is 1/100 so top must be 99k and bottom is 1k.
A 100k pot is likely to be "loaded" in most systems unless a high-Z buffer is right after it.
For UN-loaded: re-write your dB as voltages. 0 -2 -4 -6 -8... becomes 0 0.794 0.631 0.501 0.398...
Say 100k. Then from -2dB tap to ground must be 100k*0.794 or 79.4k, and the 0 to -2 resistor must be 100k-79.4k or 20.6k. Go on from there.
Some cheats and checks. -6(.02)dB is half. So you know the sum of resistors above -6 must be 50k, and the sum below -6 must be 50k. Likewise -20 is 1/10 so top is 90k and bottom is 10k; -40dB is 1/100 so top must be 99k and bottom is 1k.
Unloaded, its just a discretized potentiometer. I'll add a load resistance option defaulting to 47k.
Code:
1: 5900.00 ohms 0.00 dB loaded by 47000, 0.00 dB unloaded
2: 6490.00 ohms -2.00 dB loaded by 47000, -1.09 dB unloaded
3: 6490.00 ohms -4.03 dB loaded by 47000, -2.46 dB unloaded
4: 6190.00 ohms -6.04 dB loaded by 47000, -4.10 dB unloaded
5: 5360.00 ohms -8.07 dB loaded by 47000, -6.01 dB unloaded
6: 4420.00 ohms -10.07 dB loaded by 47000, -8.09 dB unloaded
7: 3480.00 ohms -12.07 dB loaded by 47000, -10.29 dB unloaded
8: 2700.00 ohms -14.06 dB loaded by 47000, -12.52 dB unloaded
9: 2050.00 ohms -16.05 dB loaded by 47000, -14.76 dB unloaded
10: 1600.00 ohms -18.02 dB loaded by 47000, -16.96 dB unloaded
11: 1210.00 ohms -20.04 dB loaded by 47000, -19.17 dB unloaded
12: 953.00 ohms -22.02 dB loaded by 47000, -21.32 dB unloaded
13: 715.00 ohms -24.05 dB loaded by 47000, -23.49 dB unloaded
14: 562.00 ohms -26.02 dB loaded by 47000, -25.57 dB unloaded
15: 442.00 ohms -28.01 dB loaded by 47000, -27.64 dB unloaded
16: 348.00 ohms -30.00 dB loaded by 47000, -29.72 dB unloaded
17: 270.00 ohms -32.02 dB loaded by 47000, -31.79 dB unloaded
18: 215.00 ohms -34.01 dB loaded by 47000, -33.82 dB unloaded
19: 169.00 ohms -36.02 dB loaded by 47000, -35.87 dB unloaded
20: 133.00 ohms -38.03 dB loaded by 47000, -37.92 dB unloaded
21: 105.00 ohms -40.04 dB loaded by 47000, -39.95 dB unloaded
22: 82.50 ohms -42.04 dB loaded by 47000, -41.97 dB unloaded
23: 64.90 ohms -44.03 dB loaded by 47000, -43.97 dB unloaded
24: 51.10 ohms -46.01 dB loaded by 47000, -45.96 dB unloaded
25: 42.20 ohms -47.96 dB loaded by 47000, -47.92 dB unloaded
26: 33.00 ohms -49.99 dB loaded by 47000, -49.96 dB unloaded
27: 26.10 ohms -52.00 dB loaded by 47000, -51.97 dB unloaded
28: 20.50 ohms -54.00 dB loaded by 47000, -53.98 dB unloaded
29: 16.20 ohms -55.98 dB loaded by 47000, -55.96 dB unloaded
30: 13.00 ohms -57.94 dB loaded by 47000, -57.93 dB unloaded
31: 10.50 ohms -59.92 dB loaded by 47000, -59.91 dB unloaded
32: 40.20 ohms -61.94 dB loaded by 47000, -61.93 dB unloaded
total 50202.2 ohms
Code:
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)
Wow I use the same Shallco but mine is motorized with only 32 steps. I believe is the best switch money can buy.
@Mark Tillotson
Mark, your code is excellent and very easy to change the parameters. Thanks a lot.
Mark, your code is excellent and very easy to change the parameters. Thanks a lot.
Why? What makes it so good?Wow I use the same Shallco but mine is motorized with only 32 steps. I believe is the best switch money can buy.
Genuinely interested
> What makes it so good?
The Shallcross/Shallco (and another brand, Daven, also IRC) were PROFESSIONAL attenuators invented in the 1930s for talking-movie and broadcast applications, where reliability was more important than the cost. Find pictures online. Solid contacts with selected metal plating, real springs, solid wafers.
http://www.technicalaudio.com/pdf/Daven/Daven_attenuator_switch_lab_Catalog.pdf
The Shallcross/Shallco (and another brand, Daven, also IRC) were PROFESSIONAL attenuators invented in the 1930s for talking-movie and broadcast applications, where reliability was more important than the cost. Find pictures online. Solid contacts with selected metal plating, real springs, solid wafers.
http://www.technicalaudio.com/pdf/Daven/Daven_attenuator_switch_lab_Catalog.pdf
@Mark Tillotson
Mark, your code is excellent and very easy to change the parameters. Thanks a lot.
I found the loaded case is a little trickier as a quadratic has to be solved, but you should do your mental pressups regularly, algebra, coding, whatever. 🙂
Motorised!! Can mine be modified?
I don't know, it's 23 steps (I'm sorry my mistake), I bought mine here: BentAudio.com :: TAP
- Home
- Design & Build
- Parts
- Series Type Stepped Attenuators