From 1ce02a9d25a943ab90c819d23c4d0bbed684eba4 Mon Sep 17 00:00:00 2001 From: jaseg Date: Fri, 13 Oct 2023 18:22:00 +0200 Subject: Update sims & gen --- coil_test_board.py | 142 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 93 insertions(+), 49 deletions(-) (limited to 'coil_test_board.py') diff --git a/coil_test_board.py b/coil_test_board.py index ddab2ae..eaafbd2 100644 --- a/coil_test_board.py +++ b/coil_test_board.py @@ -1,47 +1,53 @@ #!/usr/bin/env python3 import math +import re import itertools import datetime import tempfile import subprocess +import sqlite3 +import json + +import tqdm import gerbonara.cad.kicad.pcb as pcb import gerbonara.cad.kicad.footprints as fp import gerbonara.cad.primitives as cad_pr import gerbonara.cad.kicad.graphical_primitives as kc_gr + cols = 6 rows = 4 coil_specs = [ - {'n': 1, 's': True, 't': 1, 'c': 0.20, 'w': 5.00, 'v': 0.40}, - {'n': 2, 's': True, 't': 1, 'c': 0.20, 'w': 3.00, 'v': 0.40}, - {'n': 3, 's': True, 't': 1, 'c': 0.20, 'w': 1.50, 'v': 0.40}, - {'n': 5, 's': True, 't': 1, 'c': 0.20, 'w': 0.80, 'v': 0.40}, - {'n': 10, 's': True, 't': 1, 'c': 0.20, 'w': 0.50, 'v': 0.40}, - {'n': 25, 's': True, 't': 1, 'c': 0.15, 'w': 0.25, 'v': 0.40}, - - {'n': 1, 's': False, 't': 1, 'c': 0.20, 'w': 5.00, 'v': 0.40}, - {'n': 2, 's': False, 't': 1, 'c': 0.20, 'w': 3.00, 'v': 0.40}, - {'n': 3, 's': False, 't': 1, 'c': 0.20, 'w': 1.50, 'v': 0.40}, - {'n': 5, 's': False, 't': 1, 'c': 0.20, 'w': 0.80, 'v': 0.40}, - {'n': 10, 's': False, 't': 1, 'c': 0.20, 'w': 0.50, 'v': 0.40}, - {'n': 25, 's': False, 't': 1, 'c': 0.15, 'w': 0.25, 'v': 0.40}, - - {'n': 1, 's': False, 't': 3, 'c': 0.20, 'w': 5.00, 'v': 0.40}, - {'n': 2, 's': False, 't': 3, 'c': 0.20, 'w': 3.00, 'v': 0.40}, - {'n': 3, 's': False, 't': 2, 'c': 0.20, 'w': 1.50, 'v': 0.40}, - {'n': 5, 's': False, 't': 2, 'c': 0.20, 'w': 0.80, 'v': 0.40}, - {'n': 10, 's': False, 't': 3, 'c': 0.20, 'w': 0.50, 'v': 0.40}, - {'n': 25, 's': False, 't': 2, 'c': 0.15, 'w': 0.25, 'v': 0.40}, - - {'n': 1, 's': False, 't': 5, 'c': 0.20, 'w': 5.00, 'v': 0.40}, - {'n': 2, 's': False, 't': 5, 'c': 0.20, 'w': 3.00, 'v': 0.40}, - {'n': 3, 's': False, 't': 4, 'c': 0.20, 'w': 1.50, 'v': 0.40}, - {'n': 5, 's': False, 't': 3, 'c': 0.20, 'w': 0.80, 'v': 0.40}, - {'n': 10, 's': False, 't': 7, 'c': 0.20, 'w': 0.50, 'v': 0.40}, - {'n': 25, 's': False, 't': 7, 'c': 0.15, 'w': 0.25, 'v': 0.40}, + {'n': 1, 's': True, 't': 1, 'c': 0.20, 'w': 5.00, 'd': 3.00, 'v': 5.00}, + {'n': 2, 's': True, 't': 1, 'c': 0.20, 'w': 3.00, 'd': 1.50, 'v': 3.00}, + {'n': 3, 's': True, 't': 1, 'c': 0.20, 'w': 1.50, 'd': 1.20, 'v': 2.00}, + {'n': 5, 's': True, 't': 1, 'c': 0.20, 'w': 0.80, 'd': 0.40, 'v': 0.80}, + {'n': 10, 's': True, 't': 1, 'c': 0.20, 'w': 0.50, 'd': 0.30, 'v': 0.60}, + {'n': 25, 's': True, 't': 1, 'c': 0.15, 'w': 0.25, 'd': 0.30, 'v': 0.60}, + + {'n': 1, 's': False, 't': 3, 'c': 0.20, 'w': 5.00, 'd': 3.00, 'v': 5.00}, + {'n': 2, 's': False, 't': 1, 'c': 0.20, 'w': 3.00, 'd': 1.50, 'v': 3.00}, + {'n': 3, 's': False, 't': 1, 'c': 0.20, 'w': 2.50, 'd': 1.20, 'v': 2.00}, + {'n': 5, 's': False, 't': 1, 'c': 0.20, 'w': 2.50, 'd': 0.40, 'v': 0.80}, + {'n': 10, 's': False, 't': 1, 'c': 0.20, 'w': 1.50, 'd': 0.30, 'v': 0.60}, + {'n': 25, 's': False, 't': 1, 'c': 0.15, 'w': 0.50, 'd': 0.30, 'v': 0.60}, + + {'n': 1, 's': False, 't': 4, 'c': 0.20, 'w': 5.00, 'd': 3.00, 'v': 5.00}, + {'n': 2, 's': False, 't': 3, 'c': 0.20, 'w': 3.00, 'd': 1.50, 'v': 3.00}, + {'n': 3, 's': False, 't': 4, 'c': 0.20, 'w': 2.50, 'd': 1.20, 'v': 2.00}, + {'n': 5, 's': False, 't': 3, 'c': 0.20, 'w': 2.50, 'd': 0.40, 'v': 0.80}, + {'n': 10, 's': False, 't': 3, 'c': 0.20, 'w': 1.50, 'd': 0.30, 'v': 0.60}, + {'n': 25, 's': False, 't': 3, 'c': 0.15, 'w': 0.50, 'd': 0.30, 'v': 0.60}, + + {'n': 1, 's': False, 't': 5, 'c': 0.20, 'w': 5.00, 'd': 3.00, 'v': 5.00}, + {'n': 2, 's': False, 't': 5, 'c': 0.20, 'w': 3.00, 'd': 1.50, 'v': 3.00}, + {'n': 3, 's': False, 't': 4, 'c': 0.20, 'w': 2.50, 'd': 1.20, 'v': 2.00}, + {'n': 5, 's': False, 't': 7, 'c': 0.20, 'w': 2.50, 'd': 0.40, 'v': 0.80}, + {'n': 10, 's': False, 't': 7, 'c': 0.20, 'w': 1.50, 'd': 0.30, 'v': 0.60}, + {'n': 25, 's': False, 't': 13, 'c': 0.15, 'w': 0.50, 'd': 0.30, 'v': 0.60}, ] version_string = 'v1.0' @@ -55,6 +61,8 @@ mouse_bite_hole_spacing = 0.3 hole_offset = 5 hole_dia = 3.2 coil_dia = 35 # mm +coil_inner_dia = 15 # mm +board_thickness = 0.80 # mm pad_offset = 2 # mm pad_dia = 2.0 # mm pad_length = 3.5 # mm @@ -62,6 +70,16 @@ pad_drill = 1.1 # mm pad_pitch = 2.54 # mm v_cuts = False # FIXME DEBUG mouse_bites = False # FIXME DEBUG + +db = sqlite3.connect('coil_parameters.sqlite3') +db.execute('CREATE TABLE IF NOT EXISTS runs (run_id INTEGER PRIMARY KEY, timestamp TEXT, version TEXT)') +db.execute('CREATE TABLE IF NOT EXISTS coils (coil_id INTEGER PRIMARY KEY, run_id INTEGER, FOREIGN KEY (run_id) REFERENCES runs(run_id))') +db.execute('CREATE TABLE IF NOT EXISTS results (result_id INTEGER PRIMARY KEY, coil_id INTEGER, key TEXT, value TEXT, FOREIGN KEY (coil_id) REFERENCES coils(coil_id))') +cur = db.cursor() +cur.execute('INSERT INTO runs(timestamp, version) VALUES (datetime("now"), ?)', (version_string,)) +run_id = cur.lastrowid +db.commit() + coil_pitch = coil_dia + coil_border*2 + cut_gap total_width = coil_pitch*cols + 2*tooling_border + cut_gap @@ -286,52 +304,78 @@ b.add(kc_gr.Text(text=f'Planar inductor test panel {version_string} {timestamp} thickness=a/5), justify=pcb.Justify(h=pcb.Atom.left, v=pcb.Atom.top)))) -for index, ((y, x), spec) in enumerate(zip(itertools.product(range(rows), range(cols)), coil_specs), start=1): +for index, ((y, x), spec) in tqdm.tqdm(enumerate(zip(itertools.product(range(rows), range(cols)), coil_specs), start=1)): pass with tempfile.NamedTemporaryFile(suffix='.kicad_mod') as f: tile_x0 = x0 + tooling_border + cut_gap + x*coil_pitch + tile_width/2 tile_y0 = y0 + tooling_border + cut_gap + y*coil_pitch + tile_height/2 for key, alias in { - 'inner_diameter': 'id', - 'outer_diameter': 'od', - 'trace_width': 'w', - 'turns': 'n', - 'twists': 't', - 'clearance': 'c', - 'single_layer': 's', - 'via_drill': 'v'}.items(): + 'gen.inner_diameter': 'id', + 'gen.outer_diameter': 'od', + 'gen.trace_width': 'w', + 'gen.turns': 'n', + 'gen.twists': 't', + 'gen.clearance': 'c', + 'gen.single_layer': 's', + 'gen.via_drill': 'd', + 'gen.via_diameter': 'v'}.items(): if alias in spec: spec[key] = spec.pop(alias) - if 'via_diameter' not in spec: - spec['via_diameter'] = spec['trace_width'] + if 'gen.via_diameter' not in spec: + spec['gen.via_diameter'] = spec['gen.trace_width'] - if 'inner_diameter' not in spec: - spec['inner_diameter'] = 15 + if 'gen.inner_diameter' not in spec: + spec['gen.inner_diameter'] = coil_inner_dia - if 'outer_diameter' not in spec: - spec['outer_diameter'] = 35 + if 'gen.outer_diameter' not in spec: + spec['gen.outer_diameter'] = coil_dia args = ['python', '-m', 'twisted_coil_gen_twolayer', '--no-keepout-zone'] for k, v in spec.items(): - if not isinstance(v, bool) or v: + prefix, _, k = k.partition('.') + if (not isinstance(v, bool) or v) and prefix == 'gen': args.append('--' + k.replace('_', '-')) if v is not True: args.append(str(v)) args.append(f.name) - subprocess.run(args, check=True) + res = subprocess.run(args, check=True, capture_output=True, text=True) coil = fp.Footprint.open_mod(f.name) coil.at = fp.AtPos(tile_x0, tile_y0, 0) b.add(coil) - t = [f'n={spec["turns"]}', - f'{spec["twists"]} twists', - f'w={spec["trace_width"]:.2f}mm'] - if spec.get('single_layer'): + t = [f'n={spec["gen.turns"]}', + f'{spec["gen.twists"]} twists', + f'w={spec["gen.trace_width"]:.2f}mm'] + if spec.get('gen.single_layer'): t.append('single layer') + spec['gen.board_thickness'] = board_thickness + cur.execute('INSERT INTO coils(run_id) VALUES (?)', (run_id,)) + coil_id = cur.lastrowid + + for key, value in spec.items(): + if isinstance(value, bool): + value = str(value) + db.execute('INSERT INTO results(coil_id, key, value) VALUES (?, ?, ?)', (coil_id, key, value)) + + for l in res.stderr.splitlines(): + if (m := re.fullmatch(r'Approximate inductance:\s*([-+.0-9eE]+)\s*µH', l.strip())): + val = float(m.group(1)) * 1e-6 + db.execute('INSERT INTO results(coil_id, key, value) VALUES (?, "calculated_approximate_inductance", ?)', (coil_id, val)) + if (m := re.fullmatch(r'Approximate track length:\s*([-+.0-9eE]+)\s*mm', l.strip())): + val = float(m.group(1)) * 1e-3 + db.execute('INSERT INTO results(coil_id, key, value) VALUES (?, "calculated_trace_length", ?)', (coil_id, val)) + if (m := re.fullmatch(r'Approximate resistance:\s*([-+.0-9eE]+)\s*Ω', l.strip())): + val = float(m.group(1)) + db.execute('INSERT INTO results(coil_id, key, value) VALUES (?, "calculated_approximate_resistance", ?)', (coil_id, val)) + if (m := re.fullmatch(r'Fill factor:\s*([-+.0-9eE]+)', l.strip())): + val = float(m.group(1)) + db.execute('INSERT INTO results(coil_id, key, value) VALUES (?, "calculated_fill_factor", ?)', (coil_id, val)) + db.commit() + sz = 1.5 b.add(kc_gr.Text(text='\\n'.join(t), at=pcb.AtPos(tile_x0, tile_y0), @@ -361,7 +405,7 @@ for index, ((y, x), spec) in enumerate(zip(itertools.product(range(rows), range( pads = make_pads(pads_x0, tile_y0, 270, 2, pad_dia, pad_length, pad_drill, pad_pitch) b.add(pads) - w = min(spec.get('trace_width', pad_dia), pad_dia) + w = min(spec.get('gen.trace_width', pad_dia), pad_dia) x, y, _r, _f = pads.pad(2).abs_pos w2 = (x - pad_length/2, y) x, y, _r, _f = pads.pad(1).abs_pos -- cgit