101 lines
8.5 KiB
Markdown
101 lines
8.5 KiB
Markdown
# schgen —— kicad-flow 的原理图 / 封装生成库
|
||
|
||
`n10_draw_schematic`、`n23_assign_footprints`、`d11/d20` 排版检查用。由两块真实板子的生成脚本通用化而来:
|
||
ipots_tunerX10 载板(`E:\Kicad_design\ipots_tunerX10\carrier\gen`,9 页 / 327 器件)与
|
||
DVBS2_dmod tuner 子板(`E:\Kicad_design\DVBS2_dmod\carrier\gen`,4 页 / 78 器件,**最小完整示例,先看这个**)。
|
||
|
||
思路:**原理图由工程里的 python 脚本生成,不手画**。所有坐标由符号真实外框推出,
|
||
画什么就同步登记一个占位矩形,最后逐对查重叠/越界,有问题不写文件。改电路改脚本重跑。
|
||
|
||
## 模块
|
||
|
||
| 模块 | 干什么 | 跑它用的 python |
|
||
|---|---|---|
|
||
| `env` | 读 `~/skills_env.md`:`KICAD_ROOT`(必需)、`CHROME_EXE`(可选) | 任意 |
|
||
| `kicad_lib` | `.kicad_sch` 底层:符号提取(含 extends 展开)/ 外框 / 旋转 / `Sheet` 写文件;`register_lib()` 登记工程符号库 | 任意 |
|
||
| `layout` | `Canvas`:占位登记 + 重叠/越界检查(中文按 1.3 字宽估,G-0034) | 任意 |
|
||
| `page` | `Project` / `Page`:画图原语,见下 | 任意 |
|
||
| `symgen` | `box_symbol()` 按引脚表生成方框符号(每边可不同间距);`grab_from_sch()` 从参考 `.kicad_sch` 抽符号 | 任意 |
|
||
| `diagram` | drawio → PNG(SVG 外壳直接截;纯 XML 用 diagrams.net viewer 在 headless Chrome 渲染,需联网) | 任意 |
|
||
| `root` | 根图:层次页符号 + 内嵌框图 PNG(300DPI 反算 scale,G-0022);`.kicad_pro`;`sym/fp-lib-table` | 任意 |
|
||
| `check` | `python -m schgen.check <根图>`:ERC、网表器件数、**封装↔引脚一一对应**、子电路画法(G-0035/37) | 任意 |
|
||
| `fplib` | `FpLib`:按位号从参考 `.kicad_pcb` 提取封装 / 从 KiCad 官方库拷贝 | **KiCad 自带 python**(要 pcbnew) |
|
||
| `pcbimport` | n101:从网表建板(封装按页排停车场 + 挂网)并**逐焊盘验收**。代替不可信的 MCP `sync_schematic_to_board`(G-0039) | **KiCad 自带 python** |
|
||
| `pcbplace` | 布局:圆角板框、按占地中心摆放、正反面、实物禁布区(护套等)、占地重叠/出板检查(跨面只比通孔焊盘)、**自动摆位号** `place_refs()`、JLC 4 层叠层、出正反面 PNG | **KiCad 自带 python**(出图转 PNG 会找装了 fitz 的系统 python) |
|
||
|
||
在工程脚本里:
|
||
|
||
```python
|
||
import os, sys
|
||
sys.path.insert(0, os.path.expandvars(r"%USERPROFILE%\.claude\skills\kicad-flow\scripts"))
|
||
from schgen import Project, register_lib, R, C, L, GND, snap
|
||
```
|
||
|
||
## 画图原语(`Page`)
|
||
|
||
两脚无源件**必须画进它服务的电路里**(G-0035/G-0037),别摆空地两头挂标签:
|
||
|
||
| 原语 | 用途 |
|
||
|---|---|
|
||
| `comp(lib, ref, val, x, y, rot, fields=...)` | 放件;位号撞车直接报错(G-0028)。`fields`:above/left/right/top/none 或 `("xy", rx, ry, vx, vy)` |
|
||
| `inline(x0, y0, lib, ...)` / `vline(...)` | 在水平 / 竖直线上**串**一个件,返回线的另一端 |
|
||
| `shunt(bx, by, lib, ..., net, down=True)` | 从母线一点挂下(上)一个件到电源/地:退耦、上下拉 |
|
||
| `run_taps(px, py, ux, stops, net)` | 沿线打一串抽头挂 shunt,末端出标签 |
|
||
| `fan_series(...)` | 一组引脚各串一个件、排成一列(引脚距与件距不同时用) |
|
||
| `gnd_bus` / `gnd_row` | 多个地脚并一根母线只落一个地符号 |
|
||
| `stub(cx, cy, pp, pin, net, stagger)` | 引脚拉线接标签/电源符号;排针上相邻电源脚用 stagger 错开 |
|
||
| `dot` / `seg` / `path` / `nc_pin` / `frame` / `text` | 丁字接点(G-0036)/ 线段 / 折线 / 断路标记 / 虚线框(留位不贴)/ 注释 |
|
||
| `finish()` | 有重叠或越界:打印并**不写文件** |
|
||
|
||
二极管等横放符号竖着挂时传 `rot=90/270`(`D_Schottky` 1 脚=K:`rot=270` 时 K 在上)。
|
||
|
||
## 标准流程(DVBS2_dmod 就是这么跑的)
|
||
|
||
1. `gen/gen_sch.py`:`make_lib()`(box_symbol / grab_from_sch → `lib/<prj>.kicad_sym`)→ 每页一个函数 →
|
||
`render()` 框图 → `write_root()` → `write_project()` → `write_lib_tables()`
|
||
2. `python -m schgen.check <根图>`:ERC 0、器件数对得上、子电路 A/B 级 0
|
||
3. `kicad-cli sch export pdf` → 用 fitz 渲染 PNG **逐页看图**(检查器不管"挤",只管"压")
|
||
4. n23:`<KICAD_PYTHON> gen/mkfp.py`(FpLib 从参考 PCB 按位号取件 + 自画件),
|
||
`gen_sch.py` 里 `fp_resolver` 按**数值**查表、按位号覆盖;再跑一次 check 看封装一行
|
||
5. n101:`<KICAD_PYTHON> -m schgen.pcbimport <根图> <板.kicad_pcb> [--layers 4]`(在 scripts 目录下跑),
|
||
输出最后一行"问题 0"才算导入成功。它每次重建整块板(DNP/不进 BOM/MPN 等字段一起同步)
|
||
6. 布局:工程里写 `gen/place.py`(示例见 DVBS2_dmod),用 `Placer` 按"板内坐标"摆件,
|
||
`check()` 为 0 后再 `kicad-cli pcb drc --schematic-parity`。建板 → 布局两步都是脚本,
|
||
改原理图后可以一路重跑;**一旦开始手工布线就别再跑 pcbimport**(它会重建空板)
|
||
|
||
布局经验(DVBS2_dmod):先按信号流分区再摆件——并行总线让源端引脚与连接器引脚同序对齐,
|
||
串阻排一行;开关电源回路(LX→二极管→BOOST 电容→PGND)收在芯片一角;DNP 的留位件
|
||
(如 2.x 的大电感)可以放背面;金属壳 NIM 的正下方背面可以放它自己电源脚的 0402 去耦
|
||
|
||
## 坑(已在代码里处理,改代码前先看)
|
||
|
||
- `justify center` 会让整页静默解析失败,网表空、ERC 0(G-0018)→ 判断读没读进去看**网表器件数**
|
||
- 标签角度只有 0/90,180/270 会反向压元件;字段角度要补偿元件旋转(G-0019)
|
||
- 取 unit 时要带 `NAME_0_x` 公共图形(G-0019)
|
||
- KiCad 库的 `(extends ...)` 派生符号要展开,属性块有嵌套括号必须配平替换,否则 ERC 报 lib_symbol_mismatch
|
||
- 连接器是 passive 脚,`PWR_FLAG` 放在电源进线连接器旁;稳压器 OUT 多脚时只留一个 power_out,
|
||
其余 passive,否则 ERC 报 power_out 对 power_out
|
||
- `run_taps` 的每个挂件元组必须带另一端网络(第 6 项);`run_taps(net=None)` 之后若又手动把线往外延,
|
||
最后一个抽头点要自己补 `dot()`(check 的 C 级会报"丁字口缺接点")
|
||
- 检查器的字宽按 1.2mm/字(ASCII)估:0.9、1.1 都在实板上漏报过数值文字压隔壁件;
|
||
检查器只管"压"不管"挤",出图目视 + 独立 agent 复核仍然必要
|
||
- 改 `sym-lib-table`/`fp-lib-table` 后要**整个退出 KiCad 再开**才生效(G-0020)
|
||
- KiCad 通用连接器符号(`Connector_Generic:Conn_*`)自带 `ki_fp_filters`(如 `Connector*:*_1x??_*`),
|
||
封装选择器默认勾着"Apply footprint filters",工程库里的座子(从参考设计提取的 VH3.96-2P、IDC20_2MM)
|
||
会被藏掉,用户看到的是"这个件没有封装"。做法:`set_fp_filter(src, "库:名*")` 后
|
||
`rename(symbol_def(src), src, 新名)` 拷进工程符号库再用(示例见 DVBS2_dmod 的 make_lib)。
|
||
**不要**直接覆盖内嵌的通用符号——ERC 会报 lib_symbol_mismatch
|
||
- `kicad-cli pcb drc --schematic-parity` 对**脚本生成的原理图 + pcbimport 建的板**,会在所有无名网络
|
||
(`Net-(...)`)的焊盘上报 net_conflict "No corresponding pin found in schematic"(ipots 199 条、
|
||
DVBS2 85 条),有名网络一条不报;pcbimport 的逐焊盘验收(按 kicad-cli 导出的网表)全部一致。
|
||
根因未查清,按已知告警处理,在 KiCad 界面里按一次 F8 再确认
|
||
- 圆角板框要用 `SetArcGeometry(起, 中, 止)` 三点法;只给圆心+起止点,弧可能绕远路穿过板内
|
||
- pcbnew `SetField()` 新建的字段默认可见,会被印成丝印,必须 `GetField(k).SetVisible(False)`
|
||
- **丝印(位号)**:`place_refs(size=0.8, thick=0.15, prefer={...})` 按"离器件近、横移小"的代价
|
||
顺序找位置,要求不压任何器件占地(含自己)、焊盘、丝印图形、已摆位号、板边;数值统一挪到 Fab。
|
||
用 KiCad 真实文字外框算碰撞——0.8mm 字高的位号外框实测 3.38 x 1.46mm(竖写 1.46 宽),
|
||
所以**要竖写位号的缝至少留 1.8~1.9mm**,一排 0402 想统一竖写在正上方,间距要 ≥1.7mm。
|
||
摆不下的会列出来:那是布局问题(器件之间没给位号留地方),去改布局,别缩字号。
|
||
验收看 `kicad-cli pcb drc` 的 silk_over_copper / silk_overlap / silk_edge_clearance 三类都为 0
|
||
- 判断工程封装库有没有加载:选择器标题里的总数 = KiCad 自带(10.0 为 15435)+ 全局额外库 + 工程库
|