Integrate A1 carrier PCB CAD updates
- Add pinned STEP-derived DE-9 mechanical measurements and provenance - Refresh placement, routing, silkscreen, and nominal CAD envelopes - Document provisional dimensions, assumptions, and validation status
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
Requires KiCad's pcbnew binding in system Python. The known U2 footprint parity
|
||||
warning is reported explicitly, not hidden or added to KiCad's exclusions.
|
||||
"""
|
||||
import hashlib
|
||||
import json
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
@@ -29,7 +30,33 @@ assert p.ToMM(board.GetDesignSettings().GetBoardThickness())==1.6
|
||||
outline=[d for d in board.GetDrawings() if d.GetLayer()==p.Edge_Cuts]
|
||||
assert len(outline)==6
|
||||
points={(round(p.ToMM(v.x)-100,5),round(p.ToMM(v.y)-100,5)) for d in outline for v in (d.GetStart(),d.GetEnd())}
|
||||
assert points=={(0,0),(82,0),(82,80),(36,80),(36,61),(0,61)}
|
||||
expected_outline=[(36,0),(82,0),(82,80),(0,80),(0,19),(36,19)]
|
||||
assert points==set(expected_outline)
|
||||
expected_edges={frozenset((a,b)) for a,b in zip(expected_outline,expected_outline[1:]+expected_outline[:1])}
|
||||
actual_edges={frozenset((round(p.ToMM(v.x)-100,5),round(p.ToMM(v.y)-100,5))
|
||||
for v in (d.GetStart(),d.GetEnd())) for d in outline}
|
||||
assert actual_edges==expected_edges
|
||||
placements={"U1":(8,23),"U2":(43,26.670),"DS1":(43,36),
|
||||
"R1":(43,34),"R2":(54,34),"R3":(65,34),
|
||||
"SW1":(43,68),"SW2":(55,68),"SW3":(67,68),
|
||||
"H1":(3.5,22.5),"H2":(3.5,75),"H3":(78,4),"H4":(78,76)}
|
||||
for ref,(x,y) in placements.items():
|
||||
position=footprints[ref].GetPosition()
|
||||
assert position.x==p.FromMM(x+100) and position.y==p.FromMM(y+100),ref
|
||||
assert footprints[ref].GetOrientationDegrees()==0,ref
|
||||
assert len(board.Zones())==1
|
||||
reserve=board.Zones()[0]
|
||||
assert reserve.GetIsRuleArea() and reserve.IsOnLayer(p.F_Cu) and reserve.IsOnLayer(p.B_Cu)
|
||||
assert reserve.GetDoNotAllowTracks() and reserve.GetDoNotAllowVias() and reserve.GetDoNotAllowZoneFills()
|
||||
contour=reserve.Outline().COutline(0)
|
||||
assert {(p.ToMM(contour.CPoint(i).x),p.ToMM(contour.CPoint(i).y)) for i in range(contour.PointCount())}=={(110,119),(131,119),(131,132),(110,132)}
|
||||
# Reference bare-PCB front is 26.670 mm above the U2 pad-row origin.
|
||||
u2_front=p.ToMM(footprints['U2'].GetPosition().y)-26.670
|
||||
assert abs(u2_front-100)<1e-6
|
||||
assert any(isinstance(g,p.PCB_SHAPE) and g.GetLayer()==p.F_Fab and
|
||||
g.GetShape()==p.SHAPE_T_SEGMENT and
|
||||
g.GetStart().y==p.FromMM(100) and g.GetEnd().y==p.FromMM(100)
|
||||
for g in footprints['U2'].GraphicalItems()), 'U2 bare-PCB front not flush'
|
||||
assert max(x for x,y in points)-min(x for x,y in points)==82
|
||||
assert max(y for x,y in points)-min(y for x,y in points)==80
|
||||
padnets={}
|
||||
@@ -77,6 +104,13 @@ assert len(parity)==1 and parity[0]["type"]=="footprint_symbol_mismatch",parity
|
||||
assert len(parity[0]["items"])==1 and parity[0]["items"][0]["uuid"]==footprints["U2"].m_Uuid.AsString()
|
||||
summary={
|
||||
"carrier_bounds_mm":[82,80],
|
||||
"outline_local_mm":expected_outline,
|
||||
"placements_local_mm":placements,
|
||||
"rf_reserve_absolute_mm":[110,119,131,132],
|
||||
"u2_bare_pcb_front_local_y_mm":round(u2_front-100,6),
|
||||
"nominal_user_confirmed_rs232_metal_mm":{"shell_overhang":3.870,"hex_mouth_overhang":2.870,"flange_front_inset":1.930},
|
||||
"tracks":sum(not isinstance(t,p.PCB_VIA) for t in tracks),
|
||||
"vias":sum(isinstance(t,p.PCB_VIA) for t in tracks),
|
||||
"copper_layers":2,
|
||||
"draft_thickness_mm":1.6,
|
||||
"electrical_footprints":len(comps),
|
||||
@@ -84,9 +118,10 @@ summary={
|
||||
"physical_DRC_violations":0,
|
||||
"unconnected_items":0,
|
||||
"schematic_pad_nets_match":True,
|
||||
"known_parity_warning":"U2 provisional female-reference footprint assigned on PCB only; schematic footprint intentionally blank",
|
||||
"known_parity_warning":"U2 reference footprint assigned on PCB only; schematic footprint intentionally blank; nominal male external metal dimensions user-confirmed",
|
||||
"project_settings_sha256":hashlib.sha256((ROOT/'serial-carrier.kicad_pro').read_bytes()).hexdigest(),
|
||||
"ignored_DRC_checks":report["ignored_checks"],
|
||||
"not_validated":["male module pin map/fit", "assembly envelope and heights", "header/socket fit", "RF performance and antenna clearance", "power/return-path integrity", "USB power path", "OLED pull-ups", "fabrication process", "hardware operation"],
|
||||
"not_validated":["male module pin map/header fit", "ESP32 geometry and complete assembly envelope/heights", "header/socket fit", "RF performance and antenna clearance", "power/return-path integrity", "USB power path", "OLED pull-ups", "fabrication process", "hardware operation"],
|
||||
}
|
||||
(OUT/"pcb-validation-summary.json").write_text(json.dumps(summary,indent=2)+"\n")
|
||||
print("PCB draft verified: 82 x 80 mm; 2 copper layers; 0 physical DRC violations; 0 unrouted.")
|
||||
|
||||
Reference in New Issue
Block a user