tools/epro2/kicad: fix two structural ERC bugs — wire_dangling -88%, pin_not_connected -52%

Bisect found two semantics mismatches between EPRO2 and KiCad that cause
the 850 real-connectivity ERC violations on the ESP-VoCat ref project:

1. sym_writer was emitting lib coords without negating Y, but KiCad lib
   uses Y-up and re-flips Y on placement (Y-down schematic). So vertically
   arranged pins ended up at Y-mirrored absolute positions and wires that
   reach the geometric pin tip in EPRO2 missed the rendered pin tip in
   KiCad. Fix: lib_y = -epro2_y, lib_rot = (360 - rot) % 360 for pin/text.

2. sch_writer was treating each LINE as an isolated wire — but EPRO2
   binds segments into nets by NAME (WIRE.NET attr), not just geometry.
   Multi-segment nets like GND/VBUS show up as N disconnected stubs to
   KiCad. Fix: per-LINE, look up lineGroup → WIRE → NET attr and emit a
   `(label "<NET>")` at the LINE's start. Same-named labels on distinct
   physical wires is how KiCad's ERC recognizes a multi-segment net.

ESP-VoCat 9 sheets:
  wire_dangling           444 →  52  (-88%)
  pin_not_connected       406 → 196  (-52%)
  real connectivity total 850 → 248  (-71%)

Why we did NOT round to grid (the obvious-looking fix): EPRO2 places
some pins on a 10-mil pitch (e.g. magnetic socket); rounding to KiCad's
default 50-mil ERC grid would collapse those pins. The 248 residual is
fundamentally cross-sheet — single-sheet ERC can't see a net's other
endpoints on sibling sheets — and is a Phase-3 (hierarchical sheet)
problem, not a per-sheet one.

41 → 46 unit tests pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-28 23:43:11 +08:00
parent 5e63924474
commit 54f0173947
6 changed files with 197 additions and 15 deletions

44
log.md
View File

@@ -4,6 +4,50 @@
---
## 2026-04-28 23:55 KiCad 导出修真实连接错wire_dangling -88%, pin_not_connected -52%
**Claude 会话**
`fb577cc` 后续。Handoff 选项 #1:用 ERC violation 数从 850 降到接近 0 作为目标。Bisect 出两个根因,都是结构性的 KiCad 语义错(不是浮点 / 精度问题,所以 grid round 不是答案):
### Bug A — sym_writer 漏 Y-flip
KiCad lib symbol 是 Y-upschematic 是 Y-downplacement 时 KiCad 会再翻一次 Y。我们把 EPRO2 (Y-down) 的 PIN/RECT/POLY/CIRCLE/TEXT 坐标直接当 lib coord 写KiCad 的翻转就把整个 symbol body 上下镜像了。U8 4-pin 磁吸座实测pin 1↔4 对调、2↔3 对调,结果 wire 端点跟错位的 pin tip 撞不上 → ERC 报 pin_not_connected + wire_dangling。修法`lib_y = -epro2_y`pin/text rotation 也镜像 `lib_rot = (360 - rot) % 360`
### Bug B — 没发 net labelKiCad 看不出 EPRO2 的命名网络
EPRO2 的 WIRE op 带 NET attr`TXD` / `GND` / `VBUS` ……),多段 LINE 通过同名 NET 连成一个网,**不需要几何相邻**。KiCad 不知道这套,只看几何。修法:在 sch_writer 里查每条 LINE 的 `lineGroup → WIRE → NET attr`,命中就在 LINE 起点 emit 一个 `(label "<NET>")`。同名 label 在多条物理 wire 上 → KiCad ERC 才认这是同一个网。**per-LINE 不是 per-WIRE**:单个 WIRE id 下面的 LINE 段不一定共端点,每段都得有 label 才不被判 dangling。
### ESP-VoCat 9 sheets ERC 对比
| Type | baseline | after | Δ |
|---|---:|---:|---:|
| wire_dangling | 444 | 52 | **88%** |
| pin_not_connected | 406 | 196 | **52%** |
| **real connectivity 合计** | **850** | **248** | **71%** |
| label_dangling | 0 | 111 | new (warn) |
| pin_not_driven | 0 | 23 | new (connector pin 类型问题) |
| endpoint_off_grid | 1372 | 1372 | unchanged (cosmetic, EPRO2 用 30/20/10 mil pitch不在 KiCad 50 mil 网格上;不能 round——会把 < 50 mil 的 pin 间距压到一起) |
| lib_symbol_issues | 571 | 571 | unchanged (没注册 facere libcosmetic) |
剩余 248 real-connectivity 错主要是 single-sheet ERC 的天然限制:很多网只在一个 sheet 上有这一个 pin对端在别的 sheet。kicad-cli 一次只看一个 .kicad_sch看不见跨 sheet。彻底修要 Phase 3hierarchical 顶层 + sheet links
### 关键决策(记 Why
- **不 round to grid**50 mil grid 会塌缩 < 50 mil pin pitch实测 4-pin 磁吸座是 10 mil pitch破坏几何。EPRO2 源已经在整数 mil浮点不是 root cause。
- **per-LINE label 不是 per-WIRE**:同 WIRE id 下两条 LINE 段不共端点是常态(不同地方各连一段),都得 label 才不孤立。
- **用 `(label)` 不是 `(global_label)`**实验过两种语法single-sheet ERC 都判 dangling因为这个 sheet 上只出现一次);语义上 EPRO2 net 全局,但 single-sheet 校验视角看不见跨 sheet换 global_label 帮不上。Phase 3 hierarchical 重构时再切。
- **不做 ERC config tweak**KiCad 8 的 connection grid 是硬编码 50 milschematic 文件里没法配;想消 endpoint_off_grid 必须破坏 EPRO2 几何或者升级到 KiCad 9 + custom severity。
### 测试
41 → 46 单测全过:新增 `test_pin_y_negated_for_kicad_lib_y_up_convention` / `test_pin_rotation_mirrored_to_compensate_y_flip` / `test_rect_y_negated` / `test_named_wire_emits_label_at_line_start` / `test_unnamed_wire_emits_no_label`
### 下一步建议
- Phase 3 hierarchical写 root .kicad_sch 引用所有子 sheet + 把跨 sheet 的 NET 升级成 `(global_label)`single-sheet ERC 残留的 248 + 111 大概率随之降到 < 100。
- (并行) 消 lib_symbol_issues 571emit `sym-lib-table` + 独立 .kicad_sym。
---
## 2026-04-28 23:30 oshwhub 全量 listing 索引落本地33,695 项 / 28.4 MB
**Claude 会话**