Integrate DB9 mounting into enclosure lid
This commit is contained in:
@@ -78,6 +78,11 @@ def source_check():
|
||||
cad = json.loads((PCB / "reference/db9-cad/measurements.json").read_text())
|
||||
near([axis["location"][0]+43-1.905 for axis in cad["front_lock_axes"]], literal("lock_x"))
|
||||
near(cad["shell_outer_including_root_and_lip"]["dimensions"], [16.878038, 5.8, 9.1])
|
||||
shell = cad["shell_outer_including_root_and_lip"]["bounds"]
|
||||
near([shell[2], 29.337-shell[4]], [3.29762024, -3.87])
|
||||
flange = cad["front_flange_exposed_faces"]["bounds"]
|
||||
near([29.337-flange[4]], [literal("flange_y")])
|
||||
near([flange[0]+41.095, flange[3]+41.095], [41.57, 72.37])
|
||||
for axis in cad["front_lock_axes"]:
|
||||
near([axis["location"][2]-1.57], [6.27762024])
|
||||
print("PASS native PCB outline, thickness, placements, NPTH centres, buttons, USB mouths, STEP lock/shell data")
|
||||
@@ -127,6 +132,8 @@ def mesh_check(path, expected_components):
|
||||
|
||||
def geometry_check():
|
||||
"""Evaluate actual SCAD expressions, including negative stud/web fixtures."""
|
||||
assert 'panel_hangers' not in SCAD and 'panel_mount_' not in SCAD
|
||||
assert 'part=="panel"' not in SCAD and not (ROOT/"panel-default.stl").exists()
|
||||
assert 'module spacers(' not in SCAD and 'part=="spacers"' not in SCAD
|
||||
assert not (ROOT/"spacers-default.stl").exists(), "Obsolete printable spacers must not ship"
|
||||
assert 'brass_standoff_h' not in SCAD, "No brass height below carrier"
|
||||
@@ -149,35 +156,103 @@ def geometry_check():
|
||||
match = re.search(r'ECHO: "CHECK '+label+r'", (\[[^\n]+\])', output)
|
||||
assert match, output
|
||||
return ast.literal_eval(match.group(1))
|
||||
return datum("stack"), datum("engagement")
|
||||
stack, engagement = run()
|
||||
closure = datum("closure")
|
||||
assert closure[2] <= -0.5 and closure[3] < closure[4]
|
||||
if not defines:
|
||||
near(closure, [33,81,-0.5,20.82,21.6976,17.578,0.25])
|
||||
return datum("stack"), datum("engagement"), datum("connector")
|
||||
stack, engagement, connector = run()
|
||||
near(connector, [-0.47, 1.93, 2.4, 21.07, 31.9976, 18.078, 25, 3.6, 5, 1.66098])
|
||||
# Independent expected defaults, not values copied from exported meshes.
|
||||
near(stack, [7.4, 9, 19, 20.57, 35, 37.4, 15, 13.3, 15.6,
|
||||
26.8476, 21.07, 19.6, 26.6, 25.6])
|
||||
near(engagement, [2.4, 2.4])
|
||||
raised, _ = run(["carrier_boss_h=7"])
|
||||
raised, _, _ = run(["carrier_boss_h=7"])
|
||||
near(raised, [value+(0 if i == 13 else 2) for i, value in enumerate(stack)])
|
||||
taller, _ = run(["module_gap=12", "lid_above_carrier=28"])
|
||||
taller, _, _ = run(["module_gap=12", "lid_above_carrier=28"])
|
||||
near(taller, [value+(2 if i in [2,3,4,5,9,10,11,12,13] else 0)
|
||||
for i, value in enumerate(stack)])
|
||||
run(["brass_m3_stud_l=1.6"], valid=False)
|
||||
run(["brass_m2_stud_l=5"], valid=False)
|
||||
run(["wall=0.8"], valid=False)
|
||||
run(["panel_t=0.8"], valid=False)
|
||||
run(["panel_flange_gap=-0.1"], valid=False)
|
||||
run(["panel_bottom_above_module=-0.1"], valid=False)
|
||||
run(["external_fastener_clearance=5"], valid=False)
|
||||
run(["panel_rib_w=8"], valid=False)
|
||||
run(["seam_clearance=0"], valid=False)
|
||||
run(["shell_margin=0.1"], valid=False)
|
||||
run(["panel_bottom_above_module=2"], valid=False)
|
||||
print("PASS actual SCAD default/raised-carrier/taller-module datums, stud engagement and nozzle-web rejection fixtures")
|
||||
|
||||
|
||||
def installation_check():
|
||||
"""CGAL intersection of actual lid with continuous vertical envelope sweeps."""
|
||||
with tempfile.TemporaryDirectory(prefix="case-install-") as temp:
|
||||
for mode, defines in [
|
||||
("installation-check", []),
|
||||
("installation-check", ["carrier_boss_h=7", "module_gap=12", "lid_above_carrier=28", "panel_t=3"]),
|
||||
("installation-check", ["seam_clearance=0.4", "shell_margin=0.8", "end_clearance=1.5"]),
|
||||
("installation-blocked", []),
|
||||
]:
|
||||
path = Path(temp)/"sweep.stl"
|
||||
command = ["openscad", "-o", str(path), "-D", f'part="{mode}"', "-D", "emboss=false"]
|
||||
for define in defines:
|
||||
command.extend(["-D", define])
|
||||
result = subprocess.run(command+[str(ROOT/"enclosure.scad")],
|
||||
env={**os.environ, "QT_QPA_PLATFORM": "offscreen"},
|
||||
capture_output=True, text=True, timeout=180)
|
||||
assert result.returncode == 0 and "ERROR:" not in result.stderr, result.stderr
|
||||
if mode == "installation-check":
|
||||
report = mesh_check(path, 1)
|
||||
near([report["volume_mm3"]], [1])
|
||||
else:
|
||||
# Negative control: unremoved post envelopes MUST hit the panel.
|
||||
text = path.read_text()
|
||||
zs = [float(z) for z in re.findall(r"\bvertex\s+[-+\deE.]+\s+[-+\deE.]+\s+([-+\deE.]+)", text)]
|
||||
assert max(zs) > 80, "Fixture failed to detect installed posts"
|
||||
print("PASS continuous vertical installation sweep", mode, defines)
|
||||
|
||||
|
||||
def variant_check():
|
||||
fixtures = [
|
||||
('lid', ['carrier_boss_h=7', 'module_gap=12', 'lid_above_carrier=28', 'panel_t=3']),
|
||||
('base', ['carrier_boss_h=7', 'module_gap=12', 'lid_above_carrier=28', 'panel_t=3']),
|
||||
('lid', ['db_panel=false']),
|
||||
('base', ['daughter_supports=false', 'side_extra=14', 'm3_insert_d=4.4']),
|
||||
]
|
||||
with tempfile.TemporaryDirectory(prefix='case-variant-') as temp:
|
||||
for part, defines in fixtures:
|
||||
path = Path(temp)/'variant.stl'
|
||||
command = ['openscad', '-o', str(path), '-D', f'part="{part}"', '-D', 'emboss=false']
|
||||
for define in defines:
|
||||
command.extend(['-D', define])
|
||||
result = subprocess.run(command+[str(ROOT/'enclosure.scad')],
|
||||
env={**os.environ, 'QT_QPA_PLATFORM': 'offscreen'},
|
||||
capture_output=True, text=True, timeout=180)
|
||||
assert result.returncode == 0 and 'ERROR:' not in result.stderr, result.stderr
|
||||
mesh_check(path, 1)
|
||||
print('PASS parameter CGAL mesh', part, defines)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--source", action="store_true", help="also check saved KiCad/STEP registration")
|
||||
parser.add_argument("--installation", action="store_true", help="CGAL continuous vertical sweep and blocked-post control")
|
||||
parser.add_argument('--variants', action='store_true', help='CGAL parameter mesh smoke tests')
|
||||
args = parser.parse_args()
|
||||
if args.variants:
|
||||
variant_check()
|
||||
if args.installation:
|
||||
installation_check()
|
||||
geometry_check()
|
||||
if args.source:
|
||||
source_check()
|
||||
reports = [mesh_check(ROOT / name, n) for name, n in [
|
||||
("base-default.stl", 1), ("lid-default.stl", 1), ("panel-default.stl", 1),
|
||||
("base-default.stl", 1), ("lid-default.stl", 1),
|
||||
("plungers-default.stl", 3)]]
|
||||
for report, high in zip(reports, [[94,83.4,15], [94,83.4,22.75],
|
||||
[46,0,2], [28,4,25.6]]):
|
||||
for report, high in zip(reports, [[94,83.4,21.6976], [94,83.4,22.75],
|
||||
[28,4,25.6]]):
|
||||
near(report["bounds_mm"][1], high) # catch stale exports of the old stack
|
||||
print(json.dumps(reports, indent=2))
|
||||
print("PASS edge-manifold topology, winding, component counts, positive total volumes and print-bed Z")
|
||||
|
||||
Reference in New Issue
Block a user