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:
@@ -0,0 +1,93 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Add nominal STEP-derived metal bounding projections on Dwgs.User only.
|
||||
|
||||
Not silkscreen, a courtyard, or a case cutout. See db9-mechanical-notes.md for
|
||||
source attribution, selected face subsets and the user-confirmed male/female
|
||||
external-geometry equivalence. No module height or case-wall thickness assumed.
|
||||
"""
|
||||
import json
|
||||
from pathlib import Path
|
||||
import uuid
|
||||
import pcbnew as p
|
||||
|
||||
ROOT=Path(__file__).resolve().parent
|
||||
PCB=ROOT/"serial-carrier.kicad_pcb"
|
||||
NS=uuid.UUID("ba7274a8-c35d-46bc-908d-cd86708fc6c4")
|
||||
|
||||
|
||||
def main():
|
||||
lock=ROOT/"~serial-carrier.kicad_pcb.lck"
|
||||
if lock.exists():
|
||||
raise SystemExit("Close PCB Editor before refreshing the CAD envelopes")
|
||||
before=PCB.read_bytes()
|
||||
project=ROOT/"serial-carrier.kicad_pro"
|
||||
project_before=project.read_bytes()
|
||||
board=p.LoadBoard(str(PCB))
|
||||
u2=next(f for f in board.GetFootprints() if f.GetReference()=="U2")
|
||||
assert u2.GetOrientationDegrees()==0, "Review transform for rotated module"
|
||||
x0,y0=p.ToMM(u2.GetPosition().x),p.ToMM(u2.GetPosition().y)
|
||||
data=json.loads((ROOT/"reference/db9-cad/measurements.json").read_text())
|
||||
owned={str(uuid.uuid5(NS,str(i))) for i in range(64)}
|
||||
for drawing in list(board.GetDrawings()):
|
||||
if drawing.m_Uuid.AsString() in owned:
|
||||
board.Delete(drawing)
|
||||
count=0
|
||||
|
||||
def point(x,y):
|
||||
# STEP/Eagle axes +Y toward connector; KiCad local Y is downward.
|
||||
return p.VECTOR2I(p.FromMM(x0+x-1.905),p.FromMM(y0+2.667-y))
|
||||
|
||||
def add(item):
|
||||
nonlocal count
|
||||
assert count<64
|
||||
item.SetLayer(p.Dwgs_User)
|
||||
item.SetUuid(p.KIID(str(uuid.uuid5(NS,str(count)))))
|
||||
board.Add(item)
|
||||
count+=1
|
||||
|
||||
for feature in ("front_flange_exposed_faces", "shell_outer_including_root_and_lip",
|
||||
"left_front_hex_post", "right_front_hex_post"):
|
||||
xmin,ymin,_,xmax,ymax,_=data[feature]["bounds"]
|
||||
rect=p.PCB_SHAPE(board)
|
||||
rect.SetShape(p.SHAPE_T_RECT)
|
||||
rect.SetStart(point(xmin,ymax)); rect.SetEnd(point(xmax,ymin))
|
||||
rect.SetWidth(p.FromMM(0.1))
|
||||
add(rect)
|
||||
for axis in data["front_lock_axes"]:
|
||||
x=axis["location"][0]
|
||||
# These mark front-facing Y axes, not holes through the carrier PCB.
|
||||
line=p.PCB_SHAPE(board)
|
||||
line.SetShape(p.SHAPE_T_SEGMENT)
|
||||
line.SetStart(point(x,26.907)); line.SetEnd(point(x,32.707))
|
||||
line.SetWidth(p.FromMM(0.08))
|
||||
add(line)
|
||||
label=p.PCB_TEXT(board)
|
||||
label.SetText("CAD METAL ENVELOPES - NOT CASE CUTOUT")
|
||||
label.SetPosition(p.VECTOR2I(p.FromMM(x0+13.97),p.FromMM(y0-17.67)))
|
||||
label.SetTextSize(p.VECTOR2I(p.FromMM(0.65),p.FromMM(0.65)))
|
||||
label.SetTextThickness(p.FromMM(0.1))
|
||||
add(label)
|
||||
for drawing in board.GetDrawings():
|
||||
if not isinstance(drawing,p.PCB_TEXT):
|
||||
continue
|
||||
value=drawing.GetText()
|
||||
if value.startswith("DE-9 OUT /"):
|
||||
drawing.SetPosition(p.VECTOR2I(p.FromMM(x0+13.97),p.FromMM(y0-20.67)))
|
||||
elif value=="82 x 80 mm / 2 copper layers":
|
||||
drawing.SetPosition(p.VECTOR2I(p.FromMM(141),p.FromMM(91)))
|
||||
elif value.startswith("Nominal RS-232 metal verified;"):
|
||||
drawing.SetPosition(p.VECTOR2I(p.FromMM(141),p.FromMM(93.5)))
|
||||
temp=ROOT/"serial-carrier-envelope-tmp.kicad_pcb"
|
||||
try:
|
||||
assert p.SaveBoard(str(temp),board,True)
|
||||
if lock.exists() or PCB.read_bytes()!=before:
|
||||
raise RuntimeError("PCB changed or reopened; refusing overwrite")
|
||||
assert project.read_bytes()==project_before
|
||||
temp.replace(PCB)
|
||||
finally:
|
||||
temp.unlink(missing_ok=True)
|
||||
print(f"Added {count} nominal CAD projection graphics on Dwgs.User; no copper/project changes")
|
||||
|
||||
|
||||
if __name__=="__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user