{ "cells": [ { "cell_type": "code", "execution_count": 354, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import math\n", "import statistics\n", "from itertools import product\n", "\n", "from tabulate import tabulate\n", "\n", "from IPython.core.display import display, HTML" ] }, { "cell_type": "code", "execution_count": 235, "metadata": {}, "outputs": [], "source": [ "e3 = np.array([1.0, 2.2, 4.7])\n", "e6 = np.array([1.0, 1.5, 2.2, 3.3, 4.7, 6.8])\n", "e12 = np.array([1.0, 1.2, 1.5, 1.8, 2.2, 2.7, 3.3, 3.9, 4.7, 5.6, 6.8, 8.2])\n", "e24 = np.array([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])\n", "e48 = np.array([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])\n", "e96 = np.array([1.00, 1.02, 1.05, 1.07, 1.10, 1.13, 1.15, 1.18, 1.21, 1.24, 1.27, 1.30, 1.33, 1.37, 1.40, 1.43, 1.47, 1.50, 1.54, 1.58, 1.62, 1.65, 1.69, 1.74, 1.78, 1.82, 1.87, 1.91, 1.96, 2.00, 2.05, 2.10, 2.15, 2.21, 2.26, 2.32, 2.37, 2.43, 2.49, 2.55, 2.61, 2.67, 2.74, 2.80, 2.87, 2.94, 3.01, 3.09, 3.16, 3.24, 3.32, 3.40, 3.48, 3.57, 3.65, 3.74, 3.83, 3.92, 4.02, 4.12, 4.22, 4.32, 4.42, 4.53, 4.64, 4.75, 4.87, 4.99, 5.11, 5.23, 5.36, 5.49, 5.62, 5.76, 5.90, 6.04, 6.19, 6.34, 6.49, 6.65, 6.81, 6.98, 7.15, 7.32, 7.50, 7.68, 7.87, 8.06, 8.25, 8.45, 8.66, 8.87, 9.09, 9.31, 9.53, 9.76])\n", "e192 = np.array([1.00, 1.01, 1.02, 1.04, 1.05, 1.06, 1.07, 1.09, 1.10, 1.11, 1.13, 1.14, 1.15, 1.17, 1.18, 1.20, 1.21, 1.23, 1.24, 1.26, 1.27, 1.29, 1.30, 1.32, 1.33, 1.35, 1.37, 1.38, 1.40, 1.42, 1.43, 1.45, 1.47, 1.49, 1.50, 1.52, 1.54, 1.56, 1.58, 1.60, 1.62, 1.64, 1.65, 1.67, 1.69, 1.72, 1.74, 1.76, 1.78, 1.80, 1.82, 1.84, 1.87, 1.89, 1.91, 1.93, 1.96, 1.98, 2.00, 2.03, 2.05, 2.08, 2.10, 2.13, 2.15, 2.18, 2.21, 2.23, 2.26, 2.29, 2.32, 2.34, 2.37, 2.40, 2.43, 2.46, 2.49, 2.52, 2.55, 2.58, 2.61, 2.64, 2.67, 2.71, 2.74, 2.77, 2.80, 2.84, 2.87, 2.91, 2.94, 2.98, 3.01, 3.05, 3.09, 3.12, 3.16, 3.20, 3.24, 3.28, 3.32, 3.36, 3.40, 3.44, 3.48, 3.52, 3.57, 3.61, 3.65, 3.70, 3.74, 3.79, 3.83, 3.88, 3.92, 3.97, 4.02, 4.07, 4.12, 4.17, 4.22, 4.27, 4.32, 4.37, 4.42, 4.48, 4.53, 4.59, 4.64, 4.70, 4.75, 4.81, 4.87, 4.93, 4.99, 5.05, 5.11, 5.17, 5.23, 5.30, 5.36, 5.42, 5.49, 5.56, 5.62, 5.69, 5.76, 5.83, 5.90, 5.97, 6.04, 6.12, 6.19, 6.26, 6.34, 6.42, 6.49, 6.57, 6.65, 6.73, 6.81, 6.90, 6.98, 7.06, 7.15, 7.23, 7.32, 7.41, 7.50, 7.59, 7.68, 7.77, 7.87, 7.96, 8.06, 8.16, 8.25, 8.35, 8.45, 8.56, 8.66, 8.76, 8.87, 8.98, 9.09, 9.20, 9.31, 9.42, 9.53, 9.65, 9.76, 9.88])\n", "\n", "def decades(series, n):\n", " return np.hstack([series*(10**i) for i in range(n)] + [10**n])" ] }, { "cell_type": "code", "execution_count": 232, "metadata": {}, "outputs": [], "source": [ "def r_ratio(Utot, U2):\n", " return Utot/U2 - 1" ] }, { "cell_type": "code", "execution_count": 242, "metadata": {}, "outputs": [], "source": [ "def check_ratios(Utot, U2, series=e24, tolerance=0.01):\n", " values = decades(series, 7)\n", " ratios = np.outer(values, 1/values)\n", " target_ratio = r_ratio(Utot, U2)\n", " found = np.where(np.abs(1 - ratios/target_ratio) < tolerance)\n", " return list(zip(values[found[0]], values[found[1]])), np.abs(1 - ratios/target_ratio)" ] }, { "cell_type": "code", "execution_count": 355, "metadata": {}, "outputs": [], "source": [ "def par(a, b):\n", " return 1/(1/a + 1/b)" ] }, { "cell_type": "code", "execution_count": 414, "metadata": {}, "outputs": [], "source": [ "def sig_round(val, ndigits):\n", " log = math.floor(math.log10(val))\n", " return round(val/(10**log), ndigits) * (10**log)" ] }, { "cell_type": "code", "execution_count": 430, "metadata": {}, "outputs": [], "source": [ "def crossref_ratios(Utots, U2, offx=0, series=e24, allow_parallel=False):\n", " values = e24_n_decades(7)\n", " par_map = { sig_round(par(a, b), 4): (a, b) for a, b in product(values, values) }\n", " for val in values:\n", " if val in par_map:\n", " del par_map[val]\n", " par_arr = np.array(list(par_map.keys()) + list(values))\n", " if allow_parallel:\n", " values_com = par_arr + offx/2\n", " else:\n", " values_com = values + offx/2\n", " values_choice = values + offx\n", " ratios = np.outer(values_choice, 1/values_com)\n", " target_ratios = [ r_ratio(Utot, U2) for Utot in Utots ]\n", " deltas = np.array([ np.abs(1 - ratios/target_ratio) for target_ratio in target_ratios])\n", "\n", " deltas_x = deltas #[:,:,:len(series)]\n", " idx_x, mins_x = deltas_x.argmin(axis=1), deltas_x.min(axis=1)\n", " #errs_out_x = np.array([elem.dot(elem) for elem in np.swapaxes(mins_x, 0, 1)])\n", " errs_out_x = mins_x.max(axis=0)\n", " best_x = [ (errs_out_x[j], list(mins_x[:,j]), list(values_choice[idx_x[:,j]]), values_com[j]) for j in np.argsort(errs_out_x) ]\n", "\n", " deltas_y = deltas #[:,:len(series),:]\n", " idx_y, mins_y = deltas_y.argmin(axis=2), deltas_y.min(axis=2)\n", " #errs_out_y = np.array([elem.dot(elem) for elem in np.swapaxes(mins_y, 0, 1)])\n", " errs_out_y = mins_y.max(axis=0)\n", " best_y = [ (errs_out_y[j], list(mins_y[:,j]), list(values_com[idx_y[:,j]]), values_choice[j]) for j in np.argsort(errs_out_y) ]\n", " \n", " return sorted(best_x), sorted(best_y), par_map" ] }, { "cell_type": "code", "execution_count": 443, "metadata": { "scrolled": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "R1 fixed, R2 choices\n" ] }, { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
R1 (3.8V) R1 (5.0V) R1 (12V) R2 Δ R total (min) R total (max) Iq
1.60M 2.20M 5.60M 300k 0.00%, 0.00%, 1.75% 1.90M 5.90M 2.01μA
160k 220k 560k 30.0k0.00%, 0.00%, 1.75% 190k 590k 20.1μA
360k 510k 1.30M 68.0k0.74%, 2.27%, 0.62% 428k 1.37M 8.77μA
180k 240k 620k 33.0k2.27%, 0.83%, 1.12% 213k 653k 18.2μA
1.80M 2.40M 6.20M 330k 2.27%, 0.83%, 1.12% 2.13M 6.53M 1.82μA
1.20M 1.60M 4.30M 220k 2.27%, 0.83%, 2.87% 1.42M 4.52M 2.69μA
120k 160k 430k 22.0k2.27%, 0.83%, 2.87% 142k 452k 26.9μA
130k 180k 470k 24.0k1.56%, 2.27%, 3.07% 154k 494k 24.5μA
1.30M 1.80M 4.70M 240k 1.56%, 2.27%, 3.07% 1.54M 4.94M 2.45μA
430k 620k 1.60M 82.0k1.68%, 3.10%, 2.70% 512k 1.68M 7.23μA
110k 150k 390k 20.0k3.13%, 2.27%, 2.63% 130k 410k 29.3μA
1.10M 1.50M 3.90M 200k 3.13%, 2.27%, 2.63% 1.30M 4.10M 2.93μA
330k 470k 1.20M 62.0k0.20%, 3.37%, 1.87% 392k 1.26M 9.53μA
620k 910k 2.20M 120k 3.12%, 3.41%, 3.51% 740k 2.32M 5.05μA
270k 360k 1.00M 51.0k0.74%, 3.74%, 3.20% 321k 1.05M 11.8μA
820k 1.20M 3.00M 160k 3.91%, 2.27%, 1.32% 980k 3.16M 3.78μA
470k 680k 1.80M 91.0k3.16%, 1.90%, 4.11% 561k 1.89M 6.53μA
1.50M 2.00M 5.10M 270k 4.17%, 1.01%, 0.58% 1.77M 5.37M 2.19μA
150k 200k 510k 27.0k4.17%, 1.01%, 0.58% 177k 537k 21.9μA
100k 130k 330k 18.0k4.17%, 1.52%, 3.51% 118k 348k 33.5μA
1.00M 1.30M 3.30M 180k 4.17%, 1.52%, 3.51% 1.18M 3.48M 3.35μA
200k 270k 680k 36.0k4.17%, 2.27%, 0.58% 236k 716k 16.4μA
2.00M 2.70M 6.80M 360k 4.17%, 2.27%, 0.58% 2.36M 7.16M 1.64μA
240k 330k 910k 47.0k4.26%, 4.26%, 1.90%287k 957k 13.0μA
2.40M 3.30M 9.10M 470k 4.26%, 4.26%, 1.90%2.87M 9.57M 1.30μA
680k 910k 2.40M 130k 1.92%, 4.55%, 2.83% 810k 2.53M 4.75μA
560k 820k 2.00M 110k 4.55%, 1.65%, 4.31% 670k 2.11M 5.58μA
220k 330k 820k 43.0k4.07%, 4.65%, 0.37% 263k 863k 13.9μA
2.20M 3.30M 8.20M 430k 4.07%, 4.65%, 0.37% 2.63M 8.63M 1.39μA
300k 430k 1.10M 56.0k0.45%, 4.71%, 3.38% 356k 1.16M 10.4μA
200k 300k 750k 39.0k3.85%, 4.90%, 1.21% 239k 789k 15.3μA
2.00M 3.00M 7.50M 390k 3.85%, 4.90%, 1.21% 2.39M 7.89M 1.53μA
820k 1.10M 3.00M 150k 2.50%, 0.00%, 5.26% 970k 3.15M 3.91μA
390k 560k 1.50M 75.0k2.50%, 1.82%, 5.26% 465k 1.57M 7.89μA
510k 750k 2.00M 100k 4.38%, 2.27%, 5.26% 610k 2.10M 5.94μA
2.70M 3.60M 9.10M 510k 0.74%, 3.74%, 6.09% 3.21M 9.61M 1.22μA
3.00M 4.30M 9.10M 560k 0.45%, 4.71%, 14.47% 3.56M 9.66M 1.11μA
3.30M 4.70M 9.10M 620k 0.20%, 3.37%, 22.75% 3.92M 9.72M 1.05μA
3.60M 5.10M 9.10M 680k 0.74%, 2.27%, 29.57% 4.28M 9.78M 993nA
3.90M 5.60M 9.10M 750k 2.50%, 1.82%, 36.14% 4.65M 9.85M 941nA
4.30M 6.20M 9.10M 820k 1.68%, 3.10%, 41.59% 5.12M 9.92M 888nA
4.70M 6.80M 9.10M 910k 3.16%, 1.90%, 47.37% 5.61M 10.0M 842nA
5.10M 7.50M 9.10M 1.00M4.38%, 2.27%, 52.11% 6.10M 10.1M 800nA
5.60M 8.20M 9.10M 1.10M4.55%, 1.65%, 56.46% 6.70M 10.2M 760nA
6.20M 9.10M 9.10M 1.20M3.12%, 3.41%, 60.09% 7.40M 10.3M 721nA
6.80M 9.10M 9.10M 1.30M1.92%, 4.55%, 63.16% 8.10M 10.4M 701nA
8.20M 9.10M 9.10M 1.50M2.50%, 17.27%, 68.07% 9.70M 10.6M 665nA
8.20M 9.10M 9.10M 1.60M3.91%, 22.44%, 70.07% 9.80M 10.7M 659nA
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "Utots = [3.8, 5, 12]\n", "U2 = 0.6\n", "series = e48\n", "r_tot_min, r_tot_max = 100e3, 10e6\n", "\n", "si_prefix = ['y', 'z', 'a', 'f', 'p', 'n', 'μ', 'm', '', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y']\n", "def format_si(val, digits=2, suffix='', unity_prefix=''):\n", " mul = math.floor(math.log10(val))\n", " prefixes = [prefix or unity_prefix for prefix in si_prefix]\n", " prefix = prefixes[min(len(si_prefix)-1, max(0, si_prefix.index('') + mul//3))]\n", " le_format = f'{{:.{digits-mul%3}f}}{{}}{{}}'\n", " return le_format.format(val/(10**(mul//3*3)), prefix, suffix)\n", "format_r = lambda val, digits=2: format_si(val, digits=digits, unity_prefix='R')\n", "\n", "com = 'low'\n", "#com ='high'\n", "\n", "data = []\n", "best_x, best_y, par_map = crossref_ratios(Utots, U2, series=series, allow_parallel=False)\n", "print('R1 fixed, R2 choices')\n", "for _acc, deltas, r1_vals, r2 in best_x if com == 'low' else best_y:\n", " if len(data) >= 50:\n", " break\n", " \n", " r_tots = [ r1+r2 for r1 in r1_vals ]\n", " iqs = [u/(r1+r2) for r1, u in zip(r1_vals, Utots)]\n", " iq = statistics.mean(iqs)\n", " #if min(r_tots) > r_tot_max or max(r_tots) < r_tot_min:\n", " \n", " if not r_tot_min < min(r_tots) < r_tot_max:\n", " continue\n", " \n", " r1_vals = [ format_r(val) for val in r1_vals ]\n", " deltas = [ f'{d:.2%}' for d in deltas ]\n", " deltas = [ f'{d}' if d == max(deltas) else d for d in deltas ]\n", " data.append((\n", " *r1_vals,\n", " f'{format_r(par_map[r2][0])} || {format_r(par_map[r2][1])}' if r2 in par_map else f'{format_r(r2)}',\n", " f'{\", \".join(deltas)}',\n", " f'{format_r(min(r_tots))}', f'{format_r(max(r_tots))}',\n", " f'{format_si(iq, suffix=\"A\")}'))\n", "s, c = (1,2) if com == 'low' else (2,1)\n", "display(HTML(tabulate(data, [*[ f'R{s} ({format_si(u, suffix=\"V\", digits=1)})' for u in Utots ], f'R{c}', 'Δ', 'R total (min)', 'R total (max)', 'Iq'], tablefmt='html')))" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.8" } }, "nbformat": 4, "nbformat_minor": 2 }