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)
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.
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)
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
- Status
- This old topic is closed. If you want to reopen this topic, contact a moderator using the "Report Post" button.
- Home
- Design & Build
- Parts
- Series Type Stepped Attenuators