project
Adom Custom Electronic Load
Public Made by Adomby adom
Two-layer digitally controlled electronic-load prototype. Compact R11 is under active electrical, cooling and probe-access review; not a manufacturing release.
← Commit history
Screen stock TO-220 sink against board 18 without new PCB drills
9 files changed
+1536−6
docs/completion-plan.md+1−1@@ -6,7 +6,7 @@ The active objective is to finish this electronic-load design through AIFlow, th Native-saved board 18 SHA-256 `8d6cd24149f7de061f125bf45a26b50ca5b70a6b01c62b96dc3cf92187a531f1`. Nine D1 thermal vias were added to board 17, recorded and saved. Native DRC has zero errors/opens and 15 inherited library warnings. AIFlow adopted the saved board, re-ran routing and gate, and recorded the empty routing plan as landed. D1 now has 10 of 10 planned thermal vias. Six added-via coordinates differ from the offline generator by at most one nanometre per axis; read the explicit rounding audit. The earlier candidate current screen is diagnostic evidence, not a new formal same-board Fields pass. Both native 2D and 3D views and the published 2x video were inspected. Output-locked STM32 bring-up remains unflashed and unqualified. -Installed Fields remains 0.6.2; physical two-layer/plated-pad PR 5 is still open. Its rectangular heat blocks contact the PCB face, not the MOSFET case. Do not substitute that model for the missing package/interface/sink/airflow analysis. The four-hole 40 mm sink pattern was rejected against routed copper. Investigate the existing Q1 3.5 mm mounting hole at (127.46,65.34), with actual hardware, electrical isolation and support rather than assuming it qualifies an assembly.+Installed Fields remains 0.6.2; physical two-layer/plated-pad PR 5 is still open. Its rectangular heat blocks contact the PCB face, not the MOSFET case. Do not substitute that model for the missing package/interface/sink/airflow analysis. The four-hole 40 mm sink pattern was rejected against routed copper. The stock Wakefield 680-125220 candidate aligns a factory TO-220 hole with the existing Q1 3.5 mm hole and clears the current fitted-body/probe envelope screen; see stock-cooling-candidate.md. Exact model/contact, fasteners, insulation, cradle support, mating access and airflow remain unresolved. Do not call this a qualified assembly. ## Resume here
docs/status.md+2−2@@ -1,6 +1,6 @@-# Current checkpoint — 2026-10-09, 20:22 UTC+# Current checkpoint — 2026-10-09, 20:21 UTC -Board 18 remains unchanged; thermal/finish gates remain open. Instrument register fault-injection tests now pass, with DAC/configuration readback and coherent triggered INA226 reads. The control panel accepts explicitly unavailable sensors only while output is confirmed OFF, and refuses ARM until sensor and assembly qualification are valid. All sanitizer-backed C suites and 25 Python tests pass. The output-locked STM32 image builds at 64,688 flash bytes and 23,968 RAM bytes including reservations. No hardware was flashed.+Board 18 remains unchanged; thermal/finish gates remain open. The [stock sink attachment candidate](stock-cooling-candidate.md) clears the current fitted-body/probe screen without proposed new PCB holes; the actual mounting stack and airflow remain unresolved. Instrument register fault-injection tests now pass, with DAC/configuration readback and coherent triggered INA226 reads. The control panel accepts explicitly unavailable sensors only while output is confirmed OFF, and refuses ARM until sensor and assembly qualification are valid. All sanitizer-backed C suites and 25 Python tests pass. The output-locked STM32 image builds at 64,688 flash bytes and 23,968 RAM bytes including reservations. No hardware was flashed. The reviewed fan-stall replay is published and visually checked on the wiki. There are 59 raw takes, including rejected/static takes; the final narrated film is unfinished. See [clip library](build-clips.md) and [firmware contract](firmware-contract.md).
docs/stock-cooling-candidate.mdadded+23@@ -0,0 +1,23 @@+# Stock heatsink attachment candidate++++The Wakefield 680-125220 offers a factory TO-220 mounting pattern, a nominal 45.974 mm square footprint and 31.75 mm height. Its catalog lists 1.5 K/W at 400 LFM. This airflow is not established for our installed fan. Source: [manufacturer catalog, printed page 75](https://wakefieldthermal.com/content/catalogs/2019_Catalog.pdf).++Aligning one stock device hole with the existing Q1 mounting hole gives sink center (138.636, 67.118) mm. The current board-18 STEP bounding-box screen covers all 91 fitted models with no intersections; all existing probe approach circles clear the sink envelope. The screen proposes no new PCB drills. These results do not cover connectors with mating plugs, assembly tooling, exact contact geometry or tolerances. The slot/cutout pattern and drawing orientation still need verification against an exact model.++Boyd 7721-7PPSG is a possible insulating shoulder washer: nominal 3.43 mm shoulder, 2.95 mm bore, 0.81 mm shoulder length, 5.46 mm flange and 1.02 mm flange thickness, cataloged for a #4 screw. Its dimensions suggest a path worth checking, not a qualified fastener stack. Source: [Boyd catalog, printed page 96](https://info.boydcorp.com/hubfs/Thermal/Air-Cooling/Boyd-Board-Level-Heatsinks-Catalog.pdf).++The mass of the sink and fan needs an independent cradle attached to the molecule. It must not hang from Q1 leads. The PCB has no general-purpose mounting holes; attachment to the carrier, board-edge clearance and probe access must be designed together. No cradle, fastener or pad has been released. In particular, shoulder coverage through the tab, screw/nut height beneath it, pad-hole dimensions, electrical isolation and assembly sequence remain unresolved.++Using the earlier illustrative AlN/grease interface and 0.3 K/W spreading assumption with this catalog sink value gives about 50.1 C case temperature at 5 W and 40 C ambient. This is a sensitivity estimate, not a thermal gate pass; actual installed airflow, interface pressure and sensor error are not established. The 55 C trip remains unchanged.++Reproduce from the project root, using the existing CAD environment for the first command:++```sh+python tools/cooling_body_audit.py --sink 115.649 44.131 5.09 161.623 90.105 36.84 --output mechanical/cooling-680-body-audit.json+python3 tools/screen_stock_cooling.py+python3 -s tools/plot_stock_cooling.py+```++[Machine-readable screen](../mechanical/cooling-680-screen.json) · [Fitted-model evidence](../mechanical/cooling-680-body-audit.json) · [Thermal sensitivity assumptions](package-cooling-review.md)
mechanical/cooling-680-body-audit.jsonadded+1298@@ -0,0 +1,1298 @@+{+ "boardSha256": "8d6cd24149f7de061f125bf45a26b50ca5b70a6b01c62b96dc3cf92187a531f1",+ "method": "Conservative transformed fitted STEP bounding boxes, board XY with Z above top copper; zero local model transforms only",+ "sinkEnvelopeMm": [+ 115.649,+ 44.131,+ 5.09,+ 161.623,+ 90.105,+ 36.84+ ],+ "coverage": {+ "models": 91,+ "unsupported": 0+ },+ "bodyIntersections": [],+ "rows": [+ {+ "ref": "U6",+ "model": "kicad/3d/SOT-23-5.step",+ "boundsMm": [+ 127.6,+ 43.5499999,+ 0.0,+ 130.4,+ 46.4500001,+ 1.5500001+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "R33",+ "model": "kicad/3d/R_0402_1005Metric.step",+ "boundsMm": [+ 144.95,+ 62.7,+ -2.775557561563e-17,+ 145.45,+ 63.7,+ 0.35+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "R11",+ "model": "kicad/3d/R_0402_1005Metric.step",+ "boundsMm": [+ 132.5,+ 85.75,+ -2.775557561563e-17,+ 133.5,+ 86.25,+ 0.35+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "R21",+ "model": "kicad/3d/R_0402_1005Metric.step",+ "boundsMm": [+ 117.1,+ 61.95,+ -2.775557561563e-17,+ 118.1,+ 62.45,+ 0.35+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "MP2",+ "model": "kicad/3d/MachinePinMediumShort.step",+ "boundsMm": [+ 159.2,+ 99.2,+ -4.950000000000007,+ 160.8,+ 100.8,+ 2.8000000000000007+ ],+ "sinkIntersection": false,+ "underSinkXY": false+ },+ {+ "ref": "J6",+ "model": "kicad/3d/MachineContactMedium.step",+ "boundsMm": [+ 139.5649999,+ 99.56499990055856,+ -1.6500000000000021,+ 140.4350001,+ 100.43500009944144,+ 0.0+ ],+ "sinkIntersection": false,+ "underSinkXY": false+ },+ {+ "ref": "C15",+ "model": "kicad/3d/C_0603_1608Metric.step",+ "boundsMm": [+ 141.5,+ 88.2,+ 0.0,+ 142.3,+ 89.8,+ 0.8+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "F1",+ "model": "kicad/3d/Fuse_1206_3216Metric.step",+ "boundsMm": [+ 104.80000000000001,+ 90.2,+ 0.0,+ 108.0,+ 91.8,+ 0.55+ ],+ "sinkIntersection": false,+ "underSinkXY": false+ },+ {+ "ref": "MP3",+ "model": "kicad/3d/MachinePinMediumShort.step",+ "boundsMm": [+ 99.2,+ 31.2,+ -4.950000000000007,+ 100.8,+ 32.800000000000004,+ 2.8000000000000007+ ],+ "sinkIntersection": false,+ "underSinkXY": false+ },+ {+ "ref": "U9",+ "model": "kicad/3d/SOT-23-5.step",+ "boundsMm": [+ 146.6,+ 63.5499999,+ 0.0,+ 149.4,+ 66.4500001,+ 1.5500001+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "R30",+ "model": "kicad/3d/R_0402_1005Metric.step",+ "boundsMm": [+ 152.5,+ 38.25,+ -2.775557561563e-17,+ 153.5,+ 38.75,+ 0.35+ ],+ "sinkIntersection": false,+ "underSinkXY": false+ },+ {+ "ref": "RSH1",+ "model": "kicad/3d/LVK12.step",+ "boundsMm": [+ 136.4,+ 84.2,+ 0.0,+ 139.6,+ 85.8,+ 0.5+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "U3",+ "model": "kicad/3d/SOT-23-5.step",+ "boundsMm": [+ 127.6,+ 85.5499999,+ 0.0,+ 130.4,+ 88.4500001,+ 1.5500001+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "U8",+ "model": "kicad/3d/SOT-23-6.step",+ "boundsMm": [+ 126.6,+ 50.5499999,+ 0.0,+ 129.4,+ 53.4500001,+ 1.5500001+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "R20",+ "model": "kicad/3d/R_0402_1005Metric.step",+ "boundsMm": [+ 114.55,+ 61.7,+ -2.775557561563e-17,+ 115.05,+ 62.7,+ 0.35+ ],+ "sinkIntersection": false,+ "underSinkXY": false+ },+ {+ "ref": "MP1",+ "model": "kicad/3d/MachinePinMediumShort.step",+ "boundsMm": [+ 99.2,+ 99.2,+ -4.950000000000007,+ 100.8,+ 100.8,+ 2.8000000000000007+ ],+ "sinkIntersection": false,+ "underSinkXY": false+ },+ {+ "ref": "R38",+ "model": "kicad/3d/R_0402_1005Metric.step",+ "boundsMm": [+ 151.15,+ 62.7,+ -2.775557561563e-17,+ 151.65,+ 63.7,+ 0.35+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "J10",+ "model": "kicad/3d/PinHeader_1x02_P2.54mm_Vertical.step",+ "boundsMm": [+ 102.73,+ 71.73,+ -3.00000000000022,+ 107.81,+ 74.27,+ 8.54000000000022+ ],+ "sinkIntersection": false,+ "underSinkXY": false+ },+ {+ "ref": "C16",+ "model": "kicad/3d/C_0603_1608Metric.step",+ "boundsMm": [+ 126.2,+ 41.9,+ 0.0,+ 127.8,+ 42.699999999999996,+ 0.8+ ],+ "sinkIntersection": false,+ "underSinkXY": false+ },+ {+ "ref": "R23",+ "model": "kicad/3d/R_0402_1005Metric.step",+ "boundsMm": [+ 118.95,+ 60.01,+ -2.775557561563e-17,+ 119.45,+ 61.01,+ 0.35+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "R24",+ "model": "kicad/3d/R_0402_1005Metric.step",+ "boundsMm": [+ 146.3,+ 81.75,+ -2.775557561563e-17,+ 147.3,+ 82.25,+ 0.35+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "J5",+ "model": "kicad/3d/MachineContactMedium.step",+ "boundsMm": [+ 135.5649999,+ 99.56499990055856,+ -1.6500000000000021,+ 136.4350001,+ 100.43500009944144,+ 0.0+ ],+ "sinkIntersection": false,+ "underSinkXY": false+ },+ {+ "ref": "R34",+ "model": "kicad/3d/R_0402_1005Metric.step",+ "boundsMm": [+ 148.1,+ 62.25,+ -2.775557561563e-17,+ 149.1,+ 62.75,+ 0.35+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "R5",+ "model": "kicad/3d/R_0402_1005Metric.step",+ "boundsMm": [+ 111.5,+ 59.35,+ -2.775557561563e-17,+ 112.5,+ 59.85,+ 0.35+ ],+ "sinkIntersection": false,+ "underSinkXY": false+ },+ {+ "ref": "D3",+ "model": "kicad/3d/SOT-23.step",+ "boundsMm": [+ 145.9999999,+ 83.45,+ 0.0,+ 149.0000001,+ 85.95,+ 1.2000001+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "J2",+ "model": "kicad/3d/MachineContactMedium.step",+ "boundsMm": [+ 111.5649999,+ 99.56499990055856,+ -1.6500000000000021,+ 112.4350001,+ 100.43500009944144,+ 0.0+ ],+ "sinkIntersection": false,+ "underSinkXY": false+ },+ {+ "ref": "U1",+ "model": "kicad/3d/LQFP-32_7x7mm_P0.8mm.step",+ "boundsMm": [+ 138.5,+ 42.5,+ 0.0,+ 147.5,+ 51.5,+ 1.5000001+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "R22",+ "model": "kicad/3d/R_0402_1005Metric.step",+ "boundsMm": [+ 121.35,+ 60.6,+ -2.775557561563e-17,+ 121.85,+ 61.6,+ 0.35+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "C1",+ "model": "kicad/3d/C_0603_1608Metric.step",+ "boundsMm": [+ 117.2,+ 73.19999999999999,+ 0.0,+ 118.8,+ 74.0,+ 0.8+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "R31",+ "model": "kicad/3d/R_0402_1005Metric.step",+ "boundsMm": [+ 148.65,+ 44.75,+ -2.775557561563e-17,+ 149.65,+ 45.25,+ 0.35+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "R10",+ "model": "kicad/3d/R_0402_1005Metric.step",+ "boundsMm": [+ 120.55,+ 74.92,+ -2.775557561563e-17,+ 121.05,+ 75.92,+ 0.35+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "J4",+ "model": "kicad/3d/MachineContactMedium.step",+ "boundsMm": [+ 123.5649999,+ 99.56499990055856,+ -1.6500000000000021,+ 124.4350001,+ 100.43500009944144,+ 0.0+ ],+ "sinkIntersection": false,+ "underSinkXY": false+ },+ {+ "ref": "R26",+ "model": "kicad/3d/R_0402_1005Metric.step",+ "boundsMm": [+ 152.15,+ 81.5,+ -2.775557561563e-17,+ 152.65,+ 82.5,+ 0.35+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "J9",+ "model": "kicad/3d/PinHeader_1x03_P2.54mm_Vertical.step",+ "boundsMm": [+ 148.25,+ 96.73,+ -3.00000000000022,+ 155.87,+ 99.27,+ 8.54000000000022+ ],+ "sinkIntersection": false,+ "underSinkXY": false+ },+ {+ "ref": "R25",+ "model": "kicad/3d/R_0402_1005Metric.step",+ "boundsMm": [+ 149.1,+ 81.75,+ -2.775557561563e-17,+ 150.1,+ 82.25,+ 0.35+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "R19",+ "model": "kicad/3d/R_0402_1005Metric.step",+ "boundsMm": [+ 120.15,+ 61.21,+ -2.775557561563e-17,+ 120.65,+ 62.21,+ 0.35+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "R8",+ "model": "kicad/3d/R_0402_1005Metric.step",+ "boundsMm": [+ 120.55,+ 70.5,+ -2.775557561563e-17,+ 121.05,+ 71.5,+ 0.35+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "MP4",+ "model": "kicad/3d/MachinePinMediumShort.step",+ "boundsMm": [+ 159.2,+ 31.2,+ -4.950000000000007,+ 160.8,+ 32.800000000000004,+ 2.8000000000000007+ ],+ "sinkIntersection": false,+ "underSinkXY": false+ },+ {+ "ref": "R37",+ "model": "kicad/3d/R_0402_1005Metric.step",+ "boundsMm": [+ 148.45,+ 90.72,+ -2.775557561563e-17,+ 148.95,+ 91.72,+ 0.35+ ],+ "sinkIntersection": false,+ "underSinkXY": false+ },+ {+ "ref": "C5",+ "model": "kicad/3d/C_0603_1608Metric.step",+ "boundsMm": [+ 143.2,+ 84.19999999999999,+ 0.0,+ 144.8,+ 85.0,+ 0.8+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "R13",+ "model": "kicad/3d/R_0402_1005Metric.step",+ "boundsMm": [+ 142.75,+ 57.5,+ -2.775557561563e-17,+ 143.25,+ 58.5,+ 0.35+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "C18",+ "model": "kicad/3d/C_0603_1608Metric.step",+ "boundsMm": [+ 125.2,+ 48.9,+ 0.0,+ 126.8,+ 49.699999999999996,+ 0.8+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "R16",+ "model": "kicad/3d/R_0402_1005Metric.step",+ "boundsMm": [+ 151.15,+ 57.5,+ -2.775557561563e-17,+ 151.65,+ 58.5,+ 0.35+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "R28",+ "model": "kicad/3d/R_0402_1005Metric.step",+ "boundsMm": [+ 113.85,+ 66.51,+ -2.775557561563e-17,+ 114.35,+ 67.51,+ 0.35+ ],+ "sinkIntersection": false,+ "underSinkXY": false+ },+ {+ "ref": "R36",+ "model": "kicad/3d/R_0402_1005Metric.step",+ "boundsMm": [+ 149.75,+ 88.71,+ -2.775557561563e-17,+ 150.25,+ 89.71,+ 0.35+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "R4",+ "model": "kicad/3d/R_0402_1005Metric.step",+ "boundsMm": [+ 120.15,+ 56.5,+ -2.775557561563e-17,+ 120.65,+ 57.5,+ 0.35+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "U10",+ "model": "kicad/3d/SOT-23-6.step",+ "boundsMm": [+ 150.4499999,+ 43.0,+ 0.0,+ 153.35000010000002,+ 45.8,+ 1.5500001+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "U2",+ "model": "kicad/3d/MSOP-10_3x3mm_P0.5mm.step",+ "boundsMm": [+ 115.55,+ 64.4999999,+ -1.110223024625e-16,+ 120.45,+ 67.5000001,+ 1.1000001000000001+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "R3",+ "model": "kicad/3d/R_0402_1005Metric.step",+ "boundsMm": [+ 117.1,+ 56.75,+ -2.775557561563e-17,+ 118.1,+ 57.25,+ 0.35+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "Q1",+ "model": "kicad/3d/TO-220-3_Horizontal_TabUp.step",+ "boundsMm": [+ 122.335,+ 62.525,+ -8.130000000000084,+ 132.585,+ 82.2625,+ 4.455000000000001+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "Q4",+ "model": "kicad/3d/SOT-23.step",+ "boundsMm": [+ 116.75,+ 75.4999999,+ 0.0,+ 119.25,+ 78.5000001,+ 1.2000001+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "C3",+ "model": "kicad/3d/C_0603_1608Metric.step",+ "boundsMm": [+ 137.0,+ 80.6,+ 0.0,+ 138.60000000000002,+ 81.4,+ 0.8+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "C6",+ "model": "kicad/3d/C_0805_2012Metric.step",+ "boundsMm": [+ 157.4,+ 86.375,+ 0.0,+ 159.4,+ 87.625,+ 1.25+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "R1",+ "model": "kicad/3d/R_0402_1005Metric.step",+ "boundsMm": [+ 111.5,+ 56.75,+ -2.775557561563e-17,+ 112.5,+ 57.25,+ 0.35+ ],+ "sinkIntersection": false,+ "underSinkXY": false+ },+ {+ "ref": "J3",+ "model": "kicad/3d/MachineContactMedium.step",+ "boundsMm": [+ 119.5649999,+ 99.56499990055856,+ -1.6500000000000021,+ 120.4350001,+ 100.43500009944144,+ 0.0+ ],+ "sinkIntersection": false,+ "underSinkXY": false+ },+ {+ "ref": "R14",+ "model": "kicad/3d/R_0402_1005Metric.step",+ "boundsMm": [+ 145.55,+ 57.5,+ -2.775557561563e-17,+ 146.05,+ 58.5,+ 0.35+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "R2",+ "model": "kicad/3d/R_0402_1005Metric.step",+ "boundsMm": [+ 114.55,+ 56.5,+ -2.775557561563e-17,+ 115.05,+ 57.5,+ 0.35+ ],+ "sinkIntersection": false,+ "underSinkXY": false+ },+ {+ "ref": "C9",+ "model": "kicad/3d/C_0603_1608Metric.step",+ "boundsMm": [+ 144.6,+ 66.2,+ 0.0,+ 145.4,+ 67.8,+ 0.8+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "C10",+ "model": "kicad/3d/C_0603_1608Metric.step",+ "boundsMm": [+ 117.2,+ 68.89999999999999,+ 0.0,+ 118.8,+ 69.7,+ 0.8+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "C4",+ "model": "kicad/3d/C_0603_1608Metric.step",+ "boundsMm": [+ 142.2,+ 60.2,+ 0.0,+ 143.8,+ 61.0,+ 0.8+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "C17",+ "model": "kicad/3d/C_0603_1608Metric.step",+ "boundsMm": [+ 104.6,+ 48.900000000000006,+ 0.0,+ 105.4,+ 50.5,+ 0.8+ ],+ "sinkIntersection": false,+ "underSinkXY": false+ },+ {+ "ref": "U5",+ "model": "kicad/3d/SOT-23-5.step",+ "boundsMm": [+ 143.6,+ 87.5499999,+ 0.0,+ 146.4,+ 90.4500001,+ 1.5500001+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "D2",+ "model": "kicad/3d/D_SOD-323.step",+ "boundsMm": [+ 113.55,+ 58.9749999,+ -5.551115123126e-17,+ 116.05,+ 60.2250001,+ 1.11+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "R9",+ "model": "kicad/3d/R_0402_1005Metric.step",+ "boundsMm": [+ 120.55,+ 72.71,+ -2.775557561563e-17,+ 121.05,+ 73.71,+ 0.35+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "R17",+ "model": "kicad/3d/R_0402_1005Metric.step",+ "boundsMm": [+ 117.35,+ 59.1,+ -2.775557561563e-17,+ 117.85,+ 60.1,+ 0.35+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "C14",+ "model": "kicad/3d/C_0603_1608Metric.step",+ "boundsMm": [+ 139.2,+ 73.6,+ 0.0,+ 140.8,+ 74.4,+ 0.8+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "C12",+ "model": "kicad/3d/C_0603_1608Metric.step",+ "boundsMm": [+ 111.8,+ 62.4,+ 0.0,+ 113.39999999999999,+ 63.199999999999996,+ 0.8+ ],+ "sinkIntersection": false,+ "underSinkXY": false+ },+ {+ "ref": "R32",+ "model": "kicad/3d/R_0402_1005Metric.step",+ "boundsMm": [+ 148.65,+ 46.25,+ -2.775557561563e-17,+ 149.65,+ 46.75,+ 0.35+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "U4",+ "model": "kicad/3d/MSOP-10_3x3mm_P0.5mm.step",+ "boundsMm": [+ 138.55,+ 75.4999999,+ -1.110223024625e-16,+ 143.45,+ 78.5000001,+ 1.1000001000000001+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "D1",+ "model": "kicad/3d/D_SMC.step",+ "boundsMm": [+ 109.9999999,+ 88.0499999,+ -1e-07,+ 118.0000001,+ 93.9500001,+ 2.3100001+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "R29",+ "model": "kicad/3d/R_0402_1005Metric.step",+ "boundsMm": [+ 152.5,+ 36.25,+ -2.775557561563e-17,+ 153.5,+ 36.75,+ 0.35+ ],+ "sinkIntersection": false,+ "underSinkXY": false+ },+ {+ "ref": "J11",+ "model": "kicad/3d/PinHeader_1x05_P1.27mm_Vertical.step",+ "boundsMm": [+ 153.95,+ 58.365,+ -2.30000000000022,+ 156.05,+ 64.715,+ 4.00000000000022+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "Q2",+ "model": "kicad/3d/SOT-23.step",+ "boundsMm": [+ 122.75,+ 83.7999999,+ 0.0,+ 125.25,+ 86.80000009999999,+ 1.2000001+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "C11",+ "model": "kicad/3d/C_0603_1608Metric.step",+ "boundsMm": [+ 136.4,+ 42.2,+ 0.0,+ 137.20000000000002,+ 43.8,+ 0.8+ ],+ "sinkIntersection": false,+ "underSinkXY": false+ },+ {+ "ref": "R27",+ "model": "kicad/3d/R_0402_1005Metric.step",+ "boundsMm": [+ 113.85,+ 64.3,+ -2.775557561563e-17,+ 114.35,+ 65.3,+ 0.35+ ],+ "sinkIntersection": false,+ "underSinkXY": false+ },+ {+ "ref": "R15",+ "model": "kicad/3d/R_0402_1005Metric.step",+ "boundsMm": [+ 148.35,+ 57.5,+ -2.775557561563e-17,+ 148.85,+ 58.5,+ 0.35+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "C13",+ "model": "kicad/3d/C_0603_1608Metric.step",+ "boundsMm": [+ 129.2,+ 89.3,+ 0.0,+ 130.8,+ 90.10000000000001,+ 0.8+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "D4",+ "model": "kicad/3d/D_SMA.step",+ "boundsMm": [+ 148.9999999,+ 92.6499999,+ -1e-07,+ 154.0000001,+ 95.3500001,+ 2.2200001+ ],+ "sinkIntersection": false,+ "underSinkXY": false+ },+ {+ "ref": "Q3",+ "model": "kicad/3d/SOT-23.step",+ "boundsMm": [+ 118.65,+ 79.9999999,+ 0.0,+ 121.15,+ 83.0000001,+ 1.2000001+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "R6",+ "model": "kicad/3d/R_0402_1005Metric.step",+ "boundsMm": [+ 133.25,+ 81.5,+ -2.775557561563e-17,+ 133.75,+ 82.5,+ 0.35+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "C2",+ "model": "kicad/3d/C_0603_1608Metric.step",+ "boundsMm": [+ 130.89999899999998,+ 83.89999999999999,+ 0.0,+ 132.499999,+ 84.7,+ 0.8+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "R7",+ "model": "kicad/3d/R_0402_1005Metric.step",+ "boundsMm": [+ 128.5,+ 83.75,+ -2.775557561563e-17,+ 129.5,+ 84.25,+ 0.35+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "J7",+ "model": "kicad/3d/MachineContactMedium.step",+ "boundsMm": [+ 143.5649999,+ 99.56499990055856,+ -1.6500000000000021,+ 144.4350001,+ 100.43500009944144,+ 0.0+ ],+ "sinkIntersection": false,+ "underSinkXY": false+ },+ {+ "ref": "J8",+ "model": "kicad/3d/USB_C_Receptacle_GCT_USB4105-xx-A_16P_TopMnt_Horizontal.step",+ "boundsMm": [+ 154.8,+ 38.52999989951449,+ -0.9500000000000001,+ 162.5800001,+ 47.47000010048551,+ 3.3100001+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "C7",+ "model": "kicad/3d/C_0603_1608Metric.step",+ "boundsMm": [+ 151.1,+ 88.7,+ 0.0,+ 151.9,+ 90.3,+ 0.8+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "R35",+ "model": "kicad/3d/R_0402_1005Metric.step",+ "boundsMm": [+ 149.75,+ 86.5,+ -2.775557561563e-17,+ 150.25,+ 87.5,+ 0.35+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "R18",+ "model": "kicad/3d/R_0402_1005Metric.step",+ "boundsMm": [+ 120.15,+ 59.1,+ -2.775557561563e-17,+ 120.65,+ 60.1,+ 0.35+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "U7",+ "model": "kicad/3d/SOIC-14_3.9x8.7mm_P1.27mm.step",+ "boundsMm": [+ 108.0,+ 44.6499999,+ -1.665334536938e-16,+ 114.0,+ 53.3500001,+ 1.7500001+ ],+ "sinkIntersection": false,+ "underSinkXY": false+ },+ {+ "ref": "L1",+ "model": "kicad/3d/L_Abracon_AMPLH5030S.step",+ "boundsMm": [+ 141.2,+ 93.0,+ 0.05,+ 146.8,+ 98.19999999999999,+ 2.8+ ],+ "sinkIntersection": false,+ "underSinkXY": false+ },+ {+ "ref": "C8",+ "model": "kicad/3d/C_0603_1608Metric.step",+ "boundsMm": [+ 150.6,+ 66.2,+ 0.0,+ 151.4,+ 67.8,+ 0.8+ ],+ "sinkIntersection": false,+ "underSinkXY": true+ },+ {+ "ref": "J1",+ "model": "kicad/3d/MachineContactMedium.step",+ "boundsMm": [+ 107.5649999,+ 99.56499990055856,+ -1.6500000000000021,+ 108.4350001,+ 100.43500009944144,+ 0.0+ ],+ "sinkIntersection": false,+ "underSinkXY": false+ }+ ],+ "limitations": [+ "Bounding boxes can overestimate actual material",+ "No mating plugs, cables, clamps, TIM tolerances or duct",+ "Q1 nominal case contact must be verified against exact package drawing"+ ]+}
mechanical/cooling-680-screen.jsonadded+147@@ -0,0 +1,147 @@+{+ "status": "nominal-stock-sink-candidate",+ "acceptance": false,+ "boardSha256": "8d6cd24149f7de061f125bf45a26b50ca5b70a6b01c62b96dc3cf92187a531f1",+ "mpn": "680-125220",+ "manufacturer": "Wakefield Thermal",+ "sinkCenterXY": [+ 138.636,+ 67.11800000000001+ ],+ "sinkXY": [+ 115.649,+ 44.131000000000014,+ 161.623,+ 90.105+ ],+ "heightMm": 31.75,+ "existingQ1HoleXY": [+ 127.46,+ 65.34+ ],+ "existingPcbDrillMm": 3.5,+ "stockSinkDeviceDrillMm": 3.556,+ "proposedAdditionalPcbDrills": 0,+ "fittedModelCount": 91,+ "bodyConflicts": [],+ "probeChecks": [+ {+ "ref": "TP13",+ "x": 108.0,+ "y": 66.0,+ "distanceToSinkMm": 7.649000000000001,+ "clearanceFor2mmRadiusMm": 5.649000000000001+ },+ {+ "ref": "TP11",+ "x": 109.6,+ "y": 85.2,+ "distanceToSinkMm": 6.049000000000007,+ "clearanceFor2mmRadiusMm": 4.049000000000007+ },+ {+ "ref": "TP6",+ "x": 106.8,+ "y": 82.6,+ "distanceToSinkMm": 8.849000000000004,+ "clearanceFor2mmRadiusMm": 6.849000000000004+ },+ {+ "ref": "TP7",+ "x": 109.6,+ "y": 82.6,+ "distanceToSinkMm": 6.049000000000007,+ "clearanceFor2mmRadiusMm": 4.049000000000007+ },+ {+ "ref": "TP4",+ "x": 100.8,+ "y": 77.2,+ "distanceToSinkMm": 14.849000000000004,+ "clearanceFor2mmRadiusMm": 12.849000000000004+ },+ {+ "ref": "TP3",+ "x": 109.6,+ "y": 80.0,+ "distanceToSinkMm": 6.049000000000007,+ "clearanceFor2mmRadiusMm": 4.049000000000007+ },+ {+ "ref": "TP2",+ "x": 106.8,+ "y": 80.0,+ "distanceToSinkMm": 8.849000000000004,+ "clearanceFor2mmRadiusMm": 6.849000000000004+ },+ {+ "ref": "TP1",+ "x": 104.0,+ "y": 80.0,+ "distanceToSinkMm": 11.649000000000001,+ "clearanceFor2mmRadiusMm": 9.649000000000001+ },+ {+ "ref": "TP9",+ "x": 104.0,+ "y": 85.2,+ "distanceToSinkMm": 11.649000000000001,+ "clearanceFor2mmRadiusMm": 9.649000000000001+ },+ {+ "ref": "TP5",+ "x": 104.0,+ "y": 82.6,+ "distanceToSinkMm": 11.649000000000001,+ "clearanceFor2mmRadiusMm": 9.649000000000001+ },+ {+ "ref": "TP10",+ "x": 106.8,+ "y": 85.2,+ "distanceToSinkMm": 8.849000000000004,+ "clearanceFor2mmRadiusMm": 6.849000000000004+ },+ {+ "ref": "TP8",+ "x": 100.8,+ "y": 80.0,+ "distanceToSinkMm": 14.849000000000004,+ "clearanceFor2mmRadiusMm": 12.849000000000004+ },+ {+ "ref": "TP12",+ "x": 104.0,+ "y": 66.0,+ "distanceToSinkMm": 11.649000000000001,+ "clearanceFor2mmRadiusMm": 9.649000000000001+ }+ ],+ "probeConflicts": [],+ "nominalWasherCandidate": {+ "mpn": "7721-7PPSG",+ "manufacturer": "Boyd",+ "shoulderODMm": 3.43,+ "boreMm": 2.95,+ "shoulderLengthMm": 0.81,+ "flangeODMm": 5.46,+ "flangeThicknessMm": 1.02,+ "catalogScrew": "#4",+ "qualification": "Nominal only: stem coverage, tolerances, screw/nut stack and tool access unresolved"+ },+ "sources": {+ "sink": "https://wakefieldthermal.com/content/catalogs/2019_Catalog.pdf",+ "sinkCatalogPrintedPage": 75,+ "washer": "https://info.boydcorp.com/hubfs/Thermal/Air-Cooling/Boyd-Board-Level-Heatsinks-Catalog.pdf",+ "washerCatalogPrintedPage": 96+ },+ "unresolved": [+ "Exact manufacturer CAD and tab contact area",+ "Sink hole location tolerances and drawing orientation verification",+ "Electrical insulation, pad hole, shoulder coverage and clamp pressure",+ "Fastener length, underside height and assembly tool access",+ "Independent cradle support; never suspend fan/sink mass from transistor leads",+ "Fan plenum, guard, cable restraint and connector mating/service envelopes",+ "Installed airflow and physical thermal/fault qualification"+ ]+}
mechanical/cooling-680-screen.pngadded⋯ 1 unchanged line ⋯
tools/cooling_body_audit.py+7−3@@ -1,12 +1,16 @@ """Conservative fitted STEP bounds versus proposed solid cooling envelope. No exact MPN, mating-connector or mounting qualification is implied. """-import json,math,itertools,hashlib+import json,math,itertools,hashlib,argparse from pathlib import Path import cadquery as cq import sexp p=Path(__file__).resolve().parents[1];board=p/'kicad/adom-custom-electronic-load.kicad_pcb';b=sexp.parse(board.read_text());rows=[];cache={}-sink=[112,35,4.655,162,85,14.655]+parser=argparse.ArgumentParser(description=__doc__)+parser.add_argument('--sink',nargs=6,type=float,default=[112,35,4.655,162,85,14.655])+parser.add_argument('--output',default='mechanical/cooling-body-audit.json')+args=parser.parse_args();sink=args.sink+assert all(math.isfinite(v)for v in sink)and all(sink[i+3]>sink[i]for i in range(3)), 'Invalid cooling envelope' for f in sexp.find(b,'footprint'): props={v[1]:v[2]for v in sexp.find(f,'property')};ref=props['Reference'];at=list(map(float,sexp.first(f,'at')[1:]));a=math.radians(at[2]if len(at)>2 else 0) for m in sexp.find(f,'model'):@@ -16,4 +20,4 @@ for f in sexp.find(b,'footprint'): if str(path)not in cache: bb=cq.importers.importStep(str(path)).val().BoundingBox();cache[str(path)]=[bb.xmin,bb.ymin,bb.zmin,bb.xmax,bb.ymax,bb.zmax] bb=cache[str(path)];pts=[(at[0]+math.cos(a)*x-math.sin(a)*y,at[1]-math.sin(a)*x-math.cos(a)*y,z)for x,y,z in itertools.product([bb[0],bb[3]],[bb[1],bb[4]],[bb[2],bb[5]])];bounds=[min(t[i]for t in pts)for i in range(3)]+[max(t[i]for t in pts)for i in range(3)];row['boundsMm']=bounds;row['sinkIntersection']=all(max(bounds[i],sink[i])<min(bounds[i+3],sink[i+3])for i in range(3));row['underSinkXY']=all(max(bounds[i],sink[i])<min(bounds[i+3],sink[i+3])for i in range(2));rows.append(row)-r={'boardSha256':hashlib.sha256(board.read_bytes()).hexdigest(),'method':'Conservative transformed fitted STEP bounding boxes, board XY with Z above top copper; zero local model transforms only','sinkEnvelopeMm':sink,'coverage':{'models':len(rows),'unsupported':sum(bool(x.get('unsupported'))for x in rows)},'bodyIntersections':[x['ref']for x in rows if x.get('sinkIntersection')],'rows':rows,'limitations':['Bounding boxes can overestimate actual material','No mating plugs, cables, clamps, TIM tolerances or duct','Q1 nominal case contact must be verified against exact package drawing']};(p/'mechanical/cooling-body-audit.json').write_text(json.dumps(r,indent=2));print(json.dumps({k:v for k,v in r.items()if k!='rows'}))+r={'boardSha256':hashlib.sha256(board.read_bytes()).hexdigest(),'method':'Conservative transformed fitted STEP bounding boxes, board XY with Z above top copper; zero local model transforms only','sinkEnvelopeMm':sink,'coverage':{'models':len(rows),'unsupported':sum(bool(x.get('unsupported'))for x in rows)},'bodyIntersections':[x['ref']for x in rows if x.get('sinkIntersection')],'rows':rows,'limitations':['Bounding boxes can overestimate actual material','No mating plugs, cables, clamps, TIM tolerances or duct','Q1 nominal case contact must be verified against exact package drawing']};(p/args.output).write_text(json.dumps(r,indent=2));print(json.dumps({k:v for k,v in r.items()if k!='rows'}))
tools/plot_stock_cooling.pyadded+25@@ -0,0 +1,25 @@+"""Plot the current-board stock-sink envelope screen, never an exact assembly drawing."""+import json+from pathlib import Path+import matplotlib+matplotlib.use('Agg')+import matplotlib.pyplot as plt+from matplotlib.patches import Rectangle,Circle,FancyBboxPatch+P=Path(__file__).resolve().parents[1]+a=json.loads((P/'mechanical/cooling-680-body-audit.json').read_text());s=json.loads((P/'mechanical/cooling-680-screen.json').read_text());assert a['boardSha256']==s['boardSha256']+plt.style.use('dark_background');fig,ax=plt.subplots(figsize=(11,10));fig.patch.set_facecolor('#101723');ax.set_facecolor('#101723')+ax.add_patch(FancyBboxPatch((98,30),64,72,boxstyle='round,pad=0,rounding_size=2',facecolor='#123a32',edgecolor='#8fa99c',lw=2))+for r in a['rows']:+ b=r.get('boundsMm')+ if b and b[5]>=0:ax.add_patch(Rectangle((b[0],b[1]),b[3]-b[0],b[4]-b[1],facecolor='#70828d',edgecolor='#a6b0b8',alpha=.55,lw=.4))+x0,y0,x1,y1=s['sinkXY'];ax.add_patch(Rectangle((x0,y0),x1-x0,y1-y0,facecolor='#60d5cb',edgecolor='#60d5cb',alpha=.16,lw=2));ax.add_patch(Rectangle((x0,y0),x1-x0,y1-y0,fill=False,edgecolor='#60d5cb',lw=2))+for p in s['probeChecks']:+ ax.add_patch(Circle((p['x'],p['y']),2,fill=False,edgecolor='#f7ca78',lw=1.2));ax.text(p['x']+2.4,p['y']+.8,p['ref'],fontsize=8,color='#f7ca78')+hx,hy=s['existingQ1HoleXY'];ax.add_patch(Circle((hx,hy),1.75,fill=False,edgecolor='#ffffff',lw=1.8));ax.annotate('Existing Q1 hole\nNo new PCB drill proposed',xy=(hx,hy),xytext=(101,55),fontsize=10,arrowprops={'arrowstyle':'->','color':'white'},color='white')+ax.text(139,77,'Stock 680-125220\n45.974 mm square\nNominal base Z = 5.09 mm',ha='center',va='center',fontsize=11,color='#a9f2e8',bbox={'facecolor':'#101723','alpha':.85,'edgecolor':'none'})+ax.set(xlim=(93,171),ylim=(107,25),xlabel='Board X (mm)',ylabel='Board Y (mm)');ax.set_aspect('equal');ax.spines[['top','right']].set_visible(False)+fig.suptitle('Stock heatsink candidate · board 18',fontsize=20,y=.97)+fig.text(.5,.924,'91 fitted models: no bounding-box intersection • Probe approach circles: clear',ha='center',fontsize=11,color='#b8cecd')+fig.text(.5,.044,'ENVELOPE SCREEN ONLY — not accepted for fabrication\nFasteners, support cradle, exact contact, mating plugs and installed airflow remain unresolved.',ha='center',fontsize=11,color='#f7ca78')+fig.subplots_adjust(top=.9,bottom=.12,left=.08,right=.94)+fig.savefig(P/'mechanical/cooling-680-screen.png',dpi=160,facecolor=fig.get_facecolor())
tools/screen_stock_cooling.pyadded+33@@ -0,0 +1,33 @@+"""Stock TO-220 sink envelope screen against the current PCB, not assembly acceptance."""+import hashlib,json,math+from pathlib import Path+import sexp+P=Path(__file__).resolve().parents[1]+board=P/'kicad/adom-custom-electronic-load.kicad_pcb'+a=json.loads((P/'mechanical/cooling-680-body-audit.json').read_text())+assert a['boardSha256']==hashlib.sha256(board.read_bytes()).hexdigest()+b=sexp.parse(board.read_text()); footprints=sexp.find(b,'footprint'); probes=[]+q=next(f for f in footprints if any(p[1:3]==['Reference','Q1'] for p in sexp.find(f,'property')))+x,y,theta=map(float,sexp.first(q,'at')[1:]);theta=math.radians(theta)+hole=next(p for p in sexp.find(q,'pad') if p[2]=='np_thru_hole')+u,v=map(float,sexp.first(hole,'at')[1:3]);hx=x+u*math.cos(theta)+v*math.sin(theta);hy=y-u*math.sin(theta)+v*math.cos(theta)+# Manufacturer inch dimensions: hole at (-.440,-.070) relative to sink center.+cx,cy=hx+.440*25.4,hy+.070*25.4;half=1.810*25.4/2+box=[cx-half,cy-half,cx+half,cy+half]+assert all(abs(box[i]-a['sinkEnvelopeMm'][j])<1e-6 for i,j in enumerate([0,1,3,4]))+for f in footprints:+ props={p[1]:p[2]for p in sexp.find(f,'property')};ref=props['Reference']+ if not ref.startswith('TP'):continue+ px,py=map(float,sexp.first(f,'at')[1:3]);distance=math.hypot(max(box[0]-px,0,px-box[2]),max(box[1]-py,0,py-box[3]))+ probes.append({'ref':ref,'x':px,'y':py,'distanceToSinkMm':distance,'clearanceFor2mmRadiusMm':distance-2})+result={'status':'nominal-stock-sink-candidate','acceptance':False,'boardSha256':a['boardSha256'],+ 'mpn':'680-125220','manufacturer':'Wakefield Thermal','sinkCenterXY': [cx,cy], 'sinkXY':box,+ 'heightMm':31.75,'existingQ1HoleXY':[hx,hy], 'existingPcbDrillMm':float(sexp.first(hole,'drill')[1]),+ 'stockSinkDeviceDrillMm':.140*25.4,'proposedAdditionalPcbDrills':0,+ 'fittedModelCount':a['coverage']['models'],'bodyConflicts':a['bodyIntersections'],+ 'probeChecks':probes,'probeConflicts':[p['ref']for p in probes if p['clearanceFor2mmRadiusMm']<0],+ 'nominalWasherCandidate':{'mpn':'7721-7PPSG','manufacturer':'Boyd','shoulderODMm':3.43,'boreMm':2.95,'shoulderLengthMm':.81,'flangeODMm':5.46,'flangeThicknessMm':1.02,'catalogScrew':'#4','qualification':'Nominal only: stem coverage, tolerances, screw/nut stack and tool access unresolved'},+ 'sources':{'sink':'https://wakefieldthermal.com/content/catalogs/2019_Catalog.pdf','sinkCatalogPrintedPage':75,'washer':'https://info.boydcorp.com/hubfs/Thermal/Air-Cooling/Boyd-Board-Level-Heatsinks-Catalog.pdf','washerCatalogPrintedPage':96},+ 'unresolved':['Exact manufacturer CAD and tab contact area','Sink hole location tolerances and drawing orientation verification','Electrical insulation, pad hole, shoulder coverage and clamp pressure','Fastener length, underside height and assembly tool access','Independent cradle support; never suspend fan/sink mass from transistor leads','Fan plenum, guard, cable restraint and connector mating/service envelopes','Installed airflow and physical thermal/fault qualification']}+(P/'mechanical/cooling-680-screen.json').write_text(json.dumps(result,indent=2)+'\n')+print(json.dumps({k:v for k,v in result.items() if k not in ['probeChecks','unresolved','sources']},indent=2))