component
JST SM04B-GHS-TB(LF)(SN) GH 4-circuit side entry SMT header
Public Made by Adomby adom
JST GH 1.25 mm pitch, 4 circuits, side entry (right angle) SMT shrouded header with two solder tabs; mates with GHR-04V-S and SSHL-002T-P0.2.
main
#!/usr/bin/env python3
"""Compare the page footprint pad by pad with JST's recommended PC board layout for the side entry GH
header (JST GH catalog eGH.pdf p.1, 'PC board layout and Assembly layout', Side entry type).
JST gives the layout as dimensions, not coordinates. For n = 4 circuits, with KiCad's frame
(origin centred between the solder tabs in X, Y down, the header opening toward +Y):
signal pad 0.6 wide (X) x (5.4 - 3.7) = 1.7 long (Y), pitch 1.25
solder tab pad 1.0 wide (X) x 2.7 long (Y)
tab inner edge 1.35 from the outer signal pad centre (X)
Y reference the tab pads' outer (front) edge; signal pads span 3.7 .. 5.4 behind it
header outline 0.25 behind the tab pads' front edge
circuit 1 the leftmost circuit seen from the mating face (p.2 side entry view) = -X in this
top view (opening toward the viewer at +Y, so the viewer's left is -X)
usage: compare_footprint.py footprint.kicad_mod out.json"""
import json, re, sys
fp = open(sys.argv[1]).read()
pads = []
for m in re.finditer(r'\(pad "([^"]+)" smd (\w+)\s*\(at ([-\d.]+) ([-\d.]+)\)\s*\(size ([-\d.]+) ([-\d.]+)\)', fp):
pads.append(dict(number=m.group(1), shape=m.group(2), x=float(m.group(3)), y=float(m.group(4)), w=float(m.group(5)), h=float(m.group(6))))
n, pitch = 4, 1.25
xs = [(i - (n - 1) / 2) * pitch for i in range(n)] # circuit 1 at -X
tab_cx = xs[-1] + 1.35 + 1.0 / 2 # 3.725
front = None
# the drawing's Y reference: front edge of the tab pads; take it from the footprint's tabs and check the rest relative to it
tabs = [p for p in pads if p['number'] == 'MP']
front = max(p['y'] + p['h'] / 2 for p in tabs)
want = [dict(number=str(i + 1), x=xs[i], y=front - (3.7 + 5.4) / 2, w=0.6, h=1.7) for i in range(n)]
want += [dict(number='MP', x=-tab_cx, y=front - 2.7 / 2, w=1.0, h=2.7), dict(number='MP', x=tab_cx, y=front - 2.7 / 2, w=1.0, h=2.7)]
rows, ok = [], True
for w in want:
p = min((p for p in pads if p['number'] == w['number']), key=lambda p: abs(p['x'] - w['x']) + abs(p['y'] - w['y']))
d = {k: round(p[k] - w[k], 4) for k in ('x', 'y', 'w', 'h')}
good = all(abs(v) < 0.001 for v in d.values())
ok &= good
rows.append(dict(pad=w['number'], jst=dict((k, round(w[k], 4)) for k in ('x', 'y', 'w', 'h')),
footprint=dict((k, p[k]) for k in ('x', 'y', 'w', 'h')), shape=p['shape'], delta=d, match=good))
res = dict(schema='adom/footprint-compare@1', footprint=sys.argv[1],
source='JST GH catalog eGH.pdf p.1, PC board layout, Side entry type (figure viewed from the connector mounting side)',
frame='KiCad footprint frame, mm, Y down, origin centred between the tabs; Y reference = tab pad front edge (y = %.3f)' % front,
pads=rows, pads_in_footprint=len(pads), all_match=ok,
derived_checks=dict(signal_row_to_tab_centre_y=round(want[0]['y'] - want[4]['y'], 3),
signal_pad_rear_edge_from_reference=5.4, signal_pad_front_edge_from_reference=3.7,
tab_centre_x=tab_cx, header_outline_front_y=round(front - 0.25, 3)),
notes=['KiCad draws the pads as rounded rectangles (roundrect_rratio 0.25: 0.15 mm corner radius on the signal pads, 0.25 mm on the tabs); JST draws plain rectangles. Pad extents match exactly; the copper area is slightly smaller at the corners.',
'KiCad F.Fab body outline: y -1.6 .. 2.45 (4.05 deep, JST p.2 side view 4.05) and x +-4.125 (8.25 = JST dimension B for 4 circuits).',
'Pin 1: footprint pad 1 at x = -1.875, the -X end. JST p.2 side entry view (looking into the mating face, PCB below) labels Circuit No.1 at the left; with the opening toward +Y, the viewer facing the opening has -X on the left. KiCad F.Fab pin-1 chevron and the F.SilkS tick at x = -2.435 are on the same end.'])
json.dump(res, open(sys.argv[2], 'w'), indent=1)
print('all_match', ok, [ (r['pad'], r['match']) for r in rows ])