I’m finally learning the electronics that I should of learned 40 years ago. I did a bunch of Heathkit projects (Heathkit is still around but a shadow of their previous selves.) including my entire stereo system but I never delved too deeply into the theory of how the circuits worked. So now I’m back studying circuit theory, operational amplifiers, first-order filters, and an entire zoo of 21st century electronics design. (That integrated circuit does ALL of that!?!)
Having designed a UV densitometer for my photographic work I’m already thinking about a second, more sophisticated, version. I’m also wanting to explore musical vibrato from the standpoint of what repetition and depth frequencies people find pleasing. Both of these will require some careful design work.
One thing I’ve already had to deal with is non-standard resistor values. When working with operational amplifiers there are sets of equations used to calculate resistor or capacitor values. Since I have a bigger collection of resistors than capacitors it’s easier for me to fix the capacitor value and calculate the resistor value(s) I need. Of course these calculated values are generally no where near the standard resistor values. Figuring out which combination of resistors will get you closest to 27,658 ohms gets very tedious. So being a retired programmer I did what any programmer would do . . . I wrote a python script to find the combinations for me. (View the source code here.)
A note to any programmers who may look at this code.
I don’t care that I’m not using some latest-greatest, neat-oh-bleet-oh Python 3.x feature. I don’t care that there’s a “better way” to do this or that there’s a more “acceptable” way. I’m a RETIRED programmer. This is for my amusement and if you find any part of this useful all the better.
The script accepts the target resistance and a percentage tolerance and looks for either three resistors in series and two resistors in parallel plus a series resistor whose value is within the percentage tolerance provided. Running the script without arguments and with the ‘-h’ option gives the following expected output:
wemrt% ./r_finder.py usage: r_finder.py [-h] [--record] resistance tolerance r_finder.py: error: the following arguments are required: resistance, tolerance wemrt% ./r_finder.py -h usage: r_finder.py [-h] [--record] resistance tolerance positional arguments: resistance resistance in ohms e.g. 1000000 not 1M tolerance percent tolerance e.g. 5 not 0.05 optional arguments: -h, --help show this help message and exit --record If provided write results to r_finder.dat
Running the script with the 27,658 ohm value mentioned above at a tolerance of 5% produces:
wemrt% ./r_finder.py 27658 5 Target resistance: 27658 ohms Acceptable range: 26275.100000 to 29040.900000 ohms Series Solution Resistor 1: 27000 ohms Resistor 2: 560 ohms Resistor 3: 82 ohms Parallel/Series Solution First resistor: 33000 ohms Parallel resistor: 150000 ohms Network value: 27049.18 ohms Serial resistor: 1800 ohms Series Solution: 27642.00 ohms at 0.06% Parallel Solution: 28849.18 ohms at 4.31%
at very low resistance values there may not be a good serial solution but a parallel solution exists:
wemrt% ./r_finder.py 89 5.0 Target resistance: 89 ohms Acceptable range: 84.550000 to 93.450000 ohms Series Solution Resistor 1: 82 ohms No resistor found less than 7 ohms. No solution found with tolerance 5.00% Parallel/Series Solution First resistor: 100 ohms Parallel resistor: 680 ohms Network value: 87.18 ohms No serial resistor found. Series Solution: 82.00 ohms at 7.87% Parallel Solution: 87.18 ohms at 2.05%
and at very large resistance values there may not be a good parallel solution:
wemrt% ./r_finder.py 1432947 5.0 Target resistance: 1432947 ohms Acceptable range: 1361299.650000 to 1504594.350000 ohms Series Solution Resistor 1: 1200000 ohms Resistor 2: 220000 ohms Resistor 3: 12000 ohms Parallel/Series Solution First resistor: 1500000 ohms Parallel resistor not found. Series Solution: 1432000.00 ohms at 0.07% Parallel Solution: 1500000.00 ohms at 4.68%
In order to see the behavior of this script I wrote a driver to generate test cases that used the –record option to capture the solutions found. The driver accepted a starting resistance, ending resistance, increment, and percentage tolerance generating a file looking like:
#!/bin/sh ./r_finder.py 2000 5.000000 --record > /dev/null 2>&1 ./r_finder.py 4000 5.000000 --record > /dev/null 2>&1 ./r_finder.py 6000 5.000000 --record > /dev/null 2>&1 ./r_finder.py 8000 5.000000 --record > /dev/null 2>&1
The output from running these commands was fed into R and plotted:
Obviously there’s jitter in the solutions but raising the resolution to every 50 ohms to 100,000 ohms gives a more interesting plot:
The serial solution will (almost) always beat the parallel solution but the periodicity of the solutions is interesting. Of course the final decision as to which solution to use depends on the sensitivity of the circuit, availability of parts, and possibly even the amount of space available on the PCB board.