-
-
Save mattmelling/cecedfbd1f0b889f33e08281be37cc9f to your computer and use it in GitHub Desktop.
Magnetic Loop Switch Capacitor Bank calculator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import math | |
| variable = (10, 150) | |
| targets = { | |
| 40: (189, 206), | |
| 30: (93.7, 94.8), | |
| 20: (42.8, 45.4), | |
| 17: (23.7, 24), | |
| 15: (14.7, 15.7), | |
| 12: (8.69, 8.83) | |
| } | |
| capacitances = [ | |
| 0, | |
| 10, | |
| 12, | |
| 15, | |
| 22, | |
| 33, | |
| 47, | |
| 56, | |
| 68, | |
| 82, | |
| 100, | |
| 120, | |
| 150, | |
| 180, | |
| 220, | |
| 330, | |
| 470, | |
| 680 | |
| ] | |
| def p_c(c): | |
| """ | |
| Calculate parallel capacitance interval given fixed value | |
| """ | |
| return (variable[0] + c, variable[1] + c) | |
| def s_c(p, s): | |
| """ | |
| Calculate series capacitance interval given series/parallel values | |
| """ | |
| p_i = p_c(p) | |
| try: | |
| return ( | |
| 1 / ((1 / p_i[0]) + (1 / s)), | |
| 1 / ((1 / p_i[1]) + (1 / s)), | |
| ) | |
| except ZeroDivisionError: | |
| return (0, 0) | |
| def add_tolerance(rng, amount): | |
| """ | |
| Adds amount tolerance to (min, max) range specified in rng | |
| """ | |
| mn, mx = rng | |
| return ( | |
| mn - (mn * amount), | |
| mx + (mx * amount) | |
| ) | |
| def pf(v): | |
| return f'{v:.2f}pF' | |
| def pfs(v): | |
| return f'{pf(v[0])}, {pf(v[1])}' | |
| def compute_optimum(target): | |
| # # Target capacitance range | |
| # target = add_tolerance(targets[20], 0.1) | |
| # Optimum setting for (parallel, series) capacitance | |
| optimum = (0, 0) | |
| # Error computed from last optimum | |
| error = 99999.9 | |
| for p in capacitances: | |
| for s in capacitances: | |
| # Calculate range of capacitance given (p, s) | |
| c = s_c(p, s) | |
| # Compute differences from target capacitance | |
| d_min = target[0] - c[0] # Delta from min | |
| d_max = target[1] - c[1] # Delta from max | |
| # The minimum should be less than target minimum | |
| if d_min < 0: | |
| continue | |
| # Maximum should be greater than target maximum | |
| if d_max > 0: | |
| continue | |
| # Calculate root mean square error | |
| e = ( | |
| math.sqrt(math.pow(target[0] - c[0], 2)) | |
| + math.sqrt(math.pow(target[1] - c[1], 2)) | |
| ) / 2 | |
| print(f'Testing {pfs((p, s))}') | |
| print(f' Target: {pfs(target)}') | |
| print(f' Range: {pfs(c)}') | |
| print(f' Error: {e:.4f}') | |
| if e < error: | |
| print(f'*** New optimium: {(p, s)}') | |
| optimum = (p, s) | |
| error = e | |
| print(f'Optimum settings: {optimum}') | |
| return optimum | |
| results = {} | |
| for band in targets.keys(): | |
| print(band) | |
| results[band] = compute_optimum(add_tolerance(targets[band], 0.1)) | |
| required_values = {} | |
| print() | |
| print('*** Results ***') | |
| print(f'{'Band':<10}{'Target':<25}{'Parallel':<15}{'Series':<15}{'Actual':<25}{'Range':<15}{'Deg/pF':<15}') | |
| for band in results.keys(): | |
| p, s = results[band] | |
| if p > 0: | |
| required_values[p] = required_values.get(p, 0) + 1 | |
| if s > 0: | |
| required_values[s] = required_values.get(s, 0) + 1 | |
| c = s_c(p, s) | |
| rng = c[1] - c[0] | |
| if rng == 0: | |
| rng = variable[1] - variable[0] | |
| deg_per_pf = f'{360 / rng:.2f}' | |
| print(f'{f'{band}m':<10}{pfs(targets[band]):<25}{pf(p):<15}{pf(s):<15}{pfs(c):<25}{pf(rng):<15}{deg_per_pf:<15}') | |
| print() | |
| print("*** BOM ***") | |
| print(f'{'Value':<15}{'Quantity':<15}') | |
| for c in sorted(required_values.keys()): | |
| print(f'{pf(c):<15}{required_values[c]:<15}') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment