Skip to content

fix(to220): standard 2.54mm lead pitch and KiCad TO-220-3 pads - #791

Open
zkasuran wants to merge 2 commits into
tscircuit:mainfrom
zkasuran:fix/to220-kicad-pitch
Open

fix(to220): standard 2.54mm lead pitch and KiCad TO-220-3 pads#791
zkasuran wants to merge 2 commits into
tscircuit:mainfrom
zkasuran:fix/to220-kicad-pitch

Conversation

@zkasuran

@zkasuran zkasuran commented Aug 8, 2026

Copy link
Copy Markdown

Summary

to220 now emits the KiCad TO-220-3_Vertical land pattern: a fixed 2.54mm lead pitch, a rectangular pin-1 pad and pill lead pads. Previously it placed plain circular holes on a body-width-derived pitch.

Fixes #790.

The bug

The pitch was computed from the body width:

const minPitch = 2.5
const maxHoleWidth = w * 0.4
const computedPitch = Math.max(minPitch, maxHoleWidth / (numPins - 1))

For the default 3-pin part (w = 13mm) that gives 2.6mm, not the JEDEC TO-220 pitch of 0.1 inch (2.54mm). It also drifts with the body width and left the declared p parameter unused. The to220f sibling already hardcodes 2.54mm with the comment TO-220F uses 2.54mm standard pitch to match KiCad, so to220 was the odd one out.

The fix

Use a fixed 2.54mm pitch (now honoring p) and build the KiCad TO-220-3 land with platedHoleWithRectPad for pin 1 and platedHolePill for the rest, the same helpers to220f uses. to220f itself is untouched: it still overrides the holes for its own 1.2mm drill.

Parity (repo harness vs Package_TO_SOT_THT.pretty/TO-220-3_Vertical)

before after
avgRelDiff (copper) 36.52% 0.00%
courtyardDiffPercent 17.02% 11.77%

The copper now matches KiCad exactly. The residual courtyard delta is the shared TO-220 body outline: KiCad draws a slightly tighter courtyard for the metal-tab TO-220-3 than for TO-220F, while footprinter uses one body courtyard for both variants (to220f still matches TO-220F-3 within 0.5%).

Tests

  • new tests/kicad-parity/to220_3_kicad_parity.test.ts asserting avgRelDiff < 0.01 plus courtyardDiffPercent < 13, with SVG and boolean-difference snapshots
  • refreshed the to220_2/3/4/5 render snapshots

Verified locally

  • bun test: 522 pass, 0 fail
  • bun run build: success
  • bunx biome format .: clean

AI disclosure

AI assistance (Claude, Anthropic) was used in developing this change. The design, review and verification were done by the author. Verified locally before submitting: bun test (522 pass, 0 fail), bun run build, bunx biome format ..

to220 derived its pin pitch from the body width
(Math.max(2.5, w*0.4/(numPins-1))), so the default 3-pin part landed on
2.6mm instead of the JEDEC 0.1 inch (2.54mm) pitch. The pitch also drifted
whenever the body width changed and the `p` parameter was ignored. Pads
were plain circular holes rather than KiCad's rectangular pin-1 pad with
pill lead pads.

Emit the KiCad TO-220-3_Vertical land instead: a fixed 2.54mm pitch that
honors `p`, a rectangular pin-1 pad and pill lead pads. This mirrors the
to220f sibling, whose own comment notes it uses 2.54mm "to match KiCad".
Against TO-220-3_Vertical the copper parity (avgRelDiff) drops from 36.52%
to 0.00% and courtyardDiffPercent from 17.02% to 11.77%. to220f is
unchanged.

Add tests/kicad-parity/to220_3_kicad_parity.test.ts and refresh the
to220 render snapshots.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add KiCad tests for the footprints you changed.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added tests/kicad-parity/to220_4_kicad_parity.test.ts in db11e19, matching the to220_3 parity that was already in the PR. Against Package_TO_SOT_THT.pretty/TO-220-4_Vertical the copper matches KiCad exactly (avgRelDiff 0.00%) with courtyardDiffPercent 11.77%, the same residual body-outline delta as to220_3, so it reuses the same < 13 courtyard threshold and ships the SVG plus boolean-difference snapshots.

That gives KiCad parity for both fixed 2.54mm-grid variants (to220_3 and to220_4). I deliberately did not add parity for the other two changed footprints, because their KiCad references are not on a 2.54mm pitch and a passing assertion there would need a threshold that certifies nothing:

  • TO-220-2_Vertical is a 5.08mm land (the two outer leads of the frame), so the fixed 2.54mm part measures avgRelDiff 29.40% / courtyardDiffPercent 17.15% against it.
  • TO-220-5_Vertical is the 1.7mm Multiwatt land, so 2.54mm measures avgRelDiff 36.03% / courtyardDiffPercent 24.30%.

Both keep their render snapshots in tests/to220.test.ts. If you want real KiCad parity across every pin count I can follow up with a per-pin-count pitch (5.08mm for the 2-pin, 1.7mm for the 5-pin) so to220_2 and to220_5 land on their KiCad packages too. That is wider than #790, which is why I scoped this PR to the 2.54mm land. Happy to fold it in here or open a separate PR, your call.

bun test on the to220 files is green (9 pass) and bun run build succeeds.

to220_4 uses the same 2.54mm JEDEC grid as the to220_3 this PR already covers, so it matches KiCad TO-220-4_Vertical exactly: copper avgRelDiff 0.00% and courtyardDiffPercent 11.77% (the same residual body-outline delta as to220_3). Adds the parity assertion plus the SVG and boolean-difference snapshots, mirroring to220_3_kicad_parity.test.ts.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

to220 uses a body-width-derived pin pitch (2.6mm) instead of the standard 2.54mm

2 participants