component
STM32G431CBT6 - Arm Cortex-M4 Microcontroller
Public Made by Adomby adom
STMicroelectronics Microcontrollers (MCU/MPU/SOC), LQFP-48(7x7). Pinout checked against ST's open pin data, KiCad symbol/footprint/3D.
main
John Lauer
3D model from KiCad's own package generator at the datasheet's values: radiused gull-wing leads in matte tin, reviewed…
9ad862b
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
#!/usr/bin/env python3
"""Run KiCad's own gull-wing generator (kicad-packages3D-generator, GW_QFP_SOIC_SSOP_TSSOP_SOT/make_gw,
CadQuery) on a datasheet parameter set, tuning the generator's flat-foot length L until the foot measured
to the 0.25 mm gauge plane (JEDEC L) equals the datasheet value.
usage: kgen.py base_model_key overrides.json out.step (overrides: generator params + "gauge_L" target)
Prints JSON: params used, measured gauge L, bbox. The STEP holds three named parts: body, pins, mark
(KiCad's own colours), exported like the generator does (one assembly)."""
import sys, os, json, copy
REPO = os.path.expanduser("~/project/kicad-gen/kicad-packages3D-generator")
sys.path.insert(0, REPO)
import yaml, cadquery as cq
from OCP.BRepAlgoAPI import BRepAlgoAPI_Section
from OCP.gp import gp_Pln, gp_Pnt, gp_Dir
from GW_QFP_SOIC_SSOP_TSSOP_SOT.gw_qfp_soic_ssop_tssop_sot import make_gw
from _tools import shaderColors
key, ov, out = sys.argv[1], json.load(open(sys.argv[2])), sys.argv[3]
LEAD_Y = ov.pop("lead_y", None)
base = yaml.safe_load(open(os.path.join(REPO, "GW_QFP_SOIC_SSOP_TSSOP_SOT/cq_parameters.yaml")))[key]
P = copy.deepcopy(base); target = ov.pop("gauge_L", None); P.update(ov)
def build(p):
body, pins, mark = make_gw(p)
r = p["rotation"]
return [s.rotate((0, 0, 0), (0, 0, 1), r) for s in (body, pins, mark)]
def gauge_L(pins, y=None):
"""JEDEC L: lead tip to where the lead's lower outer surface crosses z = 0.25, on a section through
one lead's centre line, on the -x row."""
s = pins.val() if hasattr(pins, "val") else pins
bb = s.BoundingBox()
# find a lead centre on the -x row: section at x just inside the tip, take the first foot's y range
if y is None:
# the lead nearest y = 0 on the -x row: cluster the foot section's edges into leads, take a centre
sx = BRepAlgoAPI_Section(s.wrapped, gp_Pln(gp_Pnt(bb.xmin + 0.05, 0, 0), gp_Dir(1, 0, 0))); sx.Build()
ys = sorted(set(round(v.Y, 4) for v in cq.Shape.cast(sx.Shape()).Vertices()))
leads, cur = [], [ys[0]]
for v in ys[1:]:
if v - cur[-1] > 0.05: leads.append(cur); cur = [v]
else: cur.append(v)
leads.append(cur)
y = sorted(((l[0] + l[-1]) / 2 for l in leads), key=abs)[0]
sec = BRepAlgoAPI_Section(s.wrapped, gp_Pln(gp_Pnt(0, y, 0), gp_Dir(0, 1, 0))); sec.Build()
prof = cq.Shape.cast(sec.Shape())
sec2 = BRepAlgoAPI_Section(prof.wrapped, gp_Pln(gp_Pnt(0, 0, 0.25), gp_Dir(0, 0, 1))); sec2.Build()
xs = sorted(v.X for v in cq.Shape.cast(sec2.Shape()).Vertices() if v.X < 0)
tip = prof.BoundingBox().xmin
return round(xs[0] - tip, 4), round(y, 3)
parts = build(P)
L_meas, ylead = gauge_L(parts[1], LEAD_Y)
if target is not None:
# the generator's L is the flat foot; the gauge-plane L grows with it 1:1, so a few secant steps do
for _ in range(6):
if abs(L_meas - target) < 0.0005: break
P["L"] = P.get("L") or ((P["E"] - P["E1"]) / 2 - (P["S"] + P["R1"]))
P["S"] = None; P["L"] = round(P["L"] + (target - L_meas), 5); P.pop("S", None)
parts = build(P); L_meas, ylead = gauge_L(parts[1], LEAD_Y)
cols = {k: shaderColors.named_colors[P[k]].getDiffuseFloat() for k in ("body_color_key", "pin_color_key", "mark_color_key")}
asm = cq.Assembly(name=P["model_name"])
for name, s, ck in zip(("body", "pins", "mark"), parts, ("body_color_key", "pin_color_key", "mark_color_key")):
c = cols[ck]; asm.add(s, name=name, color=cq.Color(c[0], c[1], c[2]))
asm.save(out, "STEP")
allb = cq.Compound.makeCompound([p.val() if hasattr(p, "val") else p for p in parts]).BoundingBox()
print(json.dumps(dict(model=P["model_name"], params={k: P[k] for k in sorted(P) if k not in ("source",)}, gauge_L=L_meas, lead_y=ylead,
bbox=[round(v, 3) for v in (allb.xmin, allb.xmax, allb.ymin, allb.ymax, allb.zmin, allb.zmax)], colours=cols)))