调压是**反向**的(DAC 码越大输出越低),所以整块换算只在 rail_mv_to_code() 里出现一次那个减法,除 rail.c 外任何地方都不许碰 dac63204_write_code()。 范围 3524~4010 mV,越界即拒(SR-13,第四道限制),4010 = Vd 0。 通道映射按 §26.18 重排过,五路里四路对不上「前三路在 U6、通道号 = rail−1」: CH1→U6.OUT2 / CH2→U6.OUT0 / CH3→U7.OUT0 / CH4→U6.OUT1 / CH5→U7.OUT1。 四通道电气对等 ⇒ 接错了板子照样正常工作,只是调错了路。设计文档 §17.2 那张 过期的通道表一并改掉了。 驱动只经 hal_i2c_*:认件(DEVICE-ID=01h,53204/43204 当 BUS 错拒掉)、 开内部基准 → 写增益 2× → 写安全码 → 才给用到的通道上电(COMMON-CONFIG 因此写两次: 复位码 0 就是输出上限 4.010 V),未用通道 FBx 悬空一律保持 Hi-Z。 三个「一定会被写出来的错」逐个改进去验过测试拦得住:反向关系写反 → test_rail 红; 忘了码左对齐、通道按 rail−1 算 → test_dac63204 红。 留给下次的两条:越界请求还没记事件(TODO(A11));两点标定还没做, 现在走理论公式,将来顶替的是 RAIL_VOUT0_UV / RAIL_DAC_SPAN_UV 两个常量。 Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01QYuExfgyYa6DzRRcUso8M8
428 KiB
五路手机直供电源板 设计文档
| 项 | 值 |
|---|---|
| 版本 | v1.6(P1 补完输入侧检流;原理图只剩 P5 线束页) |
| 日期 | 2026-09-03 |
| 输入 | DC 12V / 10A 适配器 |
| 输出 | 5 路独立,3.52 ~ 4.01V 可调,每路 4A |
| 负载 | 小米8(dipper)主板,经原装 BM3E 电池排线的 P+ / P− 供电(§13.5) |
| 控制 | ESP32-S3,I²C 遥测 + 单路硬断电重启 + 开机键模拟 |
v1.6 相对 v1.5:P1 补上输入侧 INA226(U13 + Rs6 + C11,§19),地址 0x43。顺带修了 P1 上 BLD_REF/BLD_A 两个端口靠零长度导线“连着”的真错误。
v1.5 相对 v1.4:P2 复制成 P2B~P2E 四页,五路全画完(§16.5)。顺带修了母版上两个真错误:K1_VUP 端口靠零长度导线“连着”、两处标签压字。INA226 地址按布线难度重排(§8.2)。
v1.4 相对 v1.3:USB 子系统原理图画完(§18 P4-USB)。五路负载开关的 ON 下拉 / CT 摆率 / QOD 泄放 / CIN>COUT 四条按 datasheet(SLVSD76C Rev C)定稿,元件补进 §9.1 BOM。
v1.3 相对 v1.2:控制部分原理图画完,拆成 P3-CONTROL + P3B-EXPAND 两页(§17)。
复核 LMR51430(Vref 0.6V、EN 可直接接 VIN、Y 后缀是 1.1MHz,§9.3)与
DAC63204(内部基准 1.212V 不是 1.25V → 满量程 2.424V;FBx/CAP/VREF 三条外围硬要求,§4.5)。
定稿 GPIO 分配(§8.1)与 I²C 地址表(§8.2)。调试口改用 ESP32-S3 原生 USB-Serial-JTAG + USB-C。
修正全板位号撞车:P1/P2 各有一套 R1R9/C1C10/Q1,现按页/通道分段(§16.0)。
v1.2 相对 v1.1:按 datasheet 复核纠正了四处错误 —— TPS54622 的 Vref 是 0.6V 不是 0.8V (分压重算,§4.3)、eFuse 缓启动 0.36 V/ms 不是 2 V/ms(§5)、Buck 高侧限流最坏值 14A 不是 8A(§5)、TPS54622 的 EN 绝对最大 6V(要分压,§16.2)。 否决「五路 fsw 错开 2%」(§8.4)。解决 OVP 容差窗口重叠:R2 5.23k→5.49k、 Rinj 107k→150k,输出上限 4.22V→4.01V(§4.3 / §5)。P2-CHANNEL 单路原理图画完(§16)。
v1.1 相对 v1.0:移除原厂电池保护板 —— 电源接到排线的 P+/P−(保护板输出侧),保护板自动退出通路。保护链四层→三层;eFuse OVP 4.45V→4.35V;输出上限 4.22V→4.15V,分压改 R2=12.7k / Rinj=192k。元件选型定稿(§9.3),Buck 改 TPS54622(外部补偿)。
v1.0 相对 v0.3:所有待选项已定稿(§0.1 决策清单);尾插改为装原厂小板;USB 三条对策全部落到硬件;侧键扩到 3 键 ×5 路并改用 74HC595 驱动;GPIO 重新预算;BOM 定稿。
v0.3 相对 v0.2:J600 / J601~604 / J1401 引脚定义已从原理图逐脚追踪确认(§13.2 / §13.3 / §13.4);尾插的 USB 纳入范围,新增 §13.5「USB 供电与电池直供冲突」及对应的三条对策;BOM 追加 12V 母线泄放器与 VBUS 负载开关。
v0.2 相对 v0.1:输出范围 3.66.0V → 3.54.2V;eFuse OVP 6.3V → 4.45V;适配器 12.5A → 10A;分压/注入电阻重算。
0. 设计前提与风险声明
已确认
- 负载是小米8 主板的电池端子。保留原装电池排线的 BTB 公座 / NTC / ID,但旁路保护板 —— 电源接在排线的
P+/P−(保护板输出侧)焊点,电流不经过保护板的串联 MOS。 - 全部 1S 机型。
- 接尾插的 USB(有线 adb / 刷机),其余功能不用。adb 日常走 WiFi。
- 当前无随机重启 / 信号异常现象。
由此产生的两条硬约束
- 输出上限由 1S 锂电端子的绝对上限决定(4.45V),而不再由保护板决定。规格定为 3.52 ~ 4.01V,上限压低是为了给 eFuse 的 4.36V OVP 留公差余量(§5,v1.2 由 4.15V 再降)。 附带好处:DAC 的所有失效态都落在正常电池电压上(§4.4)。 代价:去掉保护板 = 失去一层与本板独立的防线,详见 §5 的取舍说明。
- USB 供电会和电池直供打架。 接上 VBUS 后手机充电器会往我们的 Buck 输出灌电,可能反灌抬高 12V 母线,或把 B+ 顶到保护板 OVP 导致手机掉电。必须按 §13.5 的三条对策处理,一条都不能省。
- 天线馈点在尾插侧。 既然要接 USB,建议直接装原厂尾插小板(§13.5 方案 A),顺带消除 §13.6 的 WiFi 风险。
0.1 决策清单(已定稿,不再讨论)
| # | 决策 | 依据 |
|---|---|---|
| 1 | 输入 12V / 10A 成品适配器 | §1 |
| 2 | 单级同步 Buck ×5,480 kHz(R103=100kΩ,CH1 位号),4.7 µH | §3 / §9.2 |
| 3 | 输出 3.52 ~ 4.01V,硬件上限 4.01V(最坏 4.12V) | §4 |
| 4 | 调压 = DAC 微调(非全范围),DAC63204 ×2,NVM 默认 3.90V | §4 |
| 5 | eFuse OVP 4.36V(68.1k/20k)/ 限流 4.45A,每路一颗(最后一道硬件防线) | §5 |
| 6 | 电池侧接原厂排线的 P+/P−(保护板输出侧),保护板旁路,保留 BTB 座 / NTC / ID |
§13.5 |
| 7 | 手机端 2200µF 铝电解(靠 ESR 阻尼)+ 聚合物 + MLCC | §6.2 |
| 8 | 每路主动放电 MOS + 10Ω,与 eFuse EN 硬件反相联锁 | §7 |
| 9 | 侧键接 3 个(PWR / VOL+ / VOL−)×5 台 = 15 路 MOS | §13.3 |
| 10 | 尾插装原厂小板(不自制 BM24 转接板) | §13.5 方案 A |
| 11 | USB 仅接电脑 / Hub(恒 5V),不接快充充电器 | §15.1 |
| 12 | USB 三条对策全做:软件关充电 + VBUS 负载开关 + 12V 母线泄放 | §15.2 |
| 13 | 15 路按键经 74HC595 ×2 驱动,EN / VBUS_EN 保持 GPIO 直连 | §8.1 |
决策 10 的连带效果:装了原厂尾插小板,§13.6 的 WiFi 天线风险自动消除(馈点、副麦克风、马达全部原样),该项从「打样前必做的阻塞项」降级为「装机后确认一次」。
必须记录的失效模式
- 直供电最致命的失效不是固件写错电压值,而是反馈分压的下电阻开路 → FB = 0V → Buck 满占空比 → 输出直接跳到 12V。软件对此完全无能为力。§5 第二层就是为它设计的。
- 无电池 = 失去了一个内阻只有几十 mΩ 的缓冲电容。瞬态阻抗设计(§6)比电压精度重要得多,是这类板子的主要故障来源。
1. 规格锁定
| 参数 | 值 | 说明 |
|---|---|---|
| 输入电压 | 12V ±10% | 成品适配器 |
| 输入电流 | ≤ 8A | 建议 12V / 10A(120W)适配器 |
| 输出路数 | 5,彼此独立 | 独立地线,不共地 |
| 输出电压 | 3.52 ~ 4.01V 连续可调 | 12 位 DAC,步进 ≈ 0.12 mV |
| 硬件电压上限 | 4.01V(拓扑决定,最坏容差 4.12V) | 见 §4.4,软件越不过去 |
| 输出电流 | 4A / 路(峰值) | 手机常态每路 0.3 ~ 1A |
| 单路峰值功率 | 16.0W | 4.01V × 4A |
| 整板峰值 | 80W | 五路同时满载,实际不会发生 |
| 整板常态 | 10 ~ 25W | 手机挂机功耗 |
| 开关频率 | 480 kHz | 五路统一,不错相(§8.4 已否决) |
| 输出纹波 | < 20 mVpp | 板端测试点 |
| 拓扑 | 单级同步 Buck ×5 | 12V→4.2V 占空比 0.35 |
2. 系统框图
DC12V 插座
│
├─ F1 保险丝 10A
├─ D1 TVS SMBJ13A
├─ Q1 P-MOS 反接保护(理想二极管,Rds < 5mΩ)
├─ C 2×470µF/25V + 4×10µF MLCC
│
└──> 12V 母线 ──┬──────────────── CH1 ────────────────────────┐
│ │
│ ┌────────────────────────────────────────┐ │
├──┤ U1 同步 Buck 480kHz │ │
│ │ L1 4.7µH / Isat 9A │ │
│ │ Cout 2×22µF X7R │ │
│ │ FB ← R1/R2 分压 ← Rinj ← DAC │ │
│ └──────────────┬─────────────────────────┘ │
│ │ │
│ Rs 5mΩ ───┴─── INA226 (I²C, V + I) │
│ │ │
│ eFuse ────┴─── 限流 4.5A / OVP 4.45V │
│ │ EN 通断 / 缓启动 │
│ ├─── Q_dis 放电 MOS + 10Ω │
│ │ (EN 反相硬件联锁) │
│ └──> 端子 ──> 手机1 电池排线 │
│ │
│ Q_key1~3 ──────> 手机1 侧键 PWR/VOL± │
│ (74HC595 驱动,栅极 100k 下拉) │
│ │
├── CH2 ... CH5 同上(布局复制,同频不错相) │
│
├── U_aux 小 Buck 12V→3.3V/500mA ──> ESP32-S3
│
├── U29 母线泄放 TL431+MOS+10Ω/5W(>13.2V 导通)
│ 防 USB 反灌 / 突卸能量抬高母线
│
└── INA226 #6(输入侧 V + I,整板功率预算)
USB 支路(每台一套,与电源支路完全分开走线):
电脑 / USB Hub ──> J12 USB-A ──┬── VBUS ──[U24 负载开关]──> J17.1 ──> 手机尾插小板
├── D− ────(差分对直通,90Ω)───> J17.2
├── D+ ────(差分对直通,90Ω)───> J17.3
└── GND ──────────────────────────> J17.4
↑ ESP32 VBUS_EN,默认断开
手机侧(每台一套,详见 §13):
电源板输出 ──> 原装 BM3E 排线的 B+ / B− 焊点(电芯已移除)
├── 排线自带 NTC / ID / 保护板
└── 原厂 BTB 插回主板电池座
C_damp 2200µF 铝电解 + C_fast + C_hf ← 放在排线端,不是电源板上
Q_key 2N7002 ×3 ──> 主板背面 J601/J602/J603 触点,公共地接 J604
USB 原厂尾插小板(USB-C 母座 + CC + 口温 NTC + 麦克风 + 天线馈点)
3. 单通道功率级计算
条件:Vin = 12V,Vout = 3.5 ~ 4.2V,Iout = 4A,fsw = 480 kHz(R3 = 100 kΩ,见 §9.2)。
3.1 占空比
D = Vout / Vin
D_min = 3.5 / 12 = 0.29 → ton = 583 ns
D_max = 4.2 / 12 = 0.35 → ton = 700 ns
占空比范围很窄(0.29~0.35),环路增益变化小,补偿比 v0.1 好做。
3.2 电感
最坏纹波点在 Vout = 4.2V:
L = Vout·(1 − D) / (ΔIL · fsw) = 4.2 × 0.65 / (1.2 × 500k) = 4.55 µH
取标准值 L = 4.7 µH(与 v0.1 相同,BOM 不变):
ΔIL = 4.2 × 0.65 / (4.7µ × 500k) = 1.16 A (29% 纹波)
I_peak = 4 + 1.16/2 = 4.58 A
| 电感要求 | 值 |
|---|---|
| 感量 | 4.7 µH ±20% |
| 饱和电流 Isat | ≥ 7 A(含 eFuse 限流点 4.5A 的过冲裕量) |
| 额定电流 Irms | ≥ 5 A |
| DCR | ≤ 15 mΩ(4A 下损耗 240 mW) |
| 类型 | 一体成型屏蔽电感,0630 / 0650 封装 |
3.3 输出电容(板端)
板端电容只管纹波与环路,真正的储能在手机侧(§6)。
2 × 22µF / 10V X7R 1210 + 100nF 0402
X7R 在 4.2V 直流偏置下容量约剩 65%,有效 ≈ 28.6 µF:
ΔV = ΔIL / (8 · fsw · C) = 1.16 / (8 × 500k × 28.6µ) = 10 mV
加上 ESR 贡献约 3mV,总纹波 ≈ 13 mVpp。
环路注意:手机侧挂着 2200 µF,通过线缆接在输出上。反馈必须在板端本地取样(local sense),不要做手机端的远端取样(remote sense),否则线缆 LC 谐振进入环路,几乎无法补偿。见 §6.2。
3.4 输入电容
单路输入 RMS 纹波电流(D = 0.35):
Icin_rms = Iout · √(D(1 − D)) = 4 × √(0.35 × 0.65) = 1.91 A
| 位置 | 器件 |
|---|---|
| 每路 IC 引脚旁 | 2 × 10µF/25V X7R 1210 + 1µF 0603 + 100nF 0402 |
| 12V 母线共用 | 2 × 470µF/25V 低 ESR 电解 + 4 × 10µF MLCC |
3.5 损耗与热
每路满载(4.2V/4A = 16.8W,效率约 93%)损耗 ≈ 1.3W,五路 ≈ 6.5W,加前级约 8W。
- 实际常态(每路 3.9V/0.5A)整板损耗 < 1.5W,自然对流足够,不需要风扇。
- 老化测试跑满载时建议加一个 40mm 风扇。
4. 调压网络与本质安全设计
4.1 思路
不用 DAC 做「全范围调压」,而是做「围绕固定中心点的微调」:分压电阻把中心点算死在 3.76V,DAC 只提供 ±0.24V 的偏移。这样即使 DAC 输出满摆到任何一端,输出也只能落在 3.52 ~ 4.01V 之间——软件在物理上无法产生规格外的电压。
4.2 电路与公式
Vout
│
R1
├────── FB (Vref) Rinj : DAC 注入电阻
R2 Vd : DAC 输出,0 ~ 2.424V
│ (内部 1.212V 基准 × 增益 2 = 2.424V)
GND
DAC ──[1k]──┬──[Rinj]── FB
10nF
│
GND
节点方程:
Vout = Vref · (1 + R1/R2 + R1/Rinj) − Vd · (R1/Rinj)
Vout 与 Vd 反向:DAC 输出越高,输出电压越低。
4.3 电阻取值
已按 datasheet 复核(SLVSA70F Rev F):TPS54622 的 Vref = 0.6 V ±1%(0.594 / 0.600 / 0.606), 不是 0.8 V。 因此采用下面这一组:
2026-09-03 定稿:采用「压低上限」的一组(§5 第二层容差对策方案 2,用户已拍板)。
| 元件 | 值(1%,0402) | 立创 |
|---|---|---|
| R1 | 30.1 kΩ | C29402 |
| R2 | 5.49 kΩ | C407675 |
| Rinj | 150 kΩ | C25755 |
R1/R2 = 5.4827 R1/Rinj = 0.20067
Vout = 0.6 × (1 + 5.4827 + 0.20067) − 0.20067 · Vd
= 4.010 − 0.2007 · Vd (Vd: 0 ~ 2.424V,范围 3.524 ~ 4.010V)
Vd 的上限是 DAC63204 内部基准 1.212V × 增益 2 = 2.424V(不是 2.5V,见 §4.5)
为什么不是原来的 5.23k / 107k(上限 4.222V):那一组的最坏角落上限 4.34V 与 eFuse OVP 的跳闸下沿 4.21V 重叠,会误跳。改这两个电阻后最坏上限降到 4.120V,与 OVP 下沿让开 86 mV,见 §5 第二层。代价是手机看到的「满电」 只有 4.01V(约 85% 电量),对手机农场无影响。
Rinj 的实际值是 151 kΩ:DAC 低通的 1 kΩ(R8)串在这条支路上。 折算后 Vout(Vd=0) = 4.009V、斜率 0.1993,与上式差 1 mV,工程上忽略。
早期版本写「TPS54622 是 0.8V、采用 49.9k/12.7k/192k」是错的,已作废。
首板实测后用 R2 的 E96 相邻值微调;改 R2 会同时移动上下限,改完必须重算 §5 第二层的容差窗口。
4.4 失效态验算(本质安全的证明)
按 §4.3 的 Vref = 0.6V 一组,穷举 DAC 与 MCU 的所有失效状态:
| 状态 | Vd | 实际 Vout | 判定 |
|---|---|---|---|
| 正常,目标 3.90V | 0.548 V | 3.900 V | ✅ |
| 上电默认值(NVM 预置 0.548V) | 0.548 V | 3.900 V | ✅ |
| DAC 输出锁死在 0V | 0 V | 4.010 V | ✅ 正常满电电压,手机继续跑 |
| DAC 输出锁死在满量程 | 2.424 V | 3.524 V | ✅ 正常,相当于电量偏低 |
| DAC 未供电 / 输出 Hi-Z | — | 3.890 V | ✅ Rinj 悬空退化成 R1/R2 分压,正好落在目标值上 |
| I²C 总线挂死 | 保持上次值 | 上次值 | ✅ |
| ESP32 跑飞 / 复位 | 保持上次值 | 上次值 | ✅ |
结论:DAC 与 MCU 的任何失效,输出都落在正常锂电池工作电压区间内,手机不会掉电,更不会损坏。
最坏容差角落(Vref ±1% + 三个电阻 ±1% 取最不利组合):
| 标称 | 最坏 | |
|---|---|---|
| 上限(Vd = 0) | 4.010 V | 4.120 V |
| 下限(Vd = 2.424V) | 3.524 V | 3.422 V |
下限的最坏值 3.422V 已经贴近小米8 的关机门限(≈3.4V)。这只会出现在 「DAC 锁死满量程 + 全部容差取最坏」的复合失效下,属于安全侧失效(手机关机, 不损坏)。固件里把 Vd 上限限制在 2.0V(→ 3.61V)即可完全避开, 正常调节根本用不到 2.0V 以上。
上一版(5.23k/107k)需要固件禁止 Vd < 0.5V 来防 eFuse 误跳,这条约束现在 不需要了 —— Vd=0 只有 4.010V,离 OVP 很远。
这一层防不了的是分压电阻本身失效,由 §5 第二层处理。
4.5 DAC 选型
- TI DAC63204(4 通道 12 位,I²C,带 NVM 上电默认值)× 2 片 = 8 通道,用 5 路。
- 关键特性是 NVM 存上电默认值:烧成 Vd = 0.548V(对应 3.90V 输出),上电即安全工作,不依赖 ESP32 初始化成功。 即使 NVM 没烧成功(上电默认 0V),输出也只有 4.010V,仍然安全。
- 内部基准 1.212 V(1.1979 / 1.212 / 1.224,±1%,TC 50 ppm/℃),增益 2× → 满量程 2.424 V。 早期文档写「1.25V × 2 = 2.5V」是错的,已按 SLASEX3A §6.8 更正。
- 分辨率:2.424V / 4096 × 0.2007 = 0.12 mV / LSB(折算到输出)。
- 外围三条硬要求(datasheet 表 5-1,接错了图上看不出来): FBx 必须接回 OUTx;CAP 接 ≈1.5 µF(本设计 2.2 µF)到 AGND; VREF 不用外部基准时要 100 nF 到地 且上拉到 VDD。GPIO 不用时也要外接电阻拉到 VDD 或 AGND。 实现见 §17.2。
- DAC 输出到 Rinj 之间加 1 kΩ + 10 nF 低通(截止 ≈16 kHz)滤更新毛刺。这个 RC 必须放在 Rinj 的 DAC 侧,不能挂在 FB 节点上,否则给环路引入额外极点。
5. 三层保护链
彼此独立,任何一层单独失效都不会导致手机损坏。
第一层:拓扑限幅(§4)
分压网络 + DAC 量程决定输出物理范围 3.524 ~ 4.010V(最坏容差 3.422 ~ 4.120V), 全部是正常锂电池电压。
- 防的是:固件 bug、I²C 误码、MCU 跑飞。
- 防不了:分压电阻本身失效。
第二层:eFuse 的独立过压断开 ⭐
全板最关键的一个器件。 每路输出串一颗带可调 OVP + 可调限流的 eFuse:
| 设定 | 值 | 作用 |
|---|---|---|
| OVP 阈值 | 4.36 V(68.1k/20k) | 超过即断开负载,2µs。⚠️ 容差窗口很窄,见下 |
| 限流 | 4.45 A(R_ILIM = 20kΩ) | 恒流限制,不依赖 MCU |
| 缓启动 dV/dt | 0.36 V/ms(C_dVdT = 33nF) | 抑制 2200µF 的浪涌,涌流 0.80A |
| EN | ESP32 GPIO 直连 | 断电重启的开关 |
| FAULT | ESP32 GPIO 输入 | 上报故障 |
它防的正是那个致命故障:R2 开路 → FB = 0 → Buck 满占空比 → 输出冲向 12V → eFuse 在 4.35V 处切断。
去掉原厂保护板之后,这一层是最后一道硬件防线,所以要定量确认它来得及。 按 datasheet(SLVSA70F / SLVSCF3A)的最坏值而不是典型值:
故障电流受 TPS54622 高侧限流约束,datasheet 8 / 11 / 14 A(min/typ/max),取最坏 14 A
手机侧储能 2200 µF
dV/dt = 14 A / 2200 µF = 6.4 mV/µs
4.22V → 4.36V 需要 ≈ 22 µs
TPS25940 的 tOVP(dly) = 2 µs(datasheet 实测值) → 余量约 11 倍
结论:余量仍然充裕,去掉保护板没有实质性提高过压风险。 另外 eFuse 断开后 2200 µF 仍撑着,手机继续运行、不会掉电——比保护板断开(手机直接掉电)的表现还好。
早期版本按「限流 ≈ 8 A、余量 30 倍」估算,用的是 min 而不是 max,已修正为 11 倍。
OVP 阈值的容差窗口 —— 已解决(2026-09-03)
P2 画图时算出来的一个真问题。原始状况:
分压 R109/R110 = 68.1k / 20k(CH1 位号),V(OVPR) = 0.99V(typ) → 标称跳闸 4.361 V
V(OVPR) 范围 0.97 ~ 1.01 V(±2.0%),分压电阻 1% → 分压比 ±2.0%
→ 实际跳闸落在 4.206 ~ 4.519 V
而当时第一层允许的最高输出(Vd=0)标称 4.222 V,最坏 4.34 V
两个区间重叠 → 坏角落下 DAC 失效到 0V 时 eFuse 会误跳。 根因是「最高输出 4.222V ~ 1S 上限 4.45V」只有 5.4% 的窗口,比器件容差还窄。
对策:把第一层的上限压下去,而不是收紧 OVP。 已改 §4.3 的两个电阻 (R2 5.23k→5.49k,Rinj 107k→150k),OVP 分压 68.1k/20k 保持不动:
| 原(5.23k/107k) | 现(5.49k/150k) | |
|---|---|---|
| 第一层最高输出(标称 / 最坏) | 4.222 / 4.34 V | 4.010 / 4.120 V |
| eFuse 跳闸区间 | 4.206 ~ 4.519 V | 4.206 ~ 4.519 V(未变) |
| 两者关系 | ❌ 重叠 0.13 V | ✅ 让开 86 mV(2.1%) |
另外两个被否掉的方案,留档备查:
- 分压电阻改 0.1%:窗口只收到 4.27 ~ 4.45 V,余量仍很小,且 0.1% 的 0402 全套凑不齐。
- 维持现状 + 固件禁止 Vd < 0.5V:把硬件问题推给固件,违背 §4 的本质安全原则。
残留:最坏角落下 eFuse 可能到 4.519 V 才跳,超过 1S 绝对上限 4.45 V 约 60 mV。 接受,理由是:输出要跑到 4.5V 必然意味着第一层已失效(R2 开路 → Buck 满占空比), 此时输出以 6.4 mV/µs 冲过这一段只需 ≈10 µs,4.45→4.52 V 的 70 mV 超调持续时间 远短于锂电池的过压损伤时间常数。
其他已复核的 TPS25940A 参数
| 项 | 结论 |
|---|---|
| OVP 检测点 | 监视输入侧(IN 到 GND 的分压)。本设计 eFuse 输入 = Buck 输出,正合适 |
| ILIM 公式 | I_LIM(A) = 89 / R_ILIM(kΩ),R_ILIM 合法范围 16.9 ~ 150 kΩ |
| 限流取值 | R11 = 20 kΩ → 4.45 A(datasheet 表格 4.09/4.45/4.81 A) |
| dV/dt 公式 | dV/dt = 12 × 1µA / C_dVdT;总斜坡 t = 8.3e4 × Vin × C |
| 缓启动实际值 | C14 = 33 nF → 0.36 V/ms,斜坡 11.5 ms,涌流 2200µF × 0.36V/ms = 0.80 A |
| Rds(on) | 42 mΩ typ(26~64 全温区)→ 4A 时压降 168 mV / 0.67 W |
| 反灌保护 | V(IN)−V(OUT) < −9.3 mV 断开;正向重新导通门限 +100 mV |
| 变体 | TPS25940A = 热故障自动重试(L 版是锁存),本设计用 A 版 |
| PGOOD | 开漏,PGTH 门限 0.99V。R16/R17 = 20k/10k → 检测 eFuse 输出 2.97 V 以上 |
⚠️ 早期版本写「缓启动 dV/dt ≈ 2 V/ms」是错的。 2 V/ms 对 2200 µF 意味着
2200µF × 2V/ms = 4.4 A充电电流,直接顶到 4.45 A 限流点,上电会进限流而不是缓启动。 33 nF 给出的 0.36 V/ms 才是对的,.claude/eda-parts.json里缓存的选型一直是对的。
同理 §7.4 写「EN ↑ 后约 3ms 稳定」也偏乐观:实际是
tON(dly) = 100 + 150×33 = 5.1 ms延迟 + 11.5 ms 斜坡 ≈ 17 ms。
选型要求:Vin 覆盖 2.7 ~ 18V、连续电流 ≥ 4.5A、OVP 行为是「断开」而不是「钳位」、OVP 阈值可设到 4.45V 这么低、带 EN 与 FAULT。TPS25940A 全部满足。
第三层:ESP32 软件监控
INA226 读到电压偏离设定值超过 ±100 mV 且持续 50 ms → 拉低该路 EN 并上报。
去掉保护板之后这一层的价值上升了:它是唯一能发现「eFuse 本身失效」的手段。建议把巡检周期从 50 ms 收紧到 20 ms。
这一层是记录与告警用的,不承担实时保护职责。不要把过流保护做进 MCU 循环。
6. 手机侧储能与阻尼 —— 最容易翻车的地方
⚠️ 2026-09-03:这一节的数可能要整体重算。 用户提出做一块主板载板 (5 块主板固定其上,直接对插到本电源板),回路电感会从 20 cm 线缆的 300 nH 掉到板对板的约 50 nH 量级 —— 压降、f_res、Z0、Q 全变(都是往好的方向)。 电容组的位置也从「排线端」变成「载板上 P+/P− 焊盘旁」。 详见
PROGRESS.md的「⭐⭐ 第二件事:主板载板」。该方案卡在缺机械数据,尚未定稿。
6.1 问题
锂电池内阻只有几十 mΩ 且贴在手机内部,天然吸收手机的全部瞬态电流。拿掉电芯后:
线缆电感(20cm 18AWG 双线)≈ 300 nH
射频发射突发 di/dt ≈ 2 A/µs
瞬时压降 V = L · di/dt = 300n × 2/1µ = 0.6 V
手机 VBAT 掉到 3.2V 以下 → 随机重启 / 信号异常 / 摄像头启动失败。这类故障看起来像「手机自己有问题」,极难排查。
6.2 线缆 LC 谐振(必须阻尼)
手机侧加大电容后,它和线缆电感构成谐振回路:
L = 300 nH , C = 2200 µF
f_res = 1 / (2π√(LC)) = 6.2 kHz
Z0 = √(L/C) = 11.7 mΩ
R_cable(18AWG,20cm,往返)≈ 2.6 mΩ
Q = Z0 / R = 11.7 / 2.6 = 4.5 ← 欠阻尼,会振铃
解法:用铝电解的 ESR 做阻尼。 把 2200 µF 选成普通铝电解(ESR 40 ~ 100 mΩ)而不是聚合物电容:
Q = 11.7 / (2.6 + 60) = 0.19 ← 过阻尼,干净
再并少量低 ESR 电容处理快速瞬态。这里选错电容类型,板子会「莫名其妙地不稳」。
6.3 手机侧电容组(每路一套,装在电池排线端)
位号见 §20 的 P5-HARNESS 页(CH1 为 C801C806,CH2CH5 为 C811~C846)。
这些器件离板:只画在原理图上,不进 BOM、不上 PCB。
| 位号(CH1) | 器件 | 立创 | 作用 |
|---|---|---|---|
| C801 | 2200µF / 6.3V 普通铝电解,SMD 10×10.5(Rubycon 6.3TPV2200M10X10.5,ESR 60 mΩ@100kHz) | C3828985 | 主储能 + 阻尼。2026-09-06 换矮封装(原 C49256788 插件 10×16 作废);6.3V 对 4.2 V 轨够(第一层限幅 4.01 V,§4.3) |
| C802, C803 | 100µF / 6.3V X5R 1206 | C15008 | 中频瞬态 |
| C804, C805 | 22µF / 25V X5R 1206 | C12891 | 高频 |
| C806 | 100nF 0402 | C1525 | 甚高频,紧贴 P+/P− 焊点 |
⚠️ C801 千万别买成聚合物。 立创上同尺寸的
C53446724(PA10V2200M10X12) 是聚合物,ESR 只有 12 mΩ —— 装上去 Q 会从 0.19 回到 4.5,线缆 LC 在 6.2 kHz 上振铃 (§6.2 的整个阻尼设计就是靠普通铝电解那几十 mΩ 的 ESR)。 选型时看描述里有没有「类型:聚合物」。
两处与原方案的偏离(2026-09-03 画 P5 时定的,均待复核): ① C802/C803 原写「100µF/6.3V 聚合物」,立创基础库里没有这个规格, 改用 100µF/6.3V X5R 1206 MLCC。3.9V 偏压下每颗只剩约 40 µF, 中频段储能从 200 µF 掉到约 80 µF。要严格照原方案就换真聚合物。 ② C804/C805 原写「22µF/10V 1210」,改用板上已有料 22µF/25V 1206(C12891)。 电压档更高 → 偏压衰减更小,等效容量反而更接近标称。
6.4 线缆与接地要求
- 线长 ≤ 20 cm,18AWG 或更粗,正负双绞或紧贴平行。
- 每路独立回流地,五路的地绝对不要在手机端并成一根——共地阻抗会让一台手机的射频突发窜到另外四台。
- 板端出线用 Molex Micro-Fit 3.0(额定 8.5A)或 XT30,不要用杜邦线。
- 大电容必须在排线端,不是电源板上。 放在板上等于隔着 300 nH 线缆电感,基本无效。
7. 断电重启:必须做主动放电
7.1 为什么
只拉低 eFuse EN 是关不掉手机的:
手机侧 2200µF + 手机关机待机电流 ≈ 50 µA
自然放电到安全电压:t ≈ C·ΔV/I = 2200µ × 3.5 / 50µ ≈ 154 秒
「断电 10 秒再上电」根本不会触发重启。某些机型还要求 VBAT 掉到 2.5V 以下才算真正断电。
7.2 电路
在 eFuse 之后(手机侧)加:
Q_dis N-MOS(2N7002 / AO3400)
R_dis 10Ω / 1W / 2512
τ = 2200µF × 10Ω = 22 ms
放到 < 0.5V 约需 5τ ≈ 110 ms
峰值放电电流 = 4.2V / 10Ω = 0.42 A(瞬时 1.76W,占空比极低)
7.3 硬件联锁(重要)
如果固件同时打开 eFuse 和放电 MOS → 10Ω 上持续 1.76W → 电阻过热。
用一级反相器把放电 MOS 的栅极接到 eFuse 的 EN 上(一颗 2N7002 + 100 kΩ 上拉),令两者硬件互斥。好处:物理上不可能同时导通;省掉 5 个 GPIO;固件只需控制一根 EN 线。
7.4 重启的两级策略
有了开机键模拟(§13.3)之后,重启不必每次都断电:
一级(软):长按开机键 10s 强制重启
→ 不断电,闪存和文件系统友好,优先使用
二级(硬):EN ↓ → eFuse 断开,放电 MOS 自动导通
等待 3 ~ 5 s(放电到 <0.5V 只要 ~110ms,其余是等手机彻底断电)
EN ↑ → tON 延迟 5.1ms + 缓启动 0.36V/ms 斜坡 11.5ms ≈ 17ms 后稳定
→ 一级无效时才用
8. ESP32 接口设计
8.1 GPIO 分配
扩到 3 键 ×5 台后,直连方案需要 34 ~ 39 根 IO,超出 ESP32-S3-WROOM-1 的可用数量。按「安全关键直连、慢速信号扩展」拆分:
| 数量 | 信号 | 方向 | 接法 | 说明 |
|---|---|---|---|---|
| 5 | EFUSE_EN[1:5] | 输出 | GPIO 直连 | 安全关键,任何情况下都要能关电 |
| 5 | VBUS_EN[1:5] | 输出 | GPIO 直连 | 安全关键,反灌时要能立刻断 |
| 4 | KEY_SER / SRCLK / RCLK / OE# | 输出 | GPIO 直连 | 驱动 74HC595 ×2 → 15 路按键 |
| 2 | I²C SDA / SCL | 双向 | 4.7 kΩ 上拉 | INA226 ×6 + DAC63204 ×2 + PCA9555 ×1 |
| 1 | IOEXP_INT# | 输入 | GPIO 直连 | PCA9555 中断(汇总 5 路 EFUSE_FAULT) |
| 2 | NTC_ADC ×2 | 输入 | ADC | 电感区 / MOS 区各一 |
| — | UART / USB | — | — | 调试口 |
合计 19 根,余量充足(SYNC 若要做,还能再挤出 5 根)。
实际引脚分配(2026-09-06 按 PCB 几何重排,取代 09-03 那一版,§26.18)
引脚号是从「板上要去哪儿」倒推的,不是逻辑顺序。除 USB_DM/DP(IO19/IO20 是 USB PHY
硬连线)与两路 NTC(要 ADC1 = IO1~IO10)外,全部信号走 GPIO matrix,落哪个脚都行。
| 模块脚 | GPIO | 出线方向 | 信号 | 去哪儿 |
|---|---|---|---|---|
| 6 | IO6 | 东 | EFUSE_EN3 |
CH3(东北) |
| 8 | IO15 | 东 | SCL |
全板 I²C |
| 9 | IO16 | 东 | FAN_TACH |
R731/R732(x≈103) |
| 10 | IO17 | 东 | VBUS_EN5 |
J25.5(x≈109) |
| 11 | IO18 | 东 | FAN_PWM |
R733(x≈98) |
| 12 | IO8 | 东 | EFUSE_EN5 |
CH5(东南) |
| 13 / 14 | IO19 / IO20 | 东 | USB_DM / USB_DP |
J22 —— 硬连线,动不了 |
| 17 | IO9 | 北 | KEY_RCLK |
U21/U22/U33 |
| 18 | IO10 | 北 | VBUS_EN2 |
J25.14 |
| 19 | IO11 | 北 | VBUS_EN3 |
J25.38 |
| 20 | IO12 | 北 | KEY_SRCLK |
U21/U22/U33 |
| 21 | IO13 | 北 | KEY_SER |
U21.14 |
| 22 | IO14 | 北 | SDA |
全板 I²C |
| 23 | IO21 | 北 | KEY_OE# |
U21/U22/U33 + R609 |
| 24 | IO47 | 北 | UP_VBUS_DET |
J24.25 |
| 25 | IO48 | 北 | EFUSE_EN2 |
CH2(西北) |
| 32 | IO39 | 西 | EFUSE_EN1 |
CH1(西南) |
| 33 | IO40 | 西 | VBUS_EN1 |
J24.20 |
| 34 | IO41 | 西 | EFUSE_EN4 |
CH4 |
| 35 | IO42 | 西 | VBUS_EN4 |
J24.19 |
| 31 | IO38 | 西 | IOEXP_INT# |
U23(PCA9555) |
| 38 | IO2 | 西 | NTC2 |
ADC1_CH1,RT602 |
| 39 | IO1 | 西 | NTC1 |
ADC1_CH0,RT601 |
IO39~IO42 原来留给引脚 JTAG,2026-09-06 用户拍板改作 GPIO。 调试口本来就走原生 USB-Serial-JTAG(IO19/IO20 → J22),出厂 eFuse 默认选的就是它, 板上也没有 JTAG 排针。⚠️ 永远别烧
DIS_USB_JTAG—— 烧了引脚和 USB 两边都没有。 让出去的是兜底:固件把 IO19/20 改成普通 GPIO、或跑到 USB 外设起不来的地方挂死时, 引脚 JTAG 还能进去。IO39~IO42 在 S3 上不是 strapping(S3 只有 IO0/IO3/IO45/IO46 是), 复位期间高阻输入,配合目的地 100 kΩ 下拉,上电全关的行为一点没变。
有意不接的引脚(图上已用文字注明,验证脚本用 .claude/p3-nets-nc.json 放行):
| 引脚 | 为什么不用 |
|---|---|
| IO0 / IO3 / IO45 / IO46 | strapping 脚,挂负载会影响上电模式 |
| IO35 / IO36 / IO37 | WROOM-1 的 R8 版(八线 PSRAM)占用,留空以便换料 |
| IO4 / IO5 / IO7(脚 4/5/7) | 重排之后空出来的备用脚,三个都带 ADC1 |
| TXD0(IO43,脚 37)/ RXD0(IO44,脚 36) | 下载走原生 USB,不需要 UART;PCB 上引到测试点 |
下载 / 调试口用 ESP32-S3 的原生 USB-Serial-JTAG(IO19/IO20 直连 USB-C 的 D±), 不需要 USB 转串口芯片,也不需要 BOOT / RST 按键(esptool 通过 USB 直接复位进下载模式)。 USB-C 的 VBUS 故意不接:板子由 12V 供电,这样从物理上杜绝 USB 反灌到 3V3。 CC1/CC2 各 5.1 kΩ 下拉,对外表现为 UFP。
按键为什么可以走移位寄存器:按键是百毫秒级的慢速信号,串行移位的延迟(几十 µs)完全无影响;而 EN 必须在故障瞬间可控,不能依赖串行链路。
复位安全(三条都要做)
EFUSE_EN/VBUS_EN各加 100 kΩ 下拉到 GND:ESP32 复位期间 GPIO 高阻 → 五路输出全关、VBUS 全断。KEY_OE#加 100 kΩ 上拉到 3.3V:复位期间 74HC595 输出高阻。- 74HC595 每一路输出到按键 MOS 栅极之间加 100 kΩ 下拉:高阻时栅极被拉低 → 15 个按键全部不按。
缺任何一条,都可能在 ESP32 复位的瞬间误按五台手机的电源键。
8.2 I²C 设备表
| 器件 | 位号 | 用途 | 地址(2026-09-03 画五路时按布线难度重排) |
|---|---|---|---|
| INA226 | U8 ~ U12 | CH1~CH5 输出 V + I(5mΩ 分流) | 0x40 / 0x41 / 0x44 / 0x45 / 0x42 |
| INA226 | U13 | 输入侧 V + I(整板功率预算) | 0x43(A1=GND, A0=SCL) |
| DAC63204 | U6 | VDAC1 / VDAC2 / VDAC3 | 0x4A(A0 接 SDA) |
| DAC63204 | U7 | VDAC4 / VDAC5 | 0x4B(A0 接 SCL) |
| PCA9555 | U23 | 5×FLT + 5×PG + BUCK_PG + INA_ALERT | 0x20(A0=A1=A2=GND) |
| LM75BD | U34(载板) | 载板温度,风扇闭环用它 | 0x48(A0=A1=A2=GND) |
INA226 地址为什么不是 0x40~0x45 顺排(2026-09-03 改): INA226 的 A1/A0 各能接 GND / VS / SDA / SCL,但只用 GND 和 VS 只能凑出 4 个地址 (0x40 / 0x41 / 0x44 / 0x45),而全板要 6 个,所以必然有两片得把地址脚搭到 I²C 线上。 顺排(0x40~0x44)会让 CH3 接 SDA、CH4 接 SCL,而 P2 上 A0 脚的上下两侧 正好夹着 Alert 和 SDA 两根横线,往 SCL 拉必然要跨线。 改成下面这样之后,五个通道里只有 CH5 需要搭 SDA(走 (690,470)→(690,450)→(700,450), 0 交叉),剩下那个 SCL 的落到 U13 头上——它画在 P1 的空白区,布线自由。
CH1 CH2 CH3 CH4 CH5 U13(输入侧) A1 GND GND VS VS GND GND A0 GND VS GND VS SDA SCL 地址 0x40 0x41 0x44 0x45 0x42 0x43 六个地址仍然互不重复,也不与 DAC(0x4A/0x4B)、PCA9555(0x20)冲突。 代价:通道号不再等于地址低位,固件里要查表,不能算。
DAC 的 A0 接 SDA/SCL 是 datasheet 明确允许的(SLASEX3A §7.5.2.2.1: A0 可接 VDD / AGND / SDA / SCL,对应地址低三位 001 / 000 / 010 / 011)。 这里这么接是因为 A0 引脚夹在 SDA 和 SCL 中间,跳到相邻脚比拉到电源/地干净得多。 基址
1001xxx与 INA226 的1000xxx、PCA9555 的0100xxx不冲突,已逐个核对。
分流电阻:5 mΩ / 1% / 2512 / 1W,Kelvin 四线焊盘。 4A 时压降 20 mV,芯片满量程 81.92 mV,分辨率 2.5 µV → 0.5 mA。
8.3 固件功能(按价值排序)
- 崩溃检测 + 自动重启(两级)
adb connect探活失败 N 次,或电流曲线卡死 → 先长按开机键 10s;再失败 → 断电 5s → 上电。 这是整块板子最核心的价值。 - 过流 / 故障事件记录 —— 哪一路、什么时刻、多大电流。排查排线接触不良的唯一线索。
- 单路电压微调 —— 跑不稳的手机从 3.9V 提到 4.1V,或反向降压降温。
- 模拟电量曲线(可选)—— 让手机以为电量在正常变化,避免系统因"电量永远 100%"触发异常逻辑。
- 温度监控 —— NTC 超阈值先降流、再关路。
- 整板功率预算 —— 读输入侧 INA226,超过适配器能力时按优先级降载。
不要做的事
- 不要让 ESP32 参与过流保护的实时环路(那是 eFuse 的活)。
- 不要提供任何能让输出超过 4.2V 的接口。
- 不要让任一路输出给 ESP32 供电(用独立的 12V→3.3V 小 Buck)。
8.4 错相同步 —— 已否决
原计划「五路 RT 电阻取不同值(480/490/500/510/520 kHz)避免拍频」。
按 datasheet 复核后否决:TPS54622 在 Rrt = 100 kΩ 下的 fsw 是 400 / 480 / 560 kHz(±17%),
器件本身的离散度远大于想刻意制造的 2% 错开,这个做法没有任何效果。
五路统一 R3 = 100 kΩ(480 kHz)。 详见 §9.2。 TPS54622 的 RT/CLK 支持外部时钟同步,若首板实测确实存在拍频问题, 再用 ESP32-S3 的 MCPWM 输出 5 路 72° 相移时钟(引脚已预留在 §8.1 的余量里)。
9. BOM 骨架
9.1 主板
| 位号 | 器件 | 数量 | 规格 / 要求 |
|---|---|---|---|
| J1 | DC 输入插座 | 1 | 12V / 10A,或 XT60 |
| F1 | 保险丝 | 1 | 10A 慢断 |
| D1 | TVS | 1 | SMBJ13A(立创 C163651) |
| Q1 | P-MOS 反接保护 | 1 | 30V,Rds(on) < 5 mΩ |
| C_in | 铝电解 | 2 | 470µF / 25V 低 ESR |
| U1~U5 | 同步 Buck | 5 | 见 §9.2 |
| L1~L5 | 电感 | 5 | 4.7µH,Isat ≥ 7A,DCR ≤ 15 mΩ |
| — | 输出 MLCC | 10 | 22µF / 10V X7R 1210 |
| — | 输入 MLCC | 10 | 10µF / 25V X7R 1210 |
| R1/R2/Rinj | 分压 + 注入 | 15 | 1% 0402,取值见 §4.3 |
| U6, U7 | DAC63204 | 2 | 4ch 12bit,NVM 默认值 |
| U8~U13 | INA226 | 6 | I²C 电压电流监测 |
| Rs1~Rs6 | 分流电阻 | 6 | 5 mΩ 1% 2512 1W(Rs6 在 P1 的 12V 母线上,量整板输入电流) |
| C11 | U13 的 VS+ 去耦 | 1 | 100 nF 0402(P1 上) |
| U14~U18 | eFuse | 5 | OVP 可设 4.45V / 限流 4.5A / EN / FAULT |
| Q_dis1~5 | 放电 N-MOS | 5 | 2N7002 或 AO3400 |
| R_dis1~5 | 放电电阻 | 5 | 10Ω 1W 2512 |
| Q_inv1~5 | 反相器 MOS | 5 | 2N7002(EN 联锁) |
| Q_key1~15 | 按键 MOS | 15 | 2N7002(3 键 × 5 台,§13.3) |
| R_kg1~15 | 栅极串阻 | 15 | 1 kΩ 0402 |
| R_kp1~15 | 栅极下拉 | 15 | 100 kΩ 0402 |
| U19 | 辅助 Buck | 1 | LMR51430YDDCR,12V→3.315V / 500mA,1.1 MHz(§9.3) |
| U20 | ESP32-S3 模组 | 1 | WROOM-1 |
| U21, U22 | 74HC595 | 2 | 串行驱动 15 路按键,OE# 上拉到 3.3V |
| U23 | PCA9555 | 1 | I²C 输入扩展,汇总 5 路 EFUSE_FAULT + 备用 |
| U24~U28 | VBUS 负载开关 | 5 | TPS22918DBVR(C131941),1~5.5V / 2A / Ron 52 mΩ(§18) |
| U29 | 母线泄放 | 1 | TL431 + N-MOS(30V/5A) + 10Ω/5W,13.2V 导通(§15.2) |
| J2~J6 | 电源输出连接器 | 5 | Micro-Fit 3.0 双针,8.5A |
| J7~J11 | 按键连接器 | 5 | 4 针 1.25mm(PWR / VOL+ / VOL− / GND) |
| — | 2026-09-03 删除:改板载 Hub 后外部只剩一根线(§15.1) | ||
| U32 | USB 2.0 7 口 Hub | 1 | USB2517I-JZX(C478081,QFN-64)。配置见 §21 |
| Y1 | 晶振 | 1 | 24 MHz ±10ppm CL=9pF(C2762192)+ 2×12pF C0G(C1547) |
| R708 | RBIAS | 1 | 12.0 kΩ ±1%(C25752)→ GND,datasheet 硬性要求 |
| J23 | Hub 上游口 | 1 | TYPE-C-31-M-12(C165948,与 J22 同料),UFP;R717/R718 各 5.1kΩ 下拉 |
| U30 | 第二路辅助 Buck | 1 | LMR51430YDDCR(C5210749,与 U19 同料),12V→4.98V,见 §9.4 |
| L3 | 5V 轨电感 | 1 | SPM6530T-4R7M(C76857,与 L1~L5 同料) |
| R706 / R707 | 5V 反馈分压 | 2 | 100 kΩ(C25741)/ 13.7 kΩ(C25854) |
| U31 | Hub 专用 LDO | 1 | AMS1117-3.3(C6186,SOT-223),5V→3.3V,见 §9.5。PCB 上要铺铜散热 |
| J17~J21 | USB 下游口 | 5 | A1251WV-S-4P(C225106,与 J7~J11 同料),VBUS / D− / D+ / GND |
| R701~R705 | VBUS_EN 下拉 | 5 | 100 kΩ 0402 → GND,datasheet 明令 ON 脚不得悬空(§18.2) |
| C701~C705 | 负载开关 CIN | 5 | 2.2 µF / 50V 0805(C377773),必须 > COUT(§18.2) |
| C711~C715 | 负载开关 COUT | 5 | 100 nF 0402 |
| C721~C725 | 负载开关 CT | 5 | 100 pF C0G / 50V 0402(C1546),设摆率 tR ≈ 425 µs |
| RT601, RT602 | 热敏电阻 | 2 | 10 kΩ B=3380(NCP18XH103F03RB,C13564);原写 B=3950,改用立创基础库常备的 B3380,只是固件查表不同 |
| J22 | USB-C 母座 | 1 | TYPE-C-31-M-12(C165948),只用于 ESP32 下载 / 调试,VBUS 不接 |
| R602, R603 | CC 下拉 | 2 | 5.1 kΩ 0402(C25905),USB-C 作 UFP 必需 |
| R601 | ESP32 EN 上拉 | 1 | 10 kΩ;配 C603 100nF 做上电复位 |
| R604, R605 | I²C 上拉 | 2 | 4.7 kΩ → +3V3 |
| R606, R607 | 开漏上拉 | 2 | 47 kΩ;BUCK_PG / INA_ALERT |
| R608 | 开漏上拉 | 1 | 10 kΩ;PCA9555 的 INT# |
| R609 | KEY_OE# 上拉 | 1 | 100 kΩ → +3V3,ESP32 复位期间 15 路按键输出高阻 |
| R614, R616 | DAC VREF 上拉 | 2 | 10 kΩ → VDD(不用外部基准时 datasheet 要求) |
| R615, R617 | DAC GPIO 下拉 | 2 | 10 kΩ → AGND(GPIO 不用时 datasheet 要求外接电阻) |
| R618, R619 | NTC 分压 | 2 | 10 kΩ → +3V3 |
| C601 | ESP32 储能 | 1 | 22 µF 1206 |
| C608, C611 | DAC CAP 旁路 | 2 | 2.2 µF(内部 LDO,datasheet 要 0.5~15 µF) |
| C609, C612 | DAC VREF 旁路 | 2 | 100 nF |
| C602~C607, C610, C613, C614 | 去耦 / 滤波 | 9 | 100 nF 0402 |
9.2 Buck 主控:TPS54622 已定稿并复核
选型已定:TI TPS54622RHLR(VQFN-14,4.5–17V 输入 / 6A)。 下面全部按 datasheet SLVSA70F 核过,不再是估值。
| 参数 | datasheet 值 | 本设计取值 |
|---|---|---|
| Vref | 0.6 V ±1%(0.594/0.600/0.606) | 决定 §4.3 的 30.1k/5.49k/150k |
| 开关频率 | Rrt(kΩ) = 48000 × fsw(kHz)^−0.997 − 2 |
R3 = 100 kΩ → 480 kHz(datasheet 表格直接给出 400/480/560) |
| EN 绝对最大 | 6 V ⚠️ 不能直接接 +12V | R4/R5 = 68.1k / 10k 分压 |
| EN 门限 | 上升 1.21V / 下降 1.17V,Ip 1.15µA / Ih 3.3µA | 起动 9.37 V,关断 8.84 V |
| 高侧限流 | 8 / 11 / 14 A | §5 的故障 dV/dt 按 14A 算 |
| 误差放大器 gm | 1300 µS | 补偿计算用 |
| COMP→电流 gm | 16 A/V | 同上 |
| 慢启动 | Iss = 2.3 µA,tss = Css·Vref/Iss |
C9 = 10 nF → 2.6 ms |
| PWRGD | 开漏,门限 ±(94~106)% Vref | 五路线或到一根 BUCK_PG |
| 补偿 | 外部补偿(COMP 引脚,跨导型) | 见下 |
环路补偿取值(Type II)
按 datasheet §8.2.2.10 的公式,取板端本地陶瓷电容(2×22µF,4.2V 直流偏置后 ≈ 28.6 µF):
fpmod = Iout/(2π·Vout·Cout) = 4/(2π×3.9×28.6µ) = 5.7 kHz
fco2 = √(fpmod × fsw/2) = 37 kHz ← 上限
选 fco = 18 kHz(刻意取低,见下)
R4comp = 2π·fco·Vout·Cout /(gm_ea·Vref·gm_ps) = 1.0 kΩ → R6 = 1 kΩ
C4comp = Vout·Cout/(Iout·R4comp) = 28 nF → C10 = 33 nF
C5hf → C11 = 100 pF(可选高频极点)
为什么刻意把穿越频率取到 18 kHz 而不是 37 kHz:这块板是在模拟电池。 手机侧挂着 2200 µF 铝电解(ESR 40~100 mΩ,§6.3),瞬态由它本地吸收, 环路只需要慢慢维持直流点。慢环路对线缆 LC 谐振(6.2 kHz,Q=0.19)也更宽容。
打样前仍然要做一次环路实测:上面的推导假设「线缆电感把手机侧 2200 µF 在 几 kHz 以上隔离掉了」。这个假设成立与否只能靠实测。第一版三个补偿位置都留了焊盘。
§8.4 错相同步的结论:不要做
datasheet 给的 fsw 容差是 Rrt = 100kΩ → 400 / 480 / 560 kHz,即 ±17%。
原计划「五路 RT 取 480/490/500/510/520 kHz 刻意错开 2%」被器件本身的离散度完全淹没,
毫无意义。五路统一用 100 kΩ,少一条 BOM 行。
9.3 辅助 Buck:LMR51430YDDCR 已复核(SLUSEF4A Rev A)
P1 页上原来标注「Vref / EN 耐压待复核」,2026-09-03 按 datasheet 查清,结论是不用改:
| 项 | datasheet | 对本设计的影响 |
|---|---|---|
| Vref | 0.6 V(0.591 / 0.600 / 0.609,±1.5%) | P1 的 R2/R3 = 100k / 22.1k → Vout = 0.6×(1+4.5249) = 3.315 V ✅ |
| EN 绝对最大 | VIN + 0.3 V(不是 6V!) | EN 直接接 +12V 完全合法,datasheet 引脚说明原文就写 "This pin can be tied to VIN" ✅ |
| EN 门限 | 上升 1.227V / 下降 1.08V(精密 EN) | 想加 UVLO 可以外接分压,本设计不需要 |
| VIN 范围 | 4.5 ~ 36 V(绝对最大 38V) | 12V 输入,余量充足 ✅ |
| VIN UVLO | 上升 3.89 |
12V 母线跌到 4.5V 以下才关,不与 §5 的 13V 泄放门限打架 |
| 型号后缀 | Y = 1.1 MHz(X 是 500 kHz)、PFM 版 | ⚠️ 之前文档写「500 kHz」是错的,实际 1.1 MHz |
| 内部软启动 | 固定 4.0 ms(3.2/4.0/5.4) | 不用外部 SS 元件 |
| 高侧限流 | 3.67 / 4.76 / 6.68 A | 3A 器件带 0.5A 负载,余量巨大 |
| CB 电容 | 0.1 µF / ≥16V | P1 的 C8 = 100nF ✅ |
电感复核:L2 = SWPA4030S100MT(10 µH)。在 1.1 MHz / 12V→3.3V 下
ΔIL = 3.3 × (1−0.275) / (10µH × 1.1MHz) = 0.218 A,
0.5A 负载时纹波比 44%、峰值 0.61A,远低于 Isat ✅。
(TI 应用例用 6.8µH 是按 3A 满载算的,我们只用 0.5A,10µH 反而更省。)
⚠️ 唯一一处偏保守值:C7(U19 的输入去耦)现在是 2.2 µF / 50V 0805, 而 datasheet §9.2.2.6 要求「高频去耦 ≥ 4.7 µF」,应用例用 2 × 4.7µF/50V。 2.2µF 的 X5R 在 12V 直流偏置下只剩约 1.2 µF。 建议改成 10 µF / 50V 0805(C440198,BOM 里已经有),或并一颗。 不改也能工作(12V 母线上有 2×470µF + 2×10µF 大电容兜底),但要在 PCB 上把 C7 贴到 VIN/GND 引脚旁边——这条已写进 §10。
9.4 第二路辅助 Buck:12V → 5V(2026-09-03 随板载 Hub 新增)
板载 Hub 之后,下行 VBUS 不能再从上游线取(§15.1 边界 2),必须自己发 5V。
| 项 | 取值 | 说明 |
|---|---|---|
| U30 | LMR51430YDDCR(C5210749) | 和 U19 同料,§9.3 的复核结论全部适用(Vref 0.6V、EN 可直接接 VIN、Y 后缀 = 1.1 MHz、内部软启动 4 ms) |
| R706 / R707 | 100 kΩ / 13.7 kΩ(C25741 / C25854) | Vout = 0.6 × (1 + 100/13.7) = 4.98 V |
| L3 | SPM6530T-4R7M(C76857) | 复用 L1~L5 那颗,不新增 BOM 行 |
| C731, C732 | 10 µF / 50V 0805(C440198)×2 | 输入去耦。直接按 §9.3 的教训取 ≥4.7 µF,不重蹈 C7 只放 2.2 µF 的覆辙 |
| C733 | 100 nF(C1525) | CB 自举 |
| C734, C735 | 22 µF / 25V 1206(C12891)×2 | 输出 |
电感复核:12V→5V、D = 5/12 = 0.417、f = 1.1 MHz、L = 4.7 µH:
ΔIL = Vout × (1−D) / (L × f) = 5 × 0.583 / (4.7µ × 1.1M) = 0.564 A
2 A 负载时峰值 = 2.28 A ≪ Isat 6.2 A ✅ 余量巨大
纹波比 = 0.564 / 2 = 28% ✅ 正常区间
负载预算(正常态其实很轻):
| 负载 | 正常 | 最坏 |
|---|---|---|
| U31 LDO 输入(给 Hub 3.3V) | ~0.15 A | 0.42 A × 3.3/5 ≈ 0.28 A |
| 5 路下行 VBUS | ≈ 0(§15.2 对策 1 关掉充电后手机基本不从 VBUS 取电) | 5 × 0.5 A = 2.5 A(关充电全部失效,且固件没来得及切) |
| 合计 | < 0.5 A | 2.8 A |
最坏工况只在「五路的 input_suspend 同时失效」时出现,而那正是 §15.2 对策 2 (TPS22918 + INA226 监控)要切断的场景。按 2 A 连续设计,3 A 器件足够。
9.5 Hub 专用 3.3V:U31 AMS1117-3.3
不能挂 U19 那条 3.3V 轨。 USB2517 满配 5 口高速传输时,全部电源合计约 420 mA
(datasheet §8:1 口 230 mA / 4 口 330420 mA / 7 口 420460 mA),
而 U19 按 0.5 A 设计、上面已经挂着 ESP32-S3(WiFi 突发 ~350 mA)、两片 DAC、
两片 74HC595、PCA9555 和 6 片 INA226。
| 项 | 取值 | 说明 |
|---|---|---|
| U31 | AMS1117-3.3(C6186,SOT-223) | 5V → 3.3V,1 A 档;压差 1.7 V 远大于其 ~1.3 V 的 dropout |
| 耗散 | 0.42 A × 1.7 V ≈ 0.71 W(最坏) | SOT-223 要铺铜散热,已写进 §10 |
| C736 / C737 | 10 µF 输入 / 22 µF 输出 | AMS1117 要求输出至少 10 µF 才稳 |
2026-09-04:U31 已随 Hub 搬到载板,原理图上画在 C1-CONN 页 (+5V 从排针进来就在那一页),不是 C2-HUB。上面那条「就近 Hub 供电」是 PCB 摆位约束,和原理图分在哪一页无关 —— 布板时 U31 仍必须紧挨 U32。 它现在还多带两个负载:U34(LM75BD,约 0.3 mA)和五颗 EDL 模拟开关(µA 级), 相对 Hub 的 420 mA 可以忽略。
顺带的好处:Hub 的 3.3V 与 ESP32/DAC 那条控制轨物理隔开, 而且 U31 就放在 Hub 旁边(§10 的就近供电),480 Mbps 器件的回流不会串到 决定输出电压的 DAC 上去。
10. PCB 布局要点
10.1 叠层与铜厚
4 层,外层 1 oz / 内层 0.5 oz(嘉立创四层板的标准配置)。
| 层 | 用途 |
|---|---|
| L1 | 功率器件 + 信号(D± 走这一层,以 L2 为参考面) |
| L2 | 完整地平面(不许被割断) |
| L3 | Inner2-PWR:12V 母线灌铜 + 五路输出灌铜 |
| L4 | 控制信号 + ESP32 |
2026-09-03 用户拍板:外层从 2 oz 改 1 oz。 原来定 2 oz 是为了载流, 但后来加进来的两样东西和它打架: ① U32 是 0.5 mm 间距的 QFN-64 —— 2 oz 外层最小线宽/间距 0.2 mm 起,扇出很吃力(1 oz 是 0.102 mm); ② 90 Ω 差分对的几何随铜厚变(§15.3)—— 2 oz 下同样的 W/S 只有 83 Ω。 而 1 oz 载流本来就够(见下表),代价只是线要宽一点。
载流(IPC-2221 外层,A=(I/(0.048·ΔT^0.44))^(1/0.725),1 oz = 1.37 mil)
| 电流 | 哪里 | ΔT=20 °C 需要 | 本设计给的 | 实际温升 |
|---|---|---|---|---|
| 1.6 A | 每路的 +12V 支路(4 A×4.2 V÷12 V÷0.9) | 0.38 mm | 走灌铜 | — |
| 4 A | VOn / VOn_P 输出 | 1.34 mm | 1.5 mm(规则 PWR4A) |
16.7 °C |
| 4 A | SW 铜箔(§10.2-2) | 1.34 mm | 2.0 mm | 10.4 °C |
| 8 A | 12V 总干(J1 → F1 → 体电容 → 五路) | 3.49 mm | 见下 | — |
⚠️ 12V 总干那 8 A 不许当普通走线画。 规则
PWR12V给的默认 2.0 mm 是给分支用的 —— 8 A 走 2.0 mm 温升 35 °C,不能接受。 总干必须走灌铜:
- Inner2-PWR(0.5 oz)上 8 A 要 ≥18 mm 宽的铜面,或
- 顶层灌铜 ≥3.5 mm 宽,或两者分流。
之所以不把
PWR12V的最小值直接设成 3.5 mm:+12V 这个网络上还有一堆 进 0402 / SOT-23 焊盘的短支线,最小值卡 3.5 mm 会刷出几百条假 DRC 错误, 规则就没人看了。载流靠灌铜保证,不靠 DRC。同一条道理再走一步(2026-09-03 扇出时):
PWR4A/PWR12V的最小值 从 1.0 mm 再降到 0.3 mm。 规则是按网络生效的,而+12V上挂着 R104 那种 0402 分压抽头 —— 0402 焊盘只有 0.57 × 0.54 mm,1.0 mm 的线比焊盘还宽, 物理上引不出来。卡 1.0 的实测结果:29 个焊盘扇不出去,硬扇出去的又被判 「线宽 11.8 mil,应 ≥ 39.4 mil」。默认值仍是 1.5 / 2.0,交互布线画出来还是宽线。
10.2 每路 Buck 的关键回路
- 热回路(Cin → 上管 → 下管 → GND)面积最小化。 2 颗 10 µF MLCC 必须同层紧贴 IC 的 VIN / GND 引脚。这是 EMI 的第一大来源。
- SW 节点铜箔面积压到刚好够载流(约 2 mm 宽)。
- FB 走线尽量短,远离 SW 节点。 R1 / R2 紧贴 FB 引脚,Rinj 也放在附近;DAC 长线走 Rinj 另一侧。
- INA226 的分流电阻用 Kelvin 四线焊盘,取样线并行走线,不跨越 SW 或电感。
10.2b 8 A 输入链必须挤在 J1 边上(2026-09-03 布线时重排)
J1 → F1 → Q1 → C2/C3 → Rs6 这一串分叉之前全程 8 A,所以它有多长,
就要多少宽的铜。第一版布局是自动摆的,摊成了 J1(x5.8) … Rs6(x84.6~90.7),
8 A 要横穿 85 mm,其中 J1→F1 单独一段就 42 mm。
8 A 在 0.5 oz 内层要 ΔT=20 °C 得 18 mm 宽,band B 一共才 36 mm 高,
四条这样的铜面根本排不下。
重排到 J1 右手边的走廊(x 11.546 / y 49.568.5,栅极网络放 J1 上方的口袋)之后:
| 之前 | 现在 | |
|---|---|---|
| J1 → F1 | 42 mm | 6.9 mm |
| 8 A 段横跨 | x 5.8 ~ 90.7 | x 12 ~ 40 |
| 分叉点 | x 90.7 | x ≈ 40 |
| 母线最大截面电流 | 全程 8 A | 顶带 ≤ 6.4 A |
规律:8 A 那一段的长度是布局问题,不是布线问题。 等到布线时再想办法加宽, 已经晚了 —— 板上没有那么多空间。
10.4 平面层的实际划分(2026-09-03 布线时定稿)
§10.1 那张表只写了"L3 = 12V 母线灌铜 + 五路输出灌铜"。真画下来有三处要补:
| 铜面 | 层 | 网络 | 范围(mm) |
|---|---|---|---|
| GND-L2 | L2 | GND |
整板,板框内缩 0.5,只挖 ESP32 天线区 |
| VIN-RAW-L3 | L3 | J1 → F1 | x 3 |
| VIN-FUSED-L3 | L3 | F1 → Q1 | x 14.6 |
| VIN-SW-L3 | L3 | Q1 → 体电容 → Rs6 上游 | L 形,x 14.4 |
| 12V-L3 | L3 | +12V |
下带 x14.6 |
| VO1~5-L3 | L3 | VOn |
每路 30 mm 宽 / y 82.5~99.5 |
| VO1~5_P-L4 | L4 | VOn_P |
每路 30 mm 宽 / y 110~116.2 + 一条下伸臂到分流电阻 |
三处补充说明:
-
VOn_P铺在 L4 而不是 L3,与 §10.1"L4 = 控制信号"有出入,是有意的。 L3 在 y>100 那一带已经被VOn与 eFuse 输出段占住,而且分流电阻 + INA226 + 放电联锁挤在一起,VOn/ eFuse 输出 /VOn_P三个网络的焊盘在 y 上互相咬合 (eFuse 输出 y95107.5 与116 重叠),L3 上切不出干净的分界。 连接器带(y110~116)在 L4 上恰好是空的,而且 L4 是 1 oz —— 4 A 只要 1.34 mm, 给了 30 mm。控制信号避开这五块条带即可。VOn_Py103.9 -
eFuse 输出段(
$2NxxxN一类的自动命名网)不铺铜:它只有 9.5 mm (U14 → Rs101),走顶层PWR4A规则的 1.5~2 mm 线就够。 -
+12V顶带做到 16.5 mm 高(y 67.5~81.9)而不是 18 mm。18 mm 是 §10.1 算的 8 A 数值,但 8 A 只存在于分叉点之前。分叉点在 Rs6 下游 x≈40, 往左只喂 CH1(1.6 A)、往右喂 CH2~CH5(6.4 A), 6.4 A 在 16.5 mm 的 0.5 oz 内层上温升 14 °C,够了。 分叉点之前那段 8 A 走的是 band B 的 12V-L3 下带(15 mm 高)与 VIN-SW-L3(17.5 mm 高),且长度都在 10 mm 量级。
分界线的位置由焊盘边决定,不是取整数:+12V 顶边 81.9 卡在 C102 那排
1210 焊盘的上沿(y80.281.7);84.55 —— 按"元件中心在 y85.4"去算,会把它漏在两块铜面之间的缝里。VOn 底边 82.5 是因为 C107 pin1 是 rot90 的 1210,
焊盘跨到 y83.07
U8~U13 的 Kelvin 脚一律不进铜面。 INA226 是 MSOP-10、0.5 mm 间距, U13.10 是 VIN+、U13.9 是 VIN−,两脚相距 0.5 mm,任何分界线都塞不进去。 它们走顶层细线,本来也不载流。所以 VIN-SW-L3 右边界停在 x35、 12V-L3 左边界从 x38.5 起,中间 3.5 mm 全让给这几个脚。
过孔:0.3 mm 孔 / 0.6 mm 焊盘,单孔约 1~1.5 A,所以功率网络每个焊盘打 3 个,
GND 靠地平面 + 散热盘阵列一个就够。出线宽度 1.0 mm ——
不是随手挑的,是 PWR4A / PWR12V 两条线宽规则的最小值,细过它 DRC 就报线宽违规。
10.3 整体
- 五路完全相同的布局,同方向复制粘贴。不要镜像或旋转。
- 输出连接器附近留测试点:Vout、GND、EN、FAULT。
- 五路输出地在连接器处分开,只在板内地平面上单点汇合。
- 开机键的两根线(KPDPWR_N / GND)必须和该路的电源地同源,走线远离 SW 节点。
- 电感和 IC 下方铺大面积铜箔并打散热过孔阵列(0.3 mm 孔,1 mm 间距)。
- 板框 160 × 125 mm,四角 R5 圆角 + 四个 M3 金属化定位孔(孔 Φ3.2 / 焊盘 Φ6.0,接 GND)。
定位孔的 Φ6.5 禁布区与顶边的五个 Micro-Fit 是打架的,解法见
PROGRESS.md。 - ESP32 模组天线区域下方禁止铺铜、禁止走线,模组放板边。
- 辅助 Buck(U19)的 C7 必须紧贴 VIN / GND 引脚,回路面积最小化。它现在只有 2.2 µF(偏小,见 §9.3),布局补偿的余地更小;SW 走线尽量短、CB 电容贴着 CB/SW 引脚。
11. 首板上电调试顺序
严禁第一次上电就接手机。 按顺序做:
| 步 | 操作 | 通过标准 |
|---|---|---|
| 1 | 不装 U1~U5,只上 12V | 输入电流 < 50 mA,3.3V 正常,ESP32 能启动 |
| 2 | I²C 扫描 | 6 个 INA226 + 2 个 DAC 全部应答 |
| 3 | 断开 eFuse 输出侧,装 CH1 的 Buck | 空载输出 3.90V ±60 mV(DAC 走 NVM 默认值) |
| 4 | 扫描 DAC 全量程 | 输出扫过 3.52 ~ 4.22V,与 §4.3 公式误差 < 1% |
| 5 | 人为断开 R2(模拟致命故障) | eFuse 在 4.45V 断开,示波器确认输出侧不超过 4.7V 尖峰 |
| 6 | 电子负载 0→4A 阶跃(带 20 cm 线 + 电容组) | 压降 < 300 mV,无 6 kHz 振铃(阻尼验证,§6.2) |
| 7 | 满载 4A 跑 30 分钟 | 电感 / IC 温升 < 40 K |
| 8 | 断电重启时序 | 输出在 200 ms 内跌到 < 0.5V |
| 9 | 五路全装齐,重复 4 ~ 8 | — |
| 10 | 接第一台手机,先设 3.80V | 正常开机,WiFi adb 可连 |
| 11 | 验证按键模拟(§13.3) | 短按唤醒 / 长按 10s 强制重启 / VOL−+PWR 进 Fastboot 均有效 |
| 12 | ESP32 复位安全测试 | 手动复位 ESP32,示波器确认五路输出立即关断、15 路按键无一误触发 |
| 13 | 母线泄放测试(§15.2) | 可调电源把 12V 母线升到 13.5V,泄放应导通并把电压拉回 13.2V 以下 |
| 14 | USB 反灌测试(§15.2,关键) | 接 USB 但不关充电 → 观察该路 INA226 电流转负、12V 母线上升;确认固件在 200 ms 内断开 VBUS |
| 15 | 关充电后复测 | input_suspend=1 后接 USB,该路电流应无反向分量,母线不上升 |
| 16 | 有线 adb / Fastboot | adb devices 可见;fastboot devices 可见 |
| 17 | 长稳 24h | 无重启、无告警 |
第 5、6 步是这块板子的两个核心验证项,不要跳过。
12. 待确认 / 后续
已关闭
WiFi 天线风险→ 决策 10 装原厂尾插小板,风险消除,装机后确认一次即可。尾插要不要接→ 接,只用 USB(§15)。按键接几个→ 接 3 个(§13.3)。GPIO 够不够→ 74HC595 方案,19 根,余量充足(§8.1)。
仍需在打样前完成(阻塞项)
- 排线旁路验证(§13.7)→ 确认焊在
P+/P−而非B+/B−,4.40V 不断开。 - 侧键触点定位(§13.3)→ 万用表 5 分钟,拍照存档。
TPS54622 的 Vref 按 datasheet 复核→ 已完成,Vref = 0.6V(§4.3)。TPS25940 的 OVP 能否设到 4.35V→ 能,OVP 基准 0.99V、监视输入侧、响应 2µs(§5 第二层)。 但引出了下面这条新的待决项。决定 OVP 容差对策→ 2026-09-03 用户拍板方案 ②:R2 5.23k→5.49k、Rinj 107k→150k, 第一层上限压到 4.010V(最坏 4.120V),与 OVP 跳闸下沿 4.206V 让开 86 mV。 OVP 分压 68.1k/20k 不动。已改图(P2 页 R102/R107 换器件,六项验证复跑通过)与 §4.3 / §4.4 / §5。- 环路补偿实测(§9.2)→ 图上按 fco≈18kHz 放了 R106/C110/C111,三个位置都留了焊盘,首板要扫频确认。
- 量两个新连接器的高度(§26.16-C,2026-09-06)→
XT30PW-M(C53373776) 和2510-3A 直针座(C2803349)。pcb1_place.H_FP里填的 11.0 / 9.0 是按同系列常规取的 保守估计 —— 器件的3D Model Transform只给 XY 尺寸,Z 读不出来, 而这两个位置的 hmax 都是 12.0,余量只有 1~3 mm。拿实物量,别信估计值。 - 风扇线的装配顺序(§26.16-C)→ 立式座插口朝上正对载板底面,座+胶壳约 11.5 mm, 13 mm 净空里插拔只剩 1.5 mm ⇒ 必须「先插好五根风扇线,再合上载板」。 外壳方案定下来时确认这个顺序做得到(否则退回弯针座,J26~J30 引脚位置一样,改回来很快)。
4.7µH / Isat ≥ 7A 电感选型→ 用 SPM6530T-4R7M(Isat 6.2A),裕量分析见「已知遗留」。
新增变更请求(2026-09-03)
- 主板载板(第二块 PCB):按小米8 主板定位孔做一块载板,固定 5 块主板,
直接对插到本电源板。会改 §6.1~§6.4、§13.3、§15.4,并新增一节讲载板机械与板对板接口。
头号阻塞项:本项目手上没有小米8 主板的任何机械数据
(本 PDF 是电气原理图,不含外形 / 定位孔 / 接点坐标 / 元件高度),只能实测。
详见
PROGRESS.md的「⭐⭐ 第二件事」。 板载 USB Hub 的六个待定项→ 2026-09-03 全部定了: Hub = USB2517I 单片 7 口(用户拍板);自供电 5V 轨 = U30 第二片 LMR51430(§9.4); Hub 的 3.3V = U31 AMS1117-3.3 专供(§9.5,不能挂 U19);上游口 = USB-C UFP(用户拍板); TPS22918 ×5 保留(通断权留在 ESP32 手里);Hub 复位线走 74HC595 的备用输出(§21.7); J17~J21 仍在下边(否则 D± 要纵穿功率区,§15.3)。 硬件配置逐条复核见 §21。- 板载 USB Hub 的落地:原理图 P4-USB 重画 + 新增 P4B-HUB 页;PCB【C】带重排。
载板 v2(2026-09-06,元件全到底层 + 穿线槽)引出的
穿线槽尺寸实测→ 2026-09-06 用户实测:电池排线 8 宽 × 38 长,尾插排线 18 宽 × 55 长。电池槽 10 × 3.0(接口边外侧);尾插槽 20 × 3.0 在 J1401 正下方,J7n 放主板下方远处 v 37,排线沿载板背面走(§25.16 v4,2026-09-06 用户拍板)。- 两条排线路径要拿实物试装(v5):接口边朝板边,排线从板边翻下、穿槽、在背面往板中心走。尾插 2.86 + 5 + 2.7 + 1.6 + 37.7 ≈ 49.9 / 50(实长 55);电池 ≈ 31.6 / 35(实长 38)。
电池排线改成直接焊载板→ 2026-09-06 已落地(§13.5 末尾):J8n 直焊座在主板下方远处 v 15,R78n 10k / R79n 68k。还剩 P+ 左右手性实测(错了改BAND['j8']的 rot)和 排线路径试装(主板反面 3.0 mm 缝里钻过去)。J7n 手性按装法实测→ 2026-09-06 复核:不用再量。 镜像位 2026-09-05 已实测(J1401 靠接口边那一排是奇数排,fp_bm24.ODD_ROW_TOP=True与之一致), 加上 §25.16 补 3 的几何推导(只绕 u 轴弯 ⇒ J7n = J1401 绕 v 轴翻面),底层 rot 0 的回读(pin1/2 端在本体 −u、奇数排在 −v)正好等于「J1401 绕 v 轴翻面」。 装好后做一次两点通断复核:排线两头插好、手机不通电,J7n pad 52(本体 +u 端电源触点)对手机屏蔽罩通、pad 51 不通;pad 8 通(↔ J1401 pin 44 GND)、pad 7 不通(↔ pin 43)。J8n 的 P+ 在哪一侧→ 2026-09-06 用户实测:P+ 在左 ⇒BAND['j8']rot 0 正确,什么都不用改。C8n1 卧倒→ 2026-09-06 用户拍板换矮封装:Rubycon 6.3TPV2200M10X10.5(C3828985,SMD 10×10.5,ESR 60 mΩ)。下板在五块罐体投影下仍只能放 ≤1.5 mm 的件(pcb2-bottom-heights.json)。- J7n 镜像位实测要按底层装法重做(§24.3 + §25.16)。
U34量的仍是走廊温度(§25.15 那条不变)。
不阻塞打样,但要定
- 主板机械固定方式(建议连中框,见 §13.6)。
input_suspend节点在目标 ROM 上的实际路径(§15.2 对策 1)。
13. 手机侧接口(小米8 / dipper)
13.1 连接器定位(已由原理图确认)
依据:D:\DCDC\小米8原理图\Xiaomi_Mi_8_Schematic.pdf(44 页,Rev E8,2018-03-23,SDM845 + PMI8998 + PM845 + SMB1355)。
| 接口 | 位号 | 型号 | 图纸页 | 本方案 |
|---|---|---|---|---|
| 电池 BTB | J600 | Molex 505004-0810,8 pin + 4 固定脚 | Sheet 25「PMI8998 CHARGE」 | 插原厂 BM3E 排线 |
| 侧键触点 ×4 | J601~J604 | XM-217-XC-142-SP,各 2 pin | Sheet 28「PMI8998 HAPTICS&SIDEKEY」 | 要用,见 §13.3 |
| 尾插 / 副板 BTB | J1401 | Hirose BM24-50DS/2-0.35V(51),50 pin | Sheet 40「LCD&BTB」 | 不接 |
| 屏幕 + 触摸 | J1102 | Hirose BM24-50DP/2-0.35V(51),50 pin | Sheet 40 | 不接 |
13.2 电池连接器 J600 引脚定义
已从原理图逐脚追踪并逐条目视复核。
| Pin | 网络 | 去向 / 附属元件 |
|---|---|---|
| 1 | GND | 直接接地 |
| 2 | GND | 接地;经 W606(0Ω)引出 VBATT_CONN_VSENSE_M |
| 3 | BATT_ID | → PMI8998 pin 119;TP615 测试点;CR605 / CR608 ESD5471Z |
| 4 | BATT_THERM | → PMI8998 pin 159;TP0.8mm 测试点;CR606 ESD5471Z;C684(NM) |
| 5 | NC | 未连接 |
| 6 | NC | 未连接 |
| 7 | VBATT | 电池正 |
| 8 | VBATT | 电池正;经 W607(0Ω)引出 VBATT_CONN_VSENSE_P |
| G1 (GND1) | GND | 固定脚,参与导流 |
| G2 (GND2) | GND | 固定脚,参与导流 |
| G3 (GND3) | ⚠️ VBATT | 固定脚,不是地 |
| G4 (GND4) | ⚠️ VBATT | 固定脚,不是地;C691 10µF 去耦 |
⚠️ 陷阱:GND3 / GND4 这两个固定脚接的是 VBATT,不是地
原理图符号里它们叫
GND3/GND4,实际网络是 VBATT。按名字假设它们是地并短到地 = 直接短路电池。 全连接器共 4 条正极通路(7、8、G3、G4)和 4 条负极通路(1、2、G1、G2)——0.4mm 间距 BTB 单 pin 载流有限,靠并联凑充电电流,固定脚也被算作载流路径。 任何时候在这个座子附近动手(探针、飞线、返修),先记住这条。
电压采样是在座子处做开尔文取样:VBATT_CONN_VSENSE_P/M 经 W606/W607 从 pin 8 / pin 2 引出,接 PMI8998 的 VBATT_SNS_P(147) / VBATT_SNS_M(134)。
含义:手机读到的"电池电压"就是 J600 座子处的电压,与我们板子到排线之间的线损无关,但等于我们电源板输出减去线缆压降。所以 §4 设定的 3.52~4.01V 就是手机看到的值,这也再次说明 §6 的线缆压降必须压住——线损会被手机当成"电池电量在掉"。
对本方案的三条结论
- 直供只需要 VBATT 和 GND,但 BATT_ID(3) 与 BATT_THERM(4) 是两根独立的实线,缺任一条手机都可能拒绝开机或拒绝充电。这坐实了「保留原厂排线」是正确路线——排线上的 NTC 和 ID 直接落在这两个脚上。
- VBATT 与 GND 各有 4 条通路,说明单 pin 载流很有限。不要试图自制 BTB 转接板只焊一两个脚。
- BATT_ID / BATT_THERM 上有 ESD5471Z 保护,说明这两个脚对外暴露、对静电敏感——改造排线时注意防静电。
13.3 侧键 J601~J604 引脚定义与模拟电路
四个 2 pin 触点(XM-217-XC-142-SP),每个连接器的两个 pin 在板内并联,即每个是一个独立的弹片触点:
| 位号 | 串联电阻 | 网络 | 功能 | 去向 |
|---|---|---|---|---|
| J601 | R610 1kΩ | VOL_UP_N |
音量 + | PM845 GPIO |
| J602 | R611 1kΩ | PM_RESIN_N |
音量 − | PM845 RESIN_N (pin 129) |
| J603 | R612 1kΩ | PHONE_ON_N |
电源键 | PMI8998 KPD_PWR_N(111) 和 PM845 KPD_PWR_N(128),两颗 PMIC 并联 |
| J604 | — | GND |
三键公共地 | 直接接地 |
ESD 位:CR607 / CR608 / CR609(ESD5581MXT5G,NM 未贴),C686 / C687 100pF。
按键 = 把 J60x 触点短接到 J604 触点。 1kΩ 串阻已经在主板上(R610~R612),所以对地短接是安全且唯一正确的方式。
驱动电路(每台手机一套,接三个键就是三套):
J603 触点(电源键)───────── D
│ Q_key : 2N7002 N-MOS
ESP32 GPIO ──[1 kΩ]───────── G ┤
│ R_pd : 100 kΩ G→S 下拉
J604 触点(公共地)────────── S
- 电源板从
B−给手机供地,两边同地,直接用 MOS 对地短接即可,不需要光耦。 - 绝对不要从外部往 J60x 灌电压。
- 100 kΩ 下拉保证 ESP32 复位期间(GPIO 高阻)不会误按。
- 空闲电压需实测:原理图上
PHONE_ON_N没有外部上拉,电平由两颗 PMIC 的内部上拉决定。首板时记录实测值作为后续判据(读到稳定高电平即正常;读到 0V 说明认错了触点)。
接三个键(而不是只接电源键)能换来远程救砖能力:
| 组合 | 作用 | ESP32 实现 |
|---|---|---|
| J603 长按 ≈10s | 强制重启 | 单路 MOS |
| J603 长按 ≈2s | 开机 | 单路 MOS |
| J603 短按 ≈100ms | 唤醒 / 息屏 | 单路 MOS |
| J602 + J603 同时长按 | 进 Fastboot | 两路 MOS 同时导通 |
| J601 + J603 同时长按 | 进 Recovery | 两路 MOS 同时导通 |
对手机农场来说,能远程进 Fastboot 意味着刷机失败不用跑到机架前。每台多两颗 2N7002 和两个 GPIO,很划算。建议 §8.1 的 GPIO 从 5 路 KEY_PWR 扩到 15 路(5 台 × 3 键),ESP32-S3 的 IO 还够;不够就把三个键的 MOS 栅极经一片 74HC595 驱动(按键是慢速信号,串行移位完全够用)。
13.4 尾插连接器 J1401 引脚定义(Hirose BM24-50DS/2-0.35V,50 pin + 2 固定脚)
图纸 Sheet 40。这块板上没有 USB-C 母座——母座、CC、口温 NTC、ESD 全在尾插小板上,本 PDF 只覆盖主板。
⚠️ 又一个同名陷阱:GND2 固定脚是 USB_VBUS
和 J600 的 GND3/GND4 一样,J1401 符号里叫 GND2 的固定脚,实际网络是 USB_VBUS(挂 C1415/C1416/C1417 去耦 + CR1402 ESDA13P70-1U1M TVS)。G1 才是真地。
整个 USB 的供电就走这一个固定脚——Hirose 的 holddown 接触面积远大于 0.35mm 信号脚,是刻意这么设计的。
完整引脚表
| Pin | 网络 | Pin | 网络 | |
|---|---|---|---|---|
| 1 | MIC_BIAS1 ※ | 2 | TUNER_C ※ | |
| 3 | GND | 4 | VREG_L19A_3P0 | |
| 5 | CDC_MICIN | 6 | VREG_S4A_1P8 | |
| 7 | CDC_MICIP | 8 | SAR_INT | |
| 9 | GND | 10 | SSC_I2C1_SCL | |
| 11 | HEADSET_MIC_P_S_FL | 12 | SSC_I2C1_SDA | |
| 13 | GND | 14 | VREG_L16A_2P7 | |
| 15 | CDC_HPH_R | 16 | GRFC8 | |
| 17 | CDC_HPH_REF | 18 | GRFC9 | |
| 19 | CDC_HPH_L | 20 | US_EURO_SEL | |
| 21 | GND | 22 | USB_AUDIO_EN1 | |
| 23 | HAPTICS_OUT+ | 24 | DEBUG_UART_TX | |
| 25 | HAPTICS_OUT− | 26 | MBHC | |
| 27 | GND | 28 | GND | |
| 29 | DEBUG_UART_RX | 30 | USB_CC1 | |
| 31 | GND | 32 | USB_CC2 | |
| 33 | SPKR_OUT_N | 34 | VREG_BOB | |
| 35 | SPKR_OUT_N | 36 | GND | |
| 37 | SPKR_OUT_N | 38 | USB_CONN_THERM | |
| 39 | SPKR_SNS_N | 40 | GND | |
| 41 | SPKR_SNS_P | 42 | SPKR_ID | |
| 43 | SPKR_OUT_P | 44 | GND | |
| 45 | SPKR_OUT_P | 46 | USB3_HS_DP | |
| 47 | SPKR_OUT_P | 48 | USB3_HS_DM | |
| 49 | GND | 50 | GND | |
| G1 | GND | G2 | ⚠️ USB_VBUS |
※ = 由局部连线推得,未逐脚目视复核,用前实测确认。其余为几何追踪 + 目视复核。
这张表自校验通过:D+ / D−(46/48)两侧正好是 GND(44、50)做屏蔽;CC1 / CC2(30/32)两侧也是 GND(28、36)。差分对被地包夹是必然的布线约束,能对上说明引脚映射正确。
⚠️⚠️ 编号是「奇偶行」不是「DIP 绕圈」——立创的封装是错的(2026-09-04 画转接板时查清)
BM24 是 2 排 × 25 脚。两种编号方式差别巨大:
| 方式 | 排法 |
|---|---|
| 奇偶行(Hirose 真实编号) | 1,3,5…49 一排;2,4,6…50 另一排。第 n 脚和第 n+1 脚跨排相邻 |
| DIP 绕圈 | 1…25 一排;26…50 反着排另一排 |
小米8 图纸用的是奇偶行,三条独立证据:
- 符号本身:J1401 左列画的是 1,3,5…49,右列 2,4,6…50。
- 差分对被地包夹:偶数排上 44/46/48/50 = GND / D+ / D− / GND 依次相邻,是教科书式的
USB 走法。按 DIP 绕圈读,D+(46) 两边会变成 45/47(都是
SPKR_OUT_P),说不通。 - 两排分工干净:奇数排全是音频(MIC / HEADSET / CDC_HPH / HAPTICS,中间夹 GND),
偶数排全是数字与电源(VREG / I²C / UART / CC / USB / GND)。而且 33/35/37 三脚并联
SPKR_OUT_N、43/45/47 三脚并联SPKR_OUT_P—— 并联的大电流脚在同一排上连续, 按 DIP 绕圈读则中间会插进 34/36(VREG_BOB/ GND),不可能。
而立创的封装 CONN-SMD_BM24-50DP-2-0.35V51 用的是 DIP 绕圈(实测把它放到 PCB 上读焊盘
坐标:1..25 在 y=+34.45 一排自左向右,26..50 在 y=−34.45 一排自右向左)。母座
BM24-50DS(C424561)也一样。照搬它会把 50 个脚全接错。
还有两处不一致,一并记下:
- 立创符号有 54 个脚(50 信号 + 51/52 + 53/54),而 LCSC 参数页写「总PIN数 52P」。 对照 Hirose 规格书的推荐 PCB 图:header(DP) 每端两个大焊盘、receptacle(DS) 每端一个, 所以 51/52 是同一个电源触点的两个焊盘,53/54 是另一端那个。DS 封装确实只有 51/52 两个。
- 立创符号把 51/52 画在 pin1 那一端,封装却把 53/54 放在 pad1 那一端 —— 符号和封装自相矛盾。
上面三条证据同时证明了本节这张引脚表是对的 —— 三个独立角度互相印证。
封装已经自建完了(2026-09-04 深夜,改走方案 D 之后):见 §24。 几何不是按上面那句「按 30/40 脚外推」做的 —— 后来拿到了 Hirose 官方样本, 50 芯的 A/B/C 表里就有(A=12.25 / B=8.40 / C=12.55),不用外推。 (那句外推公式里的 G/H/D/E 是 Header(DP) 那一侧的尺寸,和我们要的 DS 座对不上,已作废。)
G1(GND) / G2(USB_VBUS) 落在哪一端仍然要用万用表量 (量两个电源触点对主板地的电阻,~0 Ω 的那个是 G1)—— 这一位错了转 180° 就能纠。真正致命的是另一位(哪一排是奇数排),见 §24.3。
接 USB 需要的全部脚
| 信号 | 引脚 | 去向 |
|---|---|---|
| VBUS | G2 固定脚 | → PMI8998 USB_IN / SMB1355 |
| D+ | 46 | → SDM845 HS PHY 和 PMI8998 USB_DP(163)(BC1.2 检测共用) |
| D− | 48 | → SDM845 HS PHY 和 PMI8998 USB_DM(176) |
| CC1 | 30 | → PMI8998 CC1_ID(151) |
| CC2 | 32 | → PMI8998 CC2(150) |
| 口温 NTC | 38 | → USB_CONN_THERM,快充过温保护 |
| GND | G1 + 3/9/13/21/27/31/49/28/36/40/44/50 |
Rd 下拉在 PMI8998 内部(它自带 Type-C 端口控制器),所以自制小板上 CC1/CC2 直连座子即可,不需要外部 5.1k。
13.5 接 USB 的两个硬问题(结论已定稿,实现见 §15)
问题一:0.35mm 间距,飞线是不可能的
BM24-50DS 是 0.35mm 间距 50 脚。不要试图往单个 pin 上焊线,做不到,也会毁掉座子。三个可行方案:
| 方案 | 做法 | 评价 |
|---|---|---|
| A. 装原厂尾插小板(推荐) | 整块装上,一根 FPC 插上 | USB-C 母座、CC、ESD、口温 NTC、麦克风、天线馈点全在上面,零风险 |
| B. 买"小米8 尾插排线"配件 | 只用它的 USB-C 母座那一段 | 便宜,但要自己确认排线上有没有 NTC |
| C. 自制小板 | 买 Hirose BM24-50DP(对插公座)焊到自制板,再引 USB-C | 唯一可靠的自制路线;必须补一个 10kΩ NTC 到 pin 38,否则手机可能报口温异常、拒绝快充 |
既然你已经决定不要尾插的其他功能,方案 A 仍然是成本最低的——那块小板本身就是块 FPC,占不了地方,还顺带把 §13.6 的 WiFi 天线风险一并消除了。
方案演变(2026-09-04 一天之内改了三次,最终是方案 D)
| 时间 | 方案 | 为什么被推翻 |
|---|---|---|
| 白天 | C 自制 BM24 转接小板 | 要打样 0.35 mm + 钢网 + 回流;立创封装编号还是错的 |
| 当晚 | A 装原厂尾插小板 + USB-A转C 线改端子 | 体积大;USB 链路里多一层 USB-C 插拔 |
| 当晚更晚 | D ⭐ 原厂主板-尾插排线 + 载板上一颗同型号 BM24 座 | 定稿 |
⭐ 方案 D(最终定稿):原厂排线直连载板
手机主板 J1401(BM24-50DS)
│
└── 原厂「主板→尾插」排线(两端 BM24 公头,用户实物见 2026-09-04 照片)
│
└── 载板上的 BM24-50DS 座(J71~J75,每台一颗)
│
└── 载板上就地做 Rp / 口温 / ESD / 去耦 → USB Hub
为什么它比 A 和 C 都好:
| A 原厂尾插小板 | D(定稿) | C 自制转接板 | |
|---|---|---|---|
| 自制 0.35 mm 板 | 否 | 否(排线是原厂件) | 是 |
| 电路在哪 | 都在原厂件上 | 全在载板上,阻值随便改 | 在小板上,难返修 |
| 插拔点 | J1401 + USB-C | J1401 + 载板座,各一次 | J1401 + 1.25mm |
| 体积 | 多一块小板 + 一根 USB 线 | 最紧凑 | 中 |
| 载板改动 | 无 | J17~J21 换成 BM24 座 + 每路 4 个件 | 无 |
天线/麦克风怎么办(2026-09-04 用户拍板):
「wifi 和蜂窝天线我直接买另外的插在主板上,麦克风振动马达不需要,只要能开机正常运行系统就行」
所以 §13.6 那条「WiFi 馈点可能在尾插侧」的致命项不再成立 —— 用户自己配天线。 副麦克风、震动马达、扬声器一律不要。
⚠️⚠️ 方案 D 的唯一硬前提:排线两端的引脚映射必须实测
我们只有主板图纸(§13.4 的 J1401 表),没有尾插小板图纸, 所以排线是 1:1 直通还是翻转的(pin n ↔ 51−n / 奇偶排对调)不知道。
好消息是这只影响封装,不影响原理图:
- 原理图按 §13.4 的 Hirose 编号画(D+ = 46、D− = 48、CC1 = 30、口温 = 38、 地 = 3/9/13/21/27/28/31/36/40/44/49/50、两个电源触点 = G1(GND)/G2(VBUS))—— 这一层无论排线怎么翻都是对的。
- 翻转与否被吸收进封装:立创的 BM24 封装本来就是 DIP 绕圈编号、和 Hirose 对不上 (§13.4 末尾),所以这颗座子无论如何都要自建封装。 自建时把「焊盘号 = 经排线看过去的 Hirose 脚号」定死即可。
⚠️ 2026-09-04 深夜更正:上一句原来写的是「两种候选正好差一个 180° 旋转, PCB 上转一下贴片方向就能切换」—— 这句是错的,候选有四个不是两个。 四个候选 = 2(1 脚在左端还是右端)× 2(奇数脚在上排还是下排); 180° 旋转只在其中两两之间换,剩下那一位是镜像,转贴片方向换不掉, 错了就是重打载板。详见 §24.3。
✅ 2026-09-04 已实测确认的三件事
用户拿到实物后确认:
| # | 结论 | 影响 |
|---|---|---|
| 1 | 主板上有两个对插的小圆孔(射频座) | 天线可以直接插主板 → §13.6 的致命项彻底解除 |
| 2 | 尾插小板上的 BTB 是母座 | 载板放 C424561 BM24-50DS 是对的,不用改;也说明排线两端都是公头,和主板 J1401 是 DS 自洽 |
| 3 | 排线是 1:1 直通 —— 上方内侧↔下方内侧依次通、上方外侧↔下方外侧依次通 | 见下,这条最值钱 |
排线 1:1 直通意味着什么
载板那颗座子就是 J1401 的电学克隆(同型号 DS + 直通排线 + 两端同为公头)。所以:
原理图按 §13.4 的 Hirose 编号画就是对的,一行都不用改。
翻转问题被降级成纯粹的封装 / 贴片方向问题:我们的座子在排线的另一端, 相对 J1401 天然转了 180°,引脚号会变成 N ↔ 51−N(两个电源触点也跟着对调)。 这个由自建封装的焊盘编号吸收,或者贴片时转 180° —— 网表不动。
⭐ 引脚映射已经推导完了(2026-09-04)
用户实测的原话:「从左到右,上下内侧一一导通,上下外侧一一导通」—— 也就是排线在摊平的那个平面里是恒等映射(不换排、不倒序)。 照片又确认两个公头在同一面、相差 180°(各自的软板出线方向相对)。
于是在各自的本体坐标里:
公头A(某排, 第 m 个) ↔ 公头B(同一排, 第 26−m 个) ← 排不变、序号反过来
母座与插上去的公头引脚一一重合(pin1 对 pin1),这条关系原样传给两个母座:
J1401 的第 (排, m) 脚 ↔ 载板座子的第 (同排, 26−m) 脚
再套 §13.4 已经证明的奇偶排编号(1,3,5…49 一排 / 2,4,6…50 另一排):
| J1401 脚号 | → 载板座子脚号 |
|---|---|
| 奇数 N | 50 − N |
| 偶数 N | 52 − N |
自检:1→49、2→50、49→1、50→2,奇偶不变(排没换)✔
关键网络的落点(已写进 .claude/c5_j1401.py 的 map_pin()):
| 网络 | J1401 | → 载板座子 |
|---|---|---|
| D+ | 46 | 6 |
| D− | 48 | 4 |
| CC1 | 30 | 22 |
| 口温 | 38 | 14 |
| CC2(必须悬空) | 32 | 20 |
| GND ×12 | 3,9,13,21,27,31,49 / 28,36,40,44,50 | 1,2,8,12,16,19,23,24,29,37,41,47 |
⭐ 这条推导不需要知道「哪一排是奇数排」 —— 两边都用 Hirose 脚号表达, 那个一直缺的绝对基准在等式两边自己抵消掉了。
电源触点:约定符号 pin51 = Hirose pin1/2 那一端、pin52 = pin49/50 那一端
(自建封装时按这个编号)。J1401 的 G1(地) 在它的 pin1/2 端,
经上面的反序落到我们这颗的 pin49/50 端 → 52 = GND、51 = VBUS。
✅ 2026-09-05 实测印证:用户量到 J1401 右端的大触点对地导通 = G1(顶视、接口边朝下),
即 1/2 脚端在右端 ⇒ 左端是 G2(USB_VBUS);折叠不翻长轴方向,落到载板这颗的 −X 端,
正是我们封装里 pin51 = VBUS 的位置。两边独立得出同一结论。(详见 §24.3)
⚠️ 首件仍要用万用表确认,接反就是 5 V 对地短路。
⚠️ 同时带出来一条机械硬约束:排线只能走「台阶式下折」
两个公头在同一面,意味着装配时两个母座都得朝上、大致共面 (手机里主板和尾插小板就是这么摆的)。而我们这边 J1401 朝天、载板座子也朝天、 载板在手机下面,所以:
| 走法 | 净旋转 | 公头B 朝向 | 能不能用 |
|---|---|---|---|
| 台阶式下折(下 90° 再上 90°) | 0° | 仍朝下 | ✅ |
| U 形回折(绕手机边沿兜一圈) | 180° | 翻成朝上 | ❌ 插不进去 |
→ 载板上那颗座子必须放在手机轮廓之外、J1401 出线的那一侧, 让排线顺着同一个方向下一个台阶。这条要在 PCB 摆位时就定死。
⚠️ 2026-09-05 补:排线实长约 87 mm,而
J7n只在手机板边外 3 mm —— 有 80 mm 以上的余量。 用户拍板「排线长度不用管,我到时折叠一下」, 所以J7n不挪位、台阶式下折的结论不变。 但折叠的那一坨会占手机上方的高度,定压板高度(h_up,§22.3d)时必须把它算进去。
还要不要那块小板 —— 不用了(2026-09-04 结论)
小板本来能给三样东西,现在只剩一样还悬着,而且风险很低:
| 小板本来能给 | 现在 |
|---|---|
| 引脚映射交叉验证 | ✅ 已从排线实测推出来(上面那张表) |
| 确认座子是公是母 | ✅ 用户目视确认是母座 |
| 口温电阻真值 | ✅ 从主板图纸反推出来了,见下 |
⭐ 口温电阻:不用量小板,从主板图纸就能定(2026-09-04)
主板 Sheet 36(PDF 第 38 页)上,USB_CONN_THERM 接的是 SMB1355:
SMB1355 BIAS(pin1) ──[R640 20 kΩ ±1% 0201]──┬── TSKIN(pin7)
└── USB_CONN_THERM → J1401 pin38 → 小板 NTC → GND
也就是主板出偏置、串 20 kΩ 作上臂,小板上的 NTC 是下臂,分压点送进 SMB1355 的 TSKIN。 (另外那颗 C633 100 nF 是 VAACA 的去耦,和这条链路无关,别看串行了。)
由此反推 NTC 规格:分压灵敏度在 R_ntc = R_bias = 20 kΩ 时最高,
所以原厂 NTC 在关心的温度点上应该落在 20 kΩ 附近:
| 候选 | R = 20 kΩ 发生在 | |
|---|---|---|
| 10 kΩ NTC(B≈3435) | 约 8 °C | ❌ 过温传感器不会把灵敏区放在 8 度 |
| 100 kΩ NTC(B≈4250) | 约 63 °C | ✅ 正好是接口过温的跳变区 |
而且 100 kΩ / B=4250(104EF、104FB 那一类)本来就是高通的标准热敏件 ——
内核里 adcmap_100k_104ef_104fb 那张查表就是为它做的。
→ 原厂是 100 kΩ NTC,不是本节早先猜的 10 kΩ。
我们放的是固定电阻,所以:
| 放什么 | 手机读到 | |
|---|---|---|
| 100 kΩ(定稿) | 约 25 °C(正好是 NTC 的标称点) | ✅ |
| 10 kΩ | 60 °C 以上 | ❌ 可能触发热限制 |
R771~775 已改成 100 kΩ(C25741)。
风险仍然很低:我们本来就用 input_suspend 关掉了充电,就算读数不准
也最多在内核里多一条告警。首台机上验一下即可:
for z in /sys/class/thermal/thermal_zone*; do
echo "$(cat $z/type) $(cat $z/temp)"
done | grep -iE 'conn|usb|skin'
读到接近室温 = 对了;读到荒唐值 = 换另一个阻值再试。
如果还是想在实物上量(备用)
拿一块裸的尾插小板:找 USB-C 附近那颗热敏电阻,量「BTB 座的 THERM 触点 → 小板 GND」 的总电阻(把整个网络都包进去,包括可能的串阻)。 判别是不是 NTC:量完用手指或热风捂一下再量 —— NTC 阻值会明显下降,普通电阻几乎不变。
⚠️ 唯一的弱环:G1/G2 落在哪一端,用一次开机前的测量兜住
推导链里最弱的一环是「图纸符号上 G1 画在 pin1 那头 = 物理上真在那一端」。 这是读符号推的(虽然同一张符号的奇偶排排法已被三条独立证据验证), 而接反的后果是 5 V 直接灌进手机的地 —— 一条短路,而且手机根本看不到 VBUS (§13.4:整个 USB 供电只走 G2 这一个固定脚,50 个信号脚里没有 VBUS)。
兜法不用加任何硬件:VBUS 负载开关(TPS22918)本来就默认关断
(R701~705 100 kΩ 下拉,§15.2 对策 2 / ESP32 复位期间全断)。首件流程:
- 载板焊好,排线插上手机、插上载板,先不使能 VBUS;
- 万用表量载板上
VBUSn网络对 GND 的电阻; - 读到接近 0 Ω = 接反了(此刻只有万用表在量,没有电流);读到高阻 = 对的;
- 确认后再让 ESP32 拉高
VBUS_ENn。
一次测量、零成本、100% 抓得住。若真反了,把 c5_j1401.py 里的
PWR = {'GND': 52, 'VBUS': 51} 对调再重跑,封装也跟着改。
⭐ 最省事的办法:买一块原厂尾插小板当量具(2026-09-04 想明白)
不用查图纸(查过了,公开渠道没有小板资料,见下),也不用在 0.35 mm 的排线插头上扎针。
道理:我们载板上那颗座子,接的就是原厂小板上那颗座子的位置—— 同一根排线的同一端插进去。所以「物理位置 ↔ 网络」的对应关系, 照抄原厂小板的就一定对,根本不需要知道 Hirose 编号,也不需要知道排线翻没翻。
做法(拿一块裸的尾插小板,不装机):
- 万用表打通断,从小板上 USB-C 母座的引脚出发(0.5 mm 间距,比排线插头好扎多了,
而且是裸板,走线扇出后有大片可扎的地方):
- D+ / D− / VBUS / CC1 / CC2 / GND 各自通到小板 BM24 座的哪个位置;
- 口温 NTC 的那一脚通到哪个位置。
- 把结果按物理位置(哪一排、从哪一端数第几个)记下来,抄进我们自建的封装即可。
顺带一次解决另外三个问题:
| 顺带解决 | 怎么解决 |
|---|---|
座子是公头还是母座(C424561 DS / C424560 DP) |
看一眼小板上那颗是什么,照抄 |
| 口温电阻到底该用多大(10 k 还是 100 k NTC) | 直接量小板上那颗,抄真值 |
| ESD 该用什么 | 看小板上有没有、是什么封装 |
一块尾插小板十几二十块钱,比任何图纸都便宜、也比图纸可靠(图纸还可能是别的版本)。
备用办法:直接量排线(更麻烦,只在拿不到小板时用)
- 排线插上手机 J1401(手机不通电),万用表打通断,一表笔搭手机屏蔽罩(地);
- 在排线自由端 50 个触点上走一遍(针尖表笔 + 放大镜),记下哪些响 = 地;
- 对照 §13.4 的地脚分布 —— 奇数排的地在第 2,5,7,11,14,16,25 位, 偶数排的地在第 14,18,20,22,25 位。这个图案旋转 180° 后完全不同, 所以量出来就唯一确定了映射方向。
- 顺手确认两个大焊盘(电源触点)哪个通地 —— 那个是 G1,另一个才是 G2(VBUS)。 接反就是 5 V 对地短路。
不管走哪条路,都要目视确认这根排线确实是尾插排线 —— 小米8 主板上有两个 50 脚 BM24:J1401(尾插,母座)和 J1102(屏幕,公头),别拿错。
📕 公开渠道没有小板资料(2026-09-04 查过,别再查了)
- 我们手上这份
Xiaomi_Mi_8_Schematic.pdf(Rev E8)44 页全是主板, 按关键字扫过一遍:USB_CC1/CC2、USB_CONN_THERM、USB_VBUS只出现在 PMI8998 侧和 J1401 那一页,没有任何一页画 USB-C 母座。 - mobilerdx 的「Mi 8 完整包」里只有 Block Diagram / Schematics / Parts List / Component finder 四份,就是我们这份的同一套,没有小板原理图也没有 boardview。
- vinafix 上 dipper 只有 Mi 8 Lite / Mi 8X(Mi A3),都是别的板子(§22.3b 早查过一次)。
- 维修行业换小板是整块换,不需要它的原理图 —— 所以本来就不会有。
已作废的方案 A 记录(2026-09-04 晚),留档备查
(当时的定稿)装原厂尾插小板(或买原厂尾插排线),载板侧不做任何 USB 相关电路。
连接方式:
手机 J1401 ──原厂尾插排线── USB-C 母座
↑
USB-A 转 C 线(剪掉 A 头,压 1.25mm 4P 端子)
↓
载板 J17~J21(A1251WV-S-4P,一行都不用改)
为什么改回来(用户 2026-09-04 晚确认):一旦决定「用排线连接主板和载板」, 方案 C 相对方案 A 就没有任何优势了,而方案 A 把下面这些一次性全消掉:
| 方案 C 要解决的 | 方案 A 里怎么消失的 |
|---|---|
| CC1 上拉 56 kΩ Rp | USB-A 转 C 线的 C 头里本来就有 56 kΩ(Type-C 规范强制要求,Default USB 档) |
| pin38 口温电阻(阻值还是猜的) | 原厂尾插小板上就是正确的那颗 |
| D± 的 ESD | 原厂尾插小板上本来就有 |
| CC2 悬空 | 线缆自己处理 |
| 自建 BM24-50DP 封装(立创那个编号是错的) | 不用做板了 |
| 0.35 mm 打样 + 钢网 + 回流 | 不用做板了 |
| §13.6 的天线馈点风险(原本是致命项) | 尾插小板装上了,馈点回来了 |
| 丢麦克风 / 扬声器 / 震动 | 全都回来了 |
代价只有一条:多一块原厂小板的体积和重量。对机架式手机农场无所谓。
⚠️ 买线注意:必须是 USB-A 转 C,不能是 C 转 C 或不带 Rp 的 C 公头带线 —— Rp 就藏在 A 转 C 线的 C 头里。到手先用万用表量一下 CC 对 VBUS 是不是 56 kΩ (市面上确实有阻值给错的劣质线,会让手机误判成 1.5 A / 3.0 A 档)。 端子顺序按载板 J17:1=VBUS 2=D− 3=D+ 4=GND。
⚠️ BM24 只有 10 次插拔寿命(Hirose 规格书 Durability 一栏)。 这条在方案 D 下更要紧 —— 一根排线上有两个 BM24 插拔点。
以下是已作废的方案 C 记录(2026-09-04 白天),留档备查
原话是「不接尾插小板,直接接到主板的尾插板接口」。这把上面的推荐推翻了, 下面三条是方案 C 必须补的,缺一条手机就可能不认 USB 或报错:
| 必补 | 为什么 |
|---|---|
| CC1(pin 30)经 56 kΩ 上拉到 VBUS | ⚠ 见下 |
| pin 38 接一个 10 kΩ NTC(或先用固定 10 kΩ 电阻顶上) | 口温检测,缺了可能报口温异常、拒绝快充 |
| CC2(pin 32)悬空 | 只拉一边 CC,手机才能判出插入方向 |
⚠️ CC 这一条是对 §13.4 结尾那句话的修正。 §13.4 写的是 「Rd 下拉在 PMI8998 内部,所以自制小板上 CC1/CC2 直连座子即可,不需要外部 5.1k」—— 那句话的前提是自制小板上还有一个 USB-C 母座,Rp 由插进来的线缆/主机侧提供。 现在我们把 D± 直接硬接到板载 Hub 上、整条链路里根本没有 USB-C 连接器了, 就没人提供 Rp 了。手机的 PMI8998 是靠 CC 上看到 Rp 才判定「有 DFP 插入」 并把 USB PHY 切到 device 模式的;CC 两根都悬空,很可能只充电不枚举。 所以转接小板上必须自己放这颗 56 kΩ(默认电流档)Rp。
物理形态:J1401 在主板正面朝上(§22.3b),而载板在主板下面 —— 所以对插的 BM24-50DP 不能直接焊在载板上,只能做成一小块转接板/软板, 从上面插进 J1401,再引 4 根线(VBUS / D+ / D− / GND)下来。 载板那头就是现成的 J17~J21(A1251WV-S-4P,1.25 mm 4P), 原理图完全不用改 —— 变的只是插上去的东西从「USB-A 转 C 短线」换成「J1401 转接板」。
代价,先说清楚:0.35 mm 间距 50 脚的 BM24-50DP 手工焊不了, 这块转接板得打样 + 钢网 + 回流;而且不装尾插小板就同时失去了麦克风、扬声器、天线馈点 (§13.6)。农场机走 WiFi、不用通话的话都不影响。
(↑ 就是这一段里的「天线馈点」把方案 C 拖垮的 —— §13.6 把它标成致命项, 而方案 A 一装上就不用做那个三步 RSSI 实测了。)
问题二:USB 供电会和电池直供打架 ⚠️
这是接 USB 之后最容易炸的一条,必须在设计阶段处理。
机理:接上 VBUS 后,手机的充电器看到"电池"电压 3.9V,认为电量约 50%,于是按设定电流(最高 3A)往 B+ 灌电。而 B+ 是我们 Buck 的输出,被钳在 3.9V。结果:
- 我们的同步 Buck 被反灌,进入反向工作,把能量泵回 12V 母线;
- 12V 适配器不能吸收电流,母线电压被抬高 → 可能触发适配器 OVP 或损坏;
- 若 Buck 吸不动,
B+电压上冲 → 电池保护板 4.28V OVP 断开 → 手机瞬间失去 VBAT → 关机。
三条对策,建议全做
-
软件关充电(最省事,首选) 农场机本来就 root。写高通平台的抑制节点:
echo 1 > /sys/class/power_supply/battery/input_suspend(节点名各 ROM 不同,也可能是
charging_enabled/battery_charging_enabled,首台机上确认一次即可。) 这样 USB 只做数据和自身供电,不给"电池"充电,直供完全不受干扰。 -
VBUS 加 ESP32 可控负载开关(硬件兜底) VBUS 路径串一个负载开关,默认断开,只在需要有线 adb / 刷机时接通。 固件互锁:VBUS 接通期间监控该路 INA226 —— INA226 是双向测量的(±81.92mV 分流电压,有符号),出现负电流(反灌)或电压被顶高超过设定值 +100mV,立刻断 VBUS 并告警。
-
12V 母线加泄放(几毛钱的保险,必须加) TL431 + N-MOS + 10Ω/5W 的分流泄放器,母线超过 13.2V 时导通。 防的就是"某一路被反灌 → 能量泵回母线 → 母线抬高 → 连累其他四台"。 这一条即使不接 USB 也建议加:Buck 在负载突卸时同样会有少量能量回灌。
对 §9.1 BOM 的追加:TL431 ×1、N-MOS(30V/5A)×1、10Ω/5W 泄放电阻 ×1、VBUS 负载开关 ×5(TPS22918 一类,5V/2A,带 EN)。
接 USB 之后的能力提升
| 能力 | 说明 |
|---|---|
| 有线 adb | WiFi adb 不通时的兜底通道,比断电重启温和 |
| Fastboot / EDL 刷机 | 配合 §13.3 的按键组合,远程救砖闭环 |
DEBUG_UART_TX/RX(pin 24 / 29) |
如果自制小板,顺手把调试串口引出来——内核 panic 时这是唯一能看到原因的通道,对排查"随机重启"极其有用 |
13.5 电池排线改造
排线的物理结构
BTB座 ──FPC走线── [P+ / P−] ──保护板 MOS── [B+ / B−] ──电芯焊点(已拆)
↑ ↑ ↑
主板 J600 **接这里** 原方案接这里
(保护板输出侧)
关键事实:保护板的两颗背靠背 MOS 串在负极,位于 P− 与 B− 之间;正极 B+↔P+ 是直通的。
所以接 P+/P− 时电流直接进 BTB 座,根本不经过那两颗 MOS;B− 悬空后,保护 IC 就算仍在上电工作、就算检测到过压去关 MOS,也影响不到这条通路。
保护板自动退出,不用拆、不用飞线短接、不用改排线任何东西。 而 BTB 公座、BATT_ID、BATT_THERM(NTC)全部原样保留——这两根信号缺了手机可能拒绝开机,自制转接板反而要重新解决。
⚠️ 别焊错边
焊到 B+/B− 就等于又把保护板串了回去,而且现象上完全正常,只有在过压时才会暴露(保护板抢先动作,手机莫名掉电)。
判别方法(万用表电阻档,排线离机):
| 步 | 操作 | 判据 |
|---|---|---|
| 1 | 从 BTB 座 pin 7 / 8(VBATT)量到两个候选正极焊点 | 阻值≈0 的是 P+ |
| 2 | 从 BTB 座 pin 1 / 2(GND)量到两个候选负极焊点 | 阻值≈0 的是 P−;另一个(读到二极管压降或开路)是 B− |
| 3 | 焊接后复测 | P− → BTB pin 1/2 必须是通路,且与 B− 不通 |
第 2 步的原理:
B−与P−之间隔着未上电的 MOS,只有体二极管,正反测阻值不对称;P−到 BTB 是纯铜箔,双向都接近 0Ω。
做法:电芯从 B+/B− 分离后,电源板输出焊到 P+/P−,§6.3 的电容组也装在这里,BTB 插回主板 J600。
安全提示:拆电芯时用绝缘工具,先剪正极再剪负极,不要同时接触两极。电芯单独存放,不要留在工位上。
为什么不自制 BTB 转接板
查过立创库:只有 5050040812(C724121)——那还是母座,和主板上的 J600 同类,没有对插的公座(Molex 505003-08xx plug)。自制转接板需要自行采购 Molex 原厂件手贴,还要自己复制 BATT_ID(若是 1-wire 认证 IC 则无法复制)。用原厂排线是明显更优解。
⭐ 2026-09-06 改法:在保护板焊点处剪断排线,4 个焊盘直接焊到载板(用户提出,实测中)
用户把排线从保护板上拆下来了。排线与保护板的接口是 4 个焊盘一排,用户在保护板上实测(从离 B+ 引线最近的那个数起):
| 序 | 焊盘 | 实测 |
|---|---|---|
| 1 | P+ | 对 B+ 引线通断档 ≈0(B+↔P+ 直通铜箔) |
| 2 | P− | 对 B− 开路(隔着背靠背 MOS,符合预期) |
| 3 | TEMP(BATT_THERM) | 对 P− 10 kΩ NTC |
| 4 | ID(BATT_ID) | 对 P− ≈68 kΩ 固定电阻(不是认证 IC,可以复制) |
⚠️ NTC 和 ID 都是对 P− 的,对 B− 量是几十 MΩ 漂移(开路)。第一次按"对负极线"量会得出"三个都不通"的假结论。
改法:保护板整块不要。载板每站把 TP8n1/TP8n2 两个 Ø2.7 通孔焊盘换成一个 4 焊盘 FPC 手焊封装(底层,位置不变:主板投影下方贴接口边),
加两颗电阻:TEMP → GND 10 kΩ(固定电阻模拟 25 °C,手机不充电,只需要读数正常)、ID → GND 68 kΩ。原理图 C4-SITE1~5 各加两颗。
好处:不用再手焊两根线、保护板不再吊在排线上、§13.5「焊错 B+/B− 边」的风险消失、排线两头都固定。电池槽 10 × 3 不用动(只过 8 mm 宽的排线)。
封装按保护板上的焊盘图案抄(间距 / 焊盘尺寸 / 离排线进入边的距离用卡尺量保护板,比量排线好量): 排线是面朝下焊在保护板上的,载板上它同样面朝下焊,只要排线从同一侧进来,载板底层焊盘的顺序 = 保护板焊盘面看到的顺序,不用镜像。 排线焊盘面 = BTB 插头触点面(手机里两者都朝显示屏那一侧);按 §25.16 v4 的弯折推算,排线绕过接口边、穿槽、折回主板下方之后这一面正好朝载板背面, 所以焊盘留在现在 TP8n1/2 的位置就行。装之前把排线摊平核一眼:4 个焊盘和插头触点若不在同一面,焊盘要改到槽外侧(走廊那边,排线穿过去后不折回)。
✅ 已量并已落地(2026-09-06 晚):焊盘 1 × 2 mm、间距 2.0、排线尾巴伸出焊盘行 8 mm(装配时剪到留 1 mm,露出载板焊盘外伸的那一截给烙铁)。
| 落地项 | 内容 |
|---|---|
| 封装 | 个人库 FPC-4P-P2.0_MI8-BAT(d0a99d3d…,fp_batfpc.py):4 焊盘 1.1 × 4.0 上下对称(各多伸 1 mm),1 = P+ … 4 = ID 从 −X 到 +X;丝印画 8 mm 排线边 |
| 器件 | 个人库 MI8-BAT-FPC-4P(22b0c3130f0b4ff6baab529761dab3e4),符号借立创 PZ254V-11-04P 的 4 脚(副本 bf0085b7…),Convert to PCB = yes 已核 |
| 原理图 | C4-SITE1J8n(J81R78n 10k TEMP→GND、R79n 68k ID→GND;母线西端 150→90 给四条竖走廊。六项验证 / 跨页 / port_audit 全过 |
| PCB | 导入 166 件(+5);pcb2_place.py v4b:J8n 放到主板下方远处 (22.8, 15.0)(用户拍板「35 mm 排线够得到的地方」:J600 4.6 + 绕边 5 + 到槽 2.7 + 穿板 1.6 + 背面 17.7 ≈ 31.6 ≤ 35,实长 38),电池排线车道 BAT_LANE u 18.8 |
| 铺铜 | Inner1 主板下方那块岛 v −1 |
| 手性 | BAND['j8'] rot 0 = P+ 在本体 −u。判法:排线插在 J600 上,主板 J600 那一面朝上、接口边朝自己,排线摊平朝自己伸出(焊盘面朝桌子),把排线末端向上翻折 180°(折线平行于排线宽度方向,翻完焊盘面朝上、末端指回主板)——这样左右不变。用万用表找 P−(对主板屏蔽罩通断响的那个),紧挨 P− 的排端焊盘就是 P+。P+ 在左 = rot 0 正确;在右 = 改 rot 180(封装上下对称,只改这一个数)。✅ 2026-09-06 用户实测:P+ 在左,rot 0 定稿。 |
⚠️ 顺带修的一个工具 bug:pcb2_parts_dump.py 抓底层元件包围盒时只反转不反镜像,J6n 这种上下不对称的封装会误报和 J7n 重叠(skill §9w 补)。
13.6 不接尾插的风险实测 —— ✅ 致命项已解除(2026-09-04)
最终结论:方案 D 不装尾插小板,但用户确认主板上有两个对插的射频小圆孔,天线直接插主板, 所以「WiFi 馈点可能在尾插侧」这条致命项不成立。副麦克风 / 扬声器 / 震动马达一律不要 (用户原话:「只要能开机正常运行系统就行」)。下面这一节只剩第 3 步还要做。
原文(记录当时的判断过程)
副板上除 USB-C 外还有天线馈点、副麦克风、震动马达。小米8 天线主体在中框,主板只有馈点。
**方案 A 把尾插小板装回去了,所以第 2 步不用做了。**但第 3 步仍然要做:
| 步 | 配置 | 记录 | 还要不要做 |
|---|---|---|---|
| 1 | 整机原样(含中框、尾插) | adb shell dumpsys wifi | grep RSSI 作基准 |
✅ 要(作基准) |
| 2 | 仅拔尾插排线 | RSSI 变化 | ❌ 不用了,尾插装着 |
| 3 | 主板脱离中框,裸板 | RSSI 变化 | ✅ 要 |
判据:第 3 步掉得厉害 → 连中框一起固定到载板上(这会改动 §22.3 的机械方案,要早测)。
历史:这一节的第 2 步原本是方案 C 的头号风险(「WiFi 若受影响 = 致命项」), 也是 2026-09-04 晚一度放弃方案 C 的主要理由之一。用户自己配天线之后不再成立。
13.7 旁路验证(打样前必做,替代原「保护板 OVP 实测」)
原「保护板 OVP 实测」随 v1.1 移除保护板而作废。改做这三项:
| 步 | 操作 | 通过标准 |
|---|---|---|
| 1 | 按 §13.5 的判别表定位 P+ / P−,焊线,拍照存档 |
P−↔BTB pin1/2 通;P−↔B− 不通 |
| 2 | 可调电源 3.80V / 限流 100 mA 接 P+/P−,量 BTB 座 pin 7/8 与 G3/G4 |
全部 3.80V,压降 < 5 mV(证明未串入保护板) |
| 3 | 升压验证保护板确已退出:把电源升到 4.40V | BTB 座电压应跟随到 4.40V 且不断开。若在 4.3V 附近断开,说明焊到了 B+/B−,返工 |
| 4 | 插机开机 | 正常开机;dumpsys battery 温度读数正常(NTC 有效);无「非原装电池」告警或仅告警不影响使用 |
第 3 步是这套改造唯一的判定性测试,不要跳过——焊错边在常温常压下完全看不出来。
14. 实测记录表(首板前填写并存档)
J600 复核(引脚定义已由图纸确定,此处只做上机验证)
| 检查项 | 方法 | 预期 | 实测 |
|---|---|---|---|
| VBATT 脚 | 排线加 3.80V,量 BTB pin 7/8 与 G3/G4 | 3.80V | |
| GND 脚 | 同上量 pin 1/2 与 G1/G2 | 0V | |
| NTC 阻值 | 断电,量 pin 4 对 pin 1/2 | ≈10 kΩ @25°C,捂热应下降 | |
| BATT_ID 形式 | 量 pin 3 对地 | □ 电阻 ____ □ 1-wire IC □ 开路 |
侧键触点(背面,与 SIM 卡托相对的长边;附近摄照片标出位置)
| 位号 | 功能 | 触点位置 | 空闲电压(对 J604) | 短接测试 |
|---|---|---|---|---|
| J601 | 音量 + | |||
| J602 | 音量 − | |||
| J603 | 电源 | 2s 开机 / 10s 强制重启 | ||
| J604 | 公共地 | 0 V | — |
保护板 OVP(§13.7,测 3 块取最小值)
| 排线 # | OVP 阈值 |
|---|---|
| 1 | |
| 2 | |
| 3 |
→ eFuse OVP 设定 = 最小值 − 100 mV = ______ V
15. USB 子系统实现
15.1 架构与边界(2026-09-03 改为板载 Hub)
对外只有一根 USB 线。五路下行由板上的 USB2517I 分,下行 VBUS 由板上自己的 5V 轨供, 不吃上游线的电流。
电脑 ──一根 USB 线──> J23 USB-C(UFP,上游)
│ D±
┌─────┴─────────────────────────┐
│ U32 USB2517I 7 口 Hub │ 自供电(§21)
│ Y1 24MHz / R708 RBIAS 12k │ 口 6/7 已禁用
└─────┬─────────────────────────┘
│ D± ×5
12V ──U30 LMR51430──> +5V ─┬─[U24~U28 TPS22918]──> VBUS ×5(ESP32 可控,默认断开)
└─U31 AMS1117-3.3──> +3V3_HUB(只给 U32)
│
J17~J21(4 针 1.25mm)── USB 线 ──> 手机原厂尾插小板 USB-C
四条边界,定死不再改
- 上游只接电脑,VBUS 恒 5V。 板上不做 PD/BC1.2 协商:J23 的 CC1/CC2 各串 5.1kΩ 下拉(R717/R718), 对外表现为纯 UFP。没有 PD 通信,充电器最多也只给 5V, 不会把 VBUS 抬到 9V/12V 去炸 TPS22918 的 5.5V 绝对最大值。
- Hub 是自供电(self-powered),不是总线供电。 下行 VBUS 来自 U30 的 5V 轨,Hub 自身的 3.3V 来自 U31。 从上游只取 <1 mA。这条不是省事,是必须的: 若声明成总线供电,主机会按「每口 100 mA」做功率预算, 而手机的 USB 描述符通常申请 500 mA → 主机拒绝配置,手机根本枚举不上。 实现方式见 §21.3(靠 CFG_SEL=000 走内部默认配置,寄存器 06h 默认 9Bh、bit7=1)。
- 本板只切 VBUS,不碰数据线。 D± 从 Hub 出来直通到出线座,中间不串任何东西。
- 不自制 USB-C 转接板。 手机那一侧的口温 NTC(J1401 pin 38)、CC、ESD 全在原厂尾插小板上,自制必然漏项。
⚠️ 板上有两个长得一样的 USB-C:J22 是 ESP32 调试口、J23 是 Hub 上游口。 插错了不烧,但现象是「adb 整排不见」,很难想到是插错口。 丝印必须写清楚,建议再用不同颜色的座子或在外壳上做标记。 (2026-09-03 用户在「USB-B 母座」与「USB-C」之间选了 USB-C,已知并接受这个风险。)
旧方案(已作废):5 个 USB-A 母座 J12
J16,各拉一根 A 公-A 公线到外置 Hub。 当时选 USB-A 母座的理由是「物理上插不了充电头」,现在由边界 1 的「不做 PD 协商」代替。 J12J16 从 BOM 里删除。
15.2 三条对策的具体实现
对策 1:软件关充电(首选,零硬件成本)
# 高通平台常见节点,首台机上确认实际路径后写进固件的开机脚本
echo 1 > /sys/class/power_supply/battery/input_suspend
# 备选名:charging_enabled / battery_charging_enabled / usb/online
关掉后 USB 只做数据和自身供电,不给"电池"充电,直供完全不受干扰。 这是常态运行的依赖项,另外两条是它失效时的兜底。
对策 2:VBUS 负载开关 + 反灌检测
硬件:每路 VBUS 串一颗 TPS22918 负载开关(1~5.5V / 2A,带 ON 与可调上升时间),ON 由 ESP32 GPIO 直连并加 100 kΩ 下拉 → 默认断开。电路画在 P4-USB,逐项计算见 §18。
⚠️ 2026-09-03 起 VBUS 的来源变了:从「上游 USB 线缆」改成板上 U30 的 5V 轨(§9.4)。 Hub 的端口电源控制脚(PRTPWR[7:1])故意不接 —— 通断权必须在 ESP32 手里, 这是本对策成立的前提。Hub 自己以为端口一直上电,不影响这里的逻辑。
固件逻辑(每路独立):
接通 VBUS 前:确认该路 input_suspend 已生效(读 sysfs 或按上次状态)
接通后每 50 ms 读一次该路 INA226:
if I < −50 mA → 反灌,立即拉低 VBUS_EN,告警
or V > 设定值 + 100 mV → 被顶高,同上
不用时保持断开
INA226 是双向测量的(分流电压 ±81.92 mV,有符号),所以「电流为负」这个判据可以直接读出来,不需要额外电路。这是选它而不是选单向电流计的原因之一。
对策 3:12V 母线泄放(几毛钱的保险,必装)
12V 母线 ──┬── R上 ──┬── TL431 REF
│ R下
│ │
│ GND
│
└── Q_bleed(N-MOS 30V/5A) ── R_bleed 10Ω/5W ── GND
栅极由 TL431 阴极经一级驱动
阈值:13.2V 导通;泄放能力 (13.2−12)/10 ≈ 120 mA 起,母线越高吸得越多
防的是「某一路被反灌 → 同步 Buck 把能量泵回 12V 母线 → 母线抬高 → 连累其他四台,甚至触发适配器 OVP」。 即使不接 USB 也建议保留:Buck 在负载突卸时同样会有少量能量回灌。
15.3 D± 走线规则(板上唯一的高速信号)
USB 2.0 HS 是 480 Mbps,按差分对处理。
2026-09-03 改板载 Hub 之后,「目标 < 30 mm」这条作废。 一颗 Hub 要喂五个分散在板边的出线座,短不了。把 U32 摆在板子正中央 (x=79 / 板宽 160)之后,五路是 64 / 32 / 0 / 32 / 64 mm,上游 J23 到 U32 只有 16 mm。 最长 64 mm 对 USB 2.0 HS 完全够用(协议本身允许 5 m 线缆), 前提是受控阻抗 —— 长度不再是主要矛盾,阻抗和参考平面完整性才是。 顺带一提:五对之间不需要互相等长,它们是五个独立端口; 要等长的只有对内(DP 与 DM)。
- 差分阻抗 90 Ω ±10%,4 层板用 L1 走线、L2 完整地平面做参考。
- 几何:W 0.28 mm / S 0.18 mm(已写进 EasyEDA 的差分对规则)。
按嘉立创四层 1.6 mm 标准叠层 L1-L2 介质 h=0.2104 mm、εr≈4.3、
1 oz 外层(§10.1 已定稿),用微带近似
Z0 = 87/√(εr+1.41)·ln(5.98h/(0.8W+t))、Zdiff = 2·Z0·(1 − 0.48·e^(−0.96·S/h))得 Z0≈57.5 Ω、Zdiff≈90.5 Ω。 (若哪天回到 2 oz,同样几何只剩 83 Ω,W 要收到约 0.24 mm —— 铜厚 t 在分母的 0.8W+t 里。) ⚠️ 叠层、板厚、prepreg 型号一变这两个数就得重算 —— 打样前用板厂的阻抗计算器复核,别信这里的近似公式。 - 对内等长误差 < 1 mm(规则里设的是 0.5 mm,留一半余量)。
- 不跨越地平面分割,不跨 SW 节点,不与任何 Buck 的电感 / SW 铜箔重叠。
- 五路 USB 走线集中在板子的一侧,与功率区物理分开。
- 每对旁边留地过孔缝合。
- 不要在 D± 上串电阻或加 ESD 之外的任何东西——ESD 用低容(< 1 pF)的 USB 专用器件,或者干脆不加(原厂尾插小板上已有)。
15.4 每台手机的线束
⚠️ 2026-09-03:若「主板载板」方案落地,这张表基本作废 —— 三条线束会被 板对板连接器取代(每台 2 电源 + 4 按键 + 4 USB,五台共 50 根,电源合计 20 A)。 详见
PROGRESS.md的「⭐⭐ 第二件事:主板载板」。方案未定稿前,下表仍是有效方案。
| 线束 | 芯数 | 板端连接器 | 手机端 | 线规 / 要求 |
|---|---|---|---|---|
| 电源 | 2 | J2~J6 Micro-Fit 3.0 | BM3E 排线的 B+ / B− 焊点 |
18 AWG,≤ 20 cm,双绞;手机端挂 §6.3 电容组 |
| 侧键 | 4 | J7~J11 4 针 1.25 mm | J601 / J602 / J603 / J604 触点 | 细线即可,远离电源线 |
| USB | 4 | J17~J21 4 针 1.25 mm | 原厂尾插小板 USB-C | 用现成 USB 线改端子,D± 保持双绞 |
接地约定:三条线束的地在手机端是同一个地(都来自 B−),但在板上必须分别回到该路的独立地,只在板内地平面单点汇合。不要在手机端把三条地并成一根——那会把射频突发耦合进 USB 和按键线。
16. P2-CHANNEL 单路原理图(已画完,五路复制的母版)
EasyEDA 工程 PhoneRail-5CH-PSU 第 2 页。先画完整一路、确认后再复制成五路。
几何验证六项全过(verify_sch.py):0 悬空引脚、0 单引脚网络、0 无名旗端口、0 同网多名。
16.0 全板位号规则(2026-09-03 新增,必须遵守)
画 P2 时发现 P1 和 P2 的位号大面积撞车(两页各有一套 R1~R9 / C1~C10 / Q1),
而位号在整张原理图里是全局唯一的,不是每页独立。五路复制后会变成五倍。
已改成下面这套,P2 的 R/C/Q/L/Rs 全部加了 100:
| 页 / 单元 | R、C、Q、L、Rs | U(芯片) | J(连接器) |
|---|---|---|---|
| P1-INPUT(输入 + 辅助电源 + 泄放 + 输入侧检流) | 1 ~ 99(含 Rs6 / C11) | U13 / U19 / U29 | J1 |
| CH1(P2) | 101 ~ 199 | U1 / U8 / U14 | J2 / J7 |
| CH2(P2B-CH2) | 201 ~ 299 | U2 / U9 / U15 | J3 / J8 |
| CH3(P2C-CH3) | 301 ~ 399 | U3 / U10 / U16 | J4 / J9 |
| CH4(P2D-CH4) | 401 ~ 499 | U4 / U11 / U17 | J5 / J10 |
| CH5(P2E-CH5) | 501 ~ 599 | U5 / U12 / U18 | J6 / J11 |
| P3-CONTROL | 601 ~ 619 | U20 | J22(USB-C 调试口) |
| P3B-EXPAND | 601 ~ 699(同段续编) | U6 / U7 / U21 / U22 / U23 | — |
| P4-USB | 701 ~ 799 | U24 ~ U28 | J12 ~ J21 |
| P5-HARNESS(离板) | 801 ~ 899 | — | — |
- 通道号 = 位号的百位,看位号就知道是哪一路,PCB 上排查故障时省事。
- U 和 J 沿用 §9.1 已经分配好的全局编号,不加百位(它们本来就不撞)。
- P1 保持原样不动(1~99 是「全板公共」段)。
- 8xx 段是离板件(手机侧电容组),不进 BOM、不上 PCB,所以百位不表示通道;
通道写在十位上:CH1 = C801
C806,CH2 = C811C816,…… CH5 = C841~C846。
16.1 页面分区
| 区 | 位置 | 内容 |
|---|---|---|
| Buck 功率级 | 左上 | U1 TPS54622 + 输入/输出电容 + L101 + RT / EN / SS / COMP |
| 反馈与调压 | 左下 | R101 / R102 / Rinj + DAC 的 1k+10nF 低通 |
| eFuse 与检流 | 右上 | U14 TPS25940A + 外围 + Rs101 + U8 INA226 + J2 |
| 放电联锁 | 右 | Q101 反相 + Q102 放电 MOS + R119 10Ω |
| 按键驱动 | 右下 | Q103/Q104/Q105 + 栅阻/下拉 + J7 |
16.2 单路位号与取值(复制五路时只改位号后缀)
| 位号 | 值 / 型号 | 作用 |
|---|---|---|
| U1 | TPS54622RHLR | 同步 Buck |
| C101, C102 | 10 µF / 50V 0805 | 输入 MLCC(紧贴 PVIN) |
| C103 | 2.2 µF / 50V 0805 | 输入中频 |
| C104 | 100 nF 0402 | 输入高频 |
| R103 | 100 kΩ | RT/CLK → 480 kHz |
| R104 / R105 | 68.1 kΩ / 10 kΩ | EN 输入 UVLO:起动 9.37V,关断 8.84V |
| C105 | 100 nF 0402 | BOOT |
| C109 | 10 nF 0402 | SS/TR → 2.6 ms 慢启动 |
| R106 / C110 / C111 | 1 kΩ / 33 nF / 100 pF | COMP 补偿(fco ≈ 18 kHz,见 §9.2) |
| L101 | SPM6530T-4R7M | 4.7 µH |
| C106, C107 | 22 µF / 25V 1206 | 输出 MLCC |
| C108 | 100 nF 0402 | 输出高频 |
| R101 / R102 / R107 | 30.1k / 5.49k / 150k | 分压 + 注入(§4.3,2026-09-03 由 5.23k/107k 改) |
| R108 / C112 | 1 kΩ / 10 nF | DAC 低通(必须在 Rinj 的 DAC 侧) |
| U14 | TPS25940ARVCR | eFuse |
| R109 / R110 | 68.1 kΩ / 20 kΩ | OVP 分压 → 4.36V(容差窗口已由 §4.3 解决,见 §5) |
| R111 | 20 kΩ | ILIM → 4.45 A |
| C114 | 33 nF | dVdT → 0.36 V/ms,斜坡 11.5 ms,涌流 0.80 A |
| R112 | 10 kΩ | IMON 取样(本设计不用,仅作测试点) |
| R113 / R115 | 47 kΩ | FLT# / PGOOD 上拉到 +3V3(开漏) |
| R114 | 100 kΩ | EFUSE_EN 下拉(ESP32 复位期间输出全关) |
| R116 / R117 | 20 kΩ / 10 kΩ | PGTH 分压 → 输出 2.97V 以上报 PGOOD |
| Rs101 | 5 mΩ 1% 2512 | 分流(Kelvin 焊盘) |
| U8 | INA226AIDGSR | A1=A0=GND → 地址 0x40(CH2~CH5 见 §8.2 的地址表,不是顺排) |
| C113 | 100 nF 0402 | INA226 VS+ 去耦 |
| Q101 / R118 | 2N7002 / 100 kΩ | EN 反相器(硬件互锁) |
| Q102 / R119 | AO3400A / 10 Ω 1W 2512 | 放电 MOS + 泄放电阻 |
| Q103~Q105 | 2N7002 ×3 | 电源键 / 音量+ / 音量− |
| R120/R122/R124 | 1 kΩ ×3 | 栅极串阻 |
| R121/R123/R125 | 100 kΩ ×3 | 栅极下拉(复位期间不误按) |
| J2 | Micro-Fit 3.0 2P | 电源出线到电池座 |
| J7 | 1.25mm 4P | 按键出线(PWR / VOL+ / VOL− / GND) |
16.3 拓扑上的两个决定(与早期草案不同,已定稿)
① 分流电阻放在 eFuse 之后(手机侧),不是之前。
L101 → VO1(Cout、FB 取样、OVP 分压)→ U14 IN
U14 OUT → VO1_F(PGTH 分压、INA226 VIN+)→ Rs101 → VO1_P → J2
├── Q102/R119 放电
└── INA226 VIN− / VBUS
- 串联电流处处相同,所以放前放后测到的电流一样;
- 但 VBUS 因此测的是手机侧电压,这正是 §5 第三层「发现 eFuse 本身失效」所必需的 (放在 eFuse 之前只能看到 Buck 输出,eFuse 是否真的断开无从判断);
- 代价:读数含 eFuse 的 Rds(on) 压降。常态 0.5A 时只有 21 mV,远小于 ±100 mV 判据; 满载 4A 时 168 mV,固件按已知电流补偿即可。
② OVP 分压取自 eFuse 输入(= Buck 输出),PGTH 分压取自 eFuse 输出。
TPS25940 的 OVP 本来就是监视输入的,正好对应「Buck 失控 → 切断负载」这个要防的故障; PGTH 则要看下游是否真的带上电了,所以取输出。两者刻意分开。
16.4 跨页网络(P3-CONTROL 侧要对上)
| 网络 | 方向 | 对端 |
|---|---|---|
+12V / +3V3 / GND |
— | P1 |
VDAC1 |
入 | DAC63204 通道 |
EFUSE_EN1 |
入 | ESP32 GPIO 直连(安全关键) |
EFUSE_FLT1 / EFUSE_PG1 |
出 | PCA9555 输入(每路 2 根,5 路共 10 根,余 6 根) |
BUCK_PG |
出 | 五路线或到一根(都是开漏),只指示「有某一路不正常」 |
INA_ALERT |
出 | 六片 INA226 线或到一根 |
SDA / SCL |
双向 | I²C |
K1_PWR / K1_VUP / K1_VDN |
入 | 74HC595 输出(慢速信号) |
VO1_P |
出 | P5-HARNESS 的手机侧电容组(2026-09-03 新增,见下) |
复制成 5 路时要改的只有三样:
- 位号百位(1xx → 2xx/3xx/4xx/5xx),U / J 按 §16.0 的表换号;
- 七个网络名:
VDACn/EFUSE_ENn/EFUSE_FLTn/EFUSE_PGn/Kn_PWR/Kn_VUP/Kn_VDN,以及输出网络VOn/VOn_F/VOn_P;- INA226 的 A0/A1 地址跳线(地址表见 §8.2)。
BUCK_PG、INA_ALERT、SDA、SCL、电源地网络五路共用,不要加后缀。
VOn_P 端口(2026-09-03 画 P5 时补的)
VOn_P(Rs01 之后 → J.1 / Q*02 漏极 / INA226 的 VIN− 与 VBUS)原来是页内一段
没有名字的网络。P5-HARNESS 的手机侧电容组要挂在这个节点上,跨页就必须有名字,
于是从 J2 那根横线(y=695)上引一段 50 长的支线,末端放 VOn_P 端口
((960,745),dir='OUT',标签朝右)。五页同构,p2gen.py 的 VOP_STUB 统一生成。
⚠️
VO2_P~VO5_P在全工程里只有 1 个实例,因为 P5 上的电容组只画了 CH1 一套 作代表。这不是漏接,.claude/xpage.py的NAMING_ONLY集合已经把它们列为例外。 哪天把 CH2~CH5 的电容组也画上去,就把它们从那个集合里删掉。
16.5 五路复制(2026-09-03 做完)
P2B-CH2 ~ P2E-CH5 四页用 dmt_Schematic.copySchematicPage 从 P2 复制出来,
然后由 .claude/p2gen.py + .claude/p2push.py 按通道号改写。五页各自几何验证六项全过,
跨页对账 0 个"只有一个实例"的网络、0 个待补对端(原来有 33 个)。
图页顺序:P1-INPUT / P2-CHANNEL / P2B-CH2 / P2C-CH3 / P2D-CH4 / P2E-CH5 / P3-CONTROL / P3B-EXPAND / P4-USB / P5-HARNESS,共 10 页。
复制时踩到的两件事,五页一起修了:
K1_VUP的端口其实没连上。 它的引脚坐标和R122.1完全重合, 靠一段零长度导线"连着"——几何验证在原来的 P2 上不报,是因为那段零长度线 恰好落在引脚上。真按这个网表打样,那一路音量+ 很可能是断的。 三个按键端口现在统一改走向上 40 的短支线,末端才放端口。- 两处标签压字:
VDAC1和K1_PWR的标签面对面撞在一起(渲染成VDACK1_PWR); J7 的地旗文字压在Q105的位号上。前者靠把 VDAC1 也挪到支线末端解决, 后者把地旗再往下引 40。
⚠️ 端口的
dir(IN/OUT/BI)读不回来——API 里没有对应的getState_, 而 dir 决定标签画在引脚左边还是右边。所以p2gen.py里的PORTS是显式声明的, 不是从页面回读的。改端口位置时必须连 dir 一起想(见easyeda-sch-geometry§8b)。
17. P3 控制部分原理图(2026-09-03 画完)
原计划一页,实际拆成两页:ESP32 的 WROOM-1 符号右侧一列就有 37 个引脚, 再加 2×595 + PCA9555 + 2×DAC 的 25 个跨页端口,标签在一张 A4 上必然互相压字。
| 页 | 内容 | 元件 |
|---|---|---|
| P3-CONTROL(第 3 页) | ESP32-S3 主控 + USB-C 调试口 + I²C/开漏上拉 + NTC 采样 | 19 |
| P3B-EXPAND(第 4 页) | 74HC595 ×2 + PCA9555 + DAC63204 ×2 | 19 |
两页各自跑完 verify_sch.py 六项检查(0 悬空、0 单引脚网络、0 无名端口、0 同网多名),
并做了一次跨页网络对账(.claude/xpage.py):全工程 0 个"只有一个实例"的网络,
33 个待 CH2~CH5 与 P4-USB 补对端。
17.1 P3-CONTROL
- 引脚分配见 §8.1;调试口方案与"有意不接的引脚"也在那一节。
- ESP32 的 3V3 来自 P1 的 U19,不依赖任何一路输出(§8.3 的硬约束)。
BUCK_PG/INA_ALERT/IOEXP_INT#三个开漏信号的上拉电阻放在这一页 (P2 上只有 eFuse 自己的 FLT#/PGOOD 上拉,Buck 的 PWRGD 和 INA226 的 ALERT 都没有)。- NTC:
+3V3 → 10k → 节点 → NTC 10k → GND,节点并 100nF 后进 ADC1。
17.2 P3B-EXPAND
74HC595 级联:U21 在前(DS 接 ESP32 的 KEY_SER),U21.Q7S → U22.DS。
先移入的位落到 U22.Q7。输出分配:
| Q0 | Q1 | Q2 | Q3 | Q4 | Q5 | Q6 | Q7 | |
|---|---|---|---|---|---|---|---|---|
| U21 | K1_PWR | K1_VUP | K1_VDN | K2_PWR | K2_VUP | K2_VDN | K3_PWR | K3_VUP |
| U22 | K3_VDN | K4_PWR | K4_VUP | K4_VDN | K5_PWR | K5_VUP | K5_VDN | 空 |
MR# 接 +3V3,OE# 走 KEY_OE# 并在本页用 100 kΩ 上拉到 +3V3——
ESP32 复位期间 GPIO 高阻,595 输出随之高阻,配合 P2 上每个栅极的 100 kΩ 下拉,
15 个按键都不会误按(§8.1 复位安全三条里的第 2、3 条)。
PCA9555(0x20):
| 端口 | 用途 |
|---|---|
| IO0_0 ~ IO0_4 | EFUSE_FLT1 ~ 5 |
| IO0_5 / IO0_6 | BUCK_PG / INA_ALERT(原打算直连 ESP32,挪到扩展器省 2 根 GPIO) |
| IO0_7、IO1_5 ~ IO1_7 | 备用,直接接地 |
| IO1_0 ~ IO1_4 | EFUSE_PG1 ~ 5 |
⚠️ 备用脚直接接地(不串电阻)依赖"PCA9555 上电默认全部为输入"这一点。 固件严禁把 Port0[7] / Port1[7:5] 配成输出,否则输出高电平会直接对地短路。 这条已写在图纸上。
DAC63204 ×2:地址见 §8.2。三处 datasheet 强制要求,图上看不出来、接错也不报错:
- FBx 必须接回 OUTx —— 电压输出模式下这是输出运放的闭环反馈路径 (SLASEX3A 表 5-1:"In voltage-output mode, connect to OUTx for closed-loop amplifier output")。 不接的话输出是开环的。
- CAP 接 2.2 µF 到 AGND —— 内部 LDO 的旁路,允许 0.5 ~ 15 µF,datasheet 建议 ≈1.5 µF。 100nF 太小。
- VREF 不用外部基准时,要 100 nF 到地 + 上拉电阻到 VDD。
通道分配(2026-09-06 按 PCB 几何重排,取代 09-03 那一版,§26.18):
| 路 | 片 | 通道 |
|---|---|---|
VDAC1 |
U6(0x4A) | OUT2 |
VDAC2 |
U6 | OUT0 |
VDAC3 |
U7(0x4B) | OUT0 |
VDAC4 |
U6 | OUT1 |
VDAC5 |
U7 | OUT1 |
U6.OUT3、U7.OUT2/OUT3 未用(FB 也不接,datasheet 说未用通道保持 FB 悬空)。
⚠️ 「前三路在 U6、通道号 = rail−1」是旧版,五路里有四路对不上。 四个通道电气上完全对等,所以接错了板子照样正常工作,只是调 CH1 的命令去调了 CH2, 功能测试完全测不出来。固件里查表不要算:
dac63204_rail_addr()/dac63204_rail_ch()(A4 已落地,test_rail_map_is_not_the_naive_formula专门拦这一手)。⚠️ 未用通道不许上电:FBx 悬空时电压输出模式是开环运放。
COMMON-CONFIG里 U6 =0x1E49(OUT3 保持 Hi-Z)、U7 =0x1FC9(OUT2/OUT3 保持 Hi-Z)。
内部基准是 1.212 V(1.1979/1.212/1.224),不是 1.25 V。 增益 2× → 满量程 2.424 V,不是 2.5 V。§4 的公式按 0~2.5V 推的, 实际 Vd 上限 2.424V,所以输出下限是 3.524 V 而不是 3.508 V(更安全,见 §4.4)。
17.3 这一页还欠什么
输入侧的 INA226(U13)+ 分流电阻 Rs6 还没画✅ 2026-09-03 已补到 P1 右侧空白区,见 §19。✅ 已画(R701~R705,§18.2)。VBUS_EN1~5的 100 kΩ 下拉电阻放在 P4-USB
18. P4-USB 原理图(2026-09-03 画完)
EasyEDA 工程第 5 页。五路完全相同,一路一列,信号自上而下:
J12~J16(USB-A 上游)→ U24~U28(TPS22918)→ J17~J21(4P 出线座)。
几何验证六项全过:0 悬空引脚、0 单引脚网络、0 无名旗端口、0 同网多名,
而且全页 0 处导线交叉——D+ / D− / GND 三条从上游座直下到出线座,
VBUS 单独绕到右边过开关再回来,谁也不跨谁。
18.1 每一路的连接
| 信号 | 走法 |
|---|---|
VBUS |
J1x.VCC → U2x.VIN → VOUT → J1y.1。这是全页唯一被切断的信号 |
D− / D+ |
J1x.2/3 → J1y.2/3,板上直通,中间不串任何东西(§15.3) |
GND |
J1x.4 → J1y.4;USB-A 的两个屏蔽脚、4P 座的两个固定脚也都接地 |
VBUS_ENn |
端口 → U2x.ON,本页带 100 kΩ 下拉 R70n |
出线座引脚顺序 1=VBUS / 2=D− / 3=D+ / 4=GND,与 USB-A 座的引脚顺序一致, 所以三条直通线是三条笔直的竖线,做线束时也不容易接错。
18.2 TPS22918 的四个外围决定(SLVSD76C Rev C 复核)
⚠️ 引脚号先说清楚:datasheet 里引脚图和 Pin Functions 表看起来是反的——
图上标注被排版拆开后读作 1 VOUT / 2 QOD / …。按文字坐标还原后两处其实一致,
以表为准:1 VIN / 2 GND / 3 ON / 4 CT / 5 QOD / 6 VOUT,立创的符号也是这个。
这一条接反了图上完全看不出来。
-
ON 脚必须有下拉(R701~R705,100 kΩ) datasheet 原文 "This pin cannot be left floating and must be driven either high or low"。 ESP32 复位期间 GPIO 高阻 → 没有下拉就是"VBUS 状态不确定", 这正是 §8.1「复位安全三条」里的第 1 条。 阈值
VIH ≥ 1 V / VIL ≤ 0.5 V,3.3 V GPIO 直驱,中间不需要电平转换。 -
CT 接 100 pF C0G(C721~C725),不悬空 摆率公式
SR = 0.55 × CT(pF) + 30(µs/V)→ 100 pF 时 85 µs/V, 5 V 下 tR ≈ 425 µs(10%90%)。 涌流5.5 V 时至少 20 V,选的是 50 V C0G, 没有电压系数问题。I = CL × dV/dt,手机尾插小板那边按 10 µF 估:10µF × 4V / 425µs ≈ 94 mA。 CT 悬空的话 tR 只有 135 µs,同样负载涌流 ≈ 296 mA,接近 USB 口的软启动上限。 电容电压等级:datasheet 表 3 要求 VIN 4 -
QOD 直接短接 VOUT 用内部
RPD ≈ 24 Ω(5 V),关断后 VBUS 约 200 µs 归零(CL=10 µF)。 这正是反灌保护要的:一发现电流为负就拉低VBUS_EN,VBUS 必须真的塌下去, 悬空的话电荷会挂在那儿。 约束:直接短接时总容性负载不得超过 200 µF,超了要串 REXT 限流,否则 RPD 过热。 本设计下游只有手机尾插小板,远低于这个数。 -
CIN 2.2 µF 必须大于 COUT 100 nF datasheet 原文:"a CIN greater than CL is highly recommended"—— 反过来的话掉电时 VOUT 会高于 VIN,电流从体二极管倒灌。 这里比值 22:1,比推荐的 10:1 还宽。
18.3 与手册其它部分的关系
VBUS_EN1~5五个端口与 P3-CONTROL 对上(跨页对账已确认,各 2 个实例)。- 反灌检测读的是该路输出的 INA226(U8~U12),不是 USB 侧——USB 这边没有电流计。 判据与固件逻辑见 §15.2 对策 2。
- 上游只接电脑或 USB Hub,VBUS 恒 5 V。真接了快充头把 VBUS 抬到 9 V, TPS22918 的绝对最大是 6 V,会当场炸。这条在 §15.1 已经定死,这里再记一次。 用的是 USB-A 母座,所以板到 Hub 之间是一根 A 公 - A 公线; 这不是标准 USB 用法,好处是物理上插不了充电头。
- CT / QOD / CIN>COUT 这三条接错了图上都看不出来,也不报错, 和 §17.2 里 DAC63204 的三条是同一类坑。
19. 输入侧检流(P1 的【D】区,2026-09-03 补画)
U13 INA226 + Rs6 5mΩ + C11 100nF,量 12V 母线的电流与电压,供 §8.3 的「整板功率预算」。
19.1 串在哪
J1 → F1 → Q1(反接保护) → ┬─ D1 TVS
├─ C2/C3 470µF + C4~C6 MLCC ← 体电容在**上游**
└─ Rs6 5mΩ ──→ +12V(五路 + 辅助 Buck + 泄放)
- 体电容在 Rs6 上游,所以 Rs6 量到的是负载电流,不是适配器电流。 480 kHz 的开关纹波由各路自己的输入 MLCC 就近提供(阻抗 ~0.03Ω, 远低于回到体电容那条路的走线电感),所以真正流过 Rs6 的主要是直流 + 负载阶跃。
- 量程:满板约 8 A → 40 mV,INA226 满量程 ±81.92 mV,余量一倍; 分辨率 2.5 µV / 5 mΩ = 0.5 mA。2512 上耗散 0.32 W(3 W 额定)。
- PCB 上 Rs6 要放在体电容与五路分叉点之间,Kelvin 四线焊盘(和 Rs1~Rs5 一样)。
19.2 接法
| 引脚 | 接到 |
|---|---|
| VIN+ | Rs6 上游焊盘(Q1 漏极侧) |
| VIN− / VBUS | Rs6 下游焊盘 = +12V 网络(VBUS 因此量的是母线电压) |
| VS+ | +3V3,旁边 C11 100nF |
| A1 / A0 | GND / SCL → 地址 0x43(§8.2 的地址表,不是顺排) |
| Alert / SDA / SCL | INA_ALERT / SDA / SCL 三个跨页端口 |
INA226 的共模范围 0~36 V,12 V 母线在范围内;A0 接 SCL 是 datasheet 允许的 16 种地址组合之一。
19.3 顺手修的一个真错误
P1 上 BLD_REF / BLD_A 两个端口的引脚坐标和 U29(TL431) 的 REF / 阴极完全重合,
靠零长度导线"连着"——和 P2 上 K1_VUP 是同一个毛病(§16.5)。
两个端口已往左挪 40 并补了真导线。
这类错误几何验证抓不到(零长度段会让"引脚落在导线上"这一条通过), 只有重画那一页时才会暴露。规律已写进
easyeda-sch-geometry§8a。
19.4 U13 的 SCL 根本没接上(2026-09-03 布线时发现并修好)
§19.3 修的是零长度导线那一类。同一页上还藏着近亲的第二类,更隐蔽:
SCL 端口的引脚坐标 (920, 340) 压在导线 [920,320 → 920,570] 的中段,
而不是端点。EasyEDA 只在导线端点处认连接,所以
- 原理图上 A0 与 SCL 引脚连成了一个节点,但这个节点没有名字;
- 导进 PCB 后它叫
$1N257,只有 U13.2 与 U13.5 两个焊盘; - U13 的 SCL 不在 I²C 总线上 —— 输入侧检流整片芯片是死的, §19.2 说的地址 0x43 也无从谈起。
而同一页的 SDA 端口引脚 (910, 380) 恰好是导线 [910,380 → 910,570] 的端点,
所以 SDA 是好的。两个端口在图上长得一模一样。
DRC / ERC / verify_sch --nets / 跨页对账四道检查全过——
verify_sch 的判据是"引脚落在某条导线段上",中段搭接满足这一条。
已改成:A0 的跳线在 (920, 340) 收尾,再从 (920, 340) 单独引一段到 U13.5,
端口引脚成为两段导线的共同端点。PCB 侧走 设计 → 从原理图导入变更 应用,
对话框逐条列出 U13:2 / U13:5 → SCL 两条,别无其它变更。
新增检查工具
.claude/port_audit.py:全工程 572 个旗/端口逐个判 "引脚是不是某条导线段的端点"。全工程当时只有这一个不合格。 规律已写进easyeda-sch-geometry§8a-2。
20. P5-HARNESS 线束页(2026-09-03 画完)
原理图第 10 页,也是最后一页。这是一页文档页——除了【B】区的手机侧电容组, 整页都是非电气图元(矩形 / 折线 / 文字),不参与网表。 它把散在 §6.3 / §13 / §15.4 里的「板子外面怎么接」收成一张图, 装机的人对着这一页就能把线束做出来,不用翻手册。
20.1 四个分区
| 区 | 内容 |
|---|---|
| 【A】 | 三条线束的连接图:板端连接器(左框)→ 缆线(中间,按信号着色)→ 手机端接点(右框) |
| 【B】 | 手机侧电容组的真电路(C801~C806 挂在 VO1_P 与 GND 之间) |
| 【C】 | 五路对照表:CH ↔ 板端 J ↔ 输出网络 ↔ INA226 地址 ↔ 电容组位号 |
| 【D】 | 动手前必读的五条红字警告(焊 P+/P−、J600 固定脚、电容位置、C801 选型、地不共用) |
20.2 【A】三条线束(每台手机一套)
| 线束 | 板端 | 缆线 | 手机端 |
|---|---|---|---|
| 电源 | J2 Micro-Fit 3.0 2P:1 VO1_P / 2 GND |
18 AWG 双绞,≤ 20 cm,红=正 黑=负 | 电池排线 P+/P− 焊点 → J600 pin 7/8 + G3/G4(VBATT)与 pin 1/2 + G1/G2(GND) |
| 侧键 | J7 1.25 mm 4P:K1_PWR / K1_VUP / K1_VDN / GND |
AWG 26~28 细线,远离电源线 | J603 电源键 / J601 音量+ / J602 音量− / J604 公共地 |
| USB | J17 1.25 mm 4P:VBUS1 / USB1_DM / USB1_DP / GND |
USB 线改端子,D± 保持双绞 | 原厂尾插小板 USB-C(CC / ESD / 口温 NTC 都在其上) |
电容组接在电源线束的手机端,也就是排线的 P+/P− 焊点处(§6.4:装在板上无效)。
20.3 【B】只画了 CH1 一套
CH2CH5 的电容组与 CH1 完全相同,没有画出来,位号见【C】表。
代价是 VO2_PVO5_P 在全工程里只有一个实例,已在 §16.4 说明并在
.claude/xpage.py 里列为 NAMING_ONLY 例外。
C801~C806 六颗都是 addIntoBom=false / addIntoPcb=false 放的,
读回 getState_AddIntoBom() / getState_AddIntoPcb() 确认过是 false。
它们不会出现在贴片 BOM 里,也不会被拉进 PCB。
20.4 画法上的两条新经验
- 文档页不要用
sch_PrimitiveWire画表格线和示意线 —— 导线会被判成网络,verify_sch.py会报一堆单引脚网络。用sch_PrimitiveRectangle/sch_PrimitivePolygon/sch_PrimitiveText(带颜色和粗体),三者都没有电气含义。 矩形的topLeftY在 Y 向上的坐标系里是上边,高度往 y 减小的方向长。 - 文字宽度要在本地算出来查越界:
宽度 ≈ 字号 × (CJK 数 + 0.5 × ASCII 数), A4 可用区x 20~1145 / y 10~812,标题栏占x>455 且 y<192。.claude/p5_harness.py的selfcheck()已经把这两条做成自动检查。
细节都写进了 easyeda-sch-geometry skill 的 §12。
21. USB2517I 硬件配置(2026-09-03 按 datasheet 逐条复核)
21.1 用哪一份 datasheet ⚠️
2517.pdf —— SMSC USB2517, Revision 2.8 (09-17-12), 50 页。
⚠️ 从 Microchip 站上还能下到
00001692C.pdf,那是 USB251xB 系列 (USB2517B,带电池充电支持)的手册,另一个世代、引脚与寄存器都不同。 我们的料是USB2517I-JZX(C478081),必须看 2517.pdf。
21.2 引脚号:图和表打架,表是对的 ⚠️
QFN-64 引脚图(Figure 2.1)和引脚表(Table 5.1)在几个脚上互相矛盾,
典型的是 RBIAS:图上读出来是 64、表里写的是 63。
判别办法(和 §18 的 TPS22918 完全同一个套路):把引脚图的文字按坐标还原——
fitz 的 get_text("words") 拿到每个词的 xy,再按「同一行/同一列」把引脚号和标签配对,
而不是按 PDF 的文本流顺序读。还原结果与 Table 5.1 逐脚一致:
VDDA33 = 5, 10, 52, 57 (图的文本流顺序会读成 1, 12 —— 错)
RBIAS = 63 VDD33PLL = 64 VDD18PLL = 62
VDD33 = 46 VDD33CR = 24 VDD18 = 25
结论:图的文本流顺序不可信,Table 5.1 可信。 本设计用的引脚号:
| 功能 | 脚号 |
|---|---|
上游 USBUP_DP / USBUP_DM |
59 / 58 |
下行 USBDN[1..7]_DP |
2, 4, 7, 9, 12, 54, 56 |
下行 USBDN[1..7]_DM |
1, 3, 6, 8, 11, 53, 55 |
VBUS_DET |
44 |
RESET_N |
43 |
RBIAS |
63 |
XTAL1/CLKIN / XTAL2 |
61 / 60 |
CFG_SEL0(=SCL) / CFG_SEL1(=HS_IND) / CFG_SEL2 |
41 / 42 / 13 |
SUSP_IND/LOCAL_PWR/NON_REM0 |
45 |
SDA/SMBDATA/NON_REM1 |
40 |
LED_B3_N/GANG_EN |
34 |
PRTPWR[1..7] |
29, 26, 23, 20, 30, 39, 36 |
OCS[1..7]_N |
28, 27, 22, 21, 35, 38, 37 |
TEST |
19 |
| 电源 | VDD33=46、VDD33CR=24、VDD33PLL=64、VDDA33=5/10/52/57、VDD18=25、VDD18PLL=62 |
| 地 | 散热焊盘(Thermal Slug)必须接 VSS |
21.3 配置方式:CFG_SEL[2:0] = 000
Table 5.2 的三个 CFG_SEL 脚在 RESET_N 上升沿被锁存,决定配置来源。
本设计取 000 = Internal Default Configuration + Strap Options are Enabled:
不要 EEPROM、不要 SMBus,全靠内部默认值加几个跳线电阻。
为什么这个组合是对的 —— 关键在寄存器 06h:
Table 7.1:06h Config Data Byte 1 内部默认 ROM = 9Bh = 1001_1011b
bit7 = SELF_BUS_PWR = 1 = Self-Powered operation ✅
0Ch Max Power (Self) = 01h → 2 mA
0Eh Hub Controller Max Current = 01h → 2 mA
即内部默认就是自供电,正是 §15.1 边界 2 要的。不需要 EEPROM 去改。
实现:CFG_SEL0(41) / CFG_SEL1(42) / CFG_SEL2(13) 各 10 kΩ 下拉到地。
⚠️ 别选
100/101(Dynamic Power Switching):那两档虽然让LOCAL_PWR脚 决定自/总线供电,但同时会把 Strap Options 关掉,端口禁用跳线就失效了。
21.4 外围元件(逐条对 datasheet)
| 位号 | 值 | 接到哪 | datasheet 依据 |
|---|---|---|---|
| R708 | 12.0 kΩ ±1%(C25752) | RBIAS(63) → GND |
Table 5.1:「A 12.0kΩ (+/-1%) resistor…to set the transceiver's internal bias」。这个值不能动 |
| Y1 | 24 MHz ±10ppm, CL=9pF(C2762192) | XTAL1(61) / XTAL2(60) |
§9.1:「Parallel Resonant, Fundamental Mode, 24 MHz ±350ppm」。选 ±10ppm 余量很大 |
| C740 / C741 | 12 pF C0G(C1547)×2 | 晶振两端 → GND | 按 Figure 9.2:CL = (C1+CS1)(C2+CS2)/(C1+CS1+C2+CS2),取杂散 ~3pF、CL=9pF → C1=C2≈12pF |
| C742 / C743 | 1 µF 0402(C52923)×2 | VDD18(25)、VDD18PLL(62) → GND |
Table 5.1 两处都写「must have a 1.0µF (or greater) ±20% (ESR <0.1Ω) capacitor to VSS」 |
| R709 / R710 | 100 kΩ / 100 kΩ | 上游 VBUS → 分压 → VBUS_DET(44) |
§7.1.2 + Table 5.1:「When designing a detachable hub, this pin must be connected to the VBUS power pin of the USB port that is upstream」。我们的上游是可插拔的 USB-C,属于 detachable,所以要真接、不能拉到 3.3V。该脚是 3.3V 逻辑,5V 必须分压 |
| R711~R713 | 10 kΩ ×3 | CFG_SEL[2:0] → GND |
§21.3 |
| R714 / R715 | 10 kΩ ×2 | USBDN6_DP(54)、USBDN7_DP(56) → +3V3_HUB |
Table 5.1:「To disable, pull up with 10K resistor to 3.3V」。见 §21.5 |
| R716 | 10 kΩ | RESET_N(43) → +3V3_HUB |
上拉;同时由 74HC595 的备用输出驱动,见 §21.6 |
| 去耦 | 100 nF ×7 | VDD33(46)、VDD33CR(24)、VDD33PLL(64)、VDDA33(5/10/52/57) |
每个电源脚一颗,就近 |
| 储能 | 10 µF ×1 | +3V3_HUB |
VBUS_DET 为什么必须真接上游 VBUS:USB 2.0 §7.2.1 规定, 上游 VBUS 没上电时下行口不许给 D± 上拉。Hub 靠这个脚判断主机在不在; 上游断电后 10 秒内撤掉 D+ 上拉。接成常高(拉到 3.3V)只在「主机永久连接」时才合法, 我们是插拔式,必须分压引真 VBUS。
21.5 端口分配与两个用不上的口
| Hub 端口 | 去向 |
|---|---|
| 1 ~ 5 | CH1 ~ CH5 → J17~J21 → 手机原厂尾插小板 |
| 6, 7 | 禁用:USBDN6_DP(54) / USBDN7_DP(56) 各 10 kΩ 上拉到 +3V3_HUB |
禁用而不是悬空,是为了 lsusb 上不出现两个永远空着的口。
跳线只在 CFG_SEL=000(Strap Options Enabled)下有效 —— 这是选 000 的另一个理由。
想把某个口放出来用(比如以后接个 USB 转串口),拆掉对应那颗 10 kΩ 即可, 焊盘留着。但目前板上没有把 6/7 口引到任何连接器,所以「备用」是指芯片有余量, 不是指有现成的口可插。
21.6 故意不接的脚
| 脚 | 处理 | 理由 |
|---|---|---|
PRTPWR[1..7] |
不接 | 端口通断权在 ESP32 手里(§15.2 对策 2),不能交给 Hub |
OCS[1..7]_N |
不接 | Table 5.3:IPU,内部上拉到 3.3V,悬空 = 无过流 ✅ |
LED_A* / LED_B* |
不接 | 不做指示灯。⚠️ 但 LED_B3_N(34) 兼 GANG_EN、LED_B[2:1](48/50) 兼 BOOST[1:0]、LED_A* 兼 PRT_SWP*,这些脚都是 Strap,悬空取默认 '0':单独通断/单独过流检测、PHY 不加强、端口极性正常 —— 都符合本设计 |
SDA/NON_REM1(40)、SUSP_IND/LOCAL_PWR/NON_REM0(45) |
各 10 kΩ 下拉 | 取 NON_REM[1:0] = '00' = 所有端口可移除。注意 45 脚同时是 LOCAL_PWR,但在 CFG_SEL=000 下自/总线供电由寄存器 06h 决定(§21.3),不看这个脚 |
TEST(19) |
下拉到 GND | IPD,仅工厂测试用 |
21.7 复位
RESET_N(43):datasheet 说拉到 VDD33 即可用内部 POR、不需要外部复位电路。
本设计在此基础上再引一根到 74HC595 的备用输出(U21/U22 共 16 个输出,
15 路按键只用了 15 个,正好剩 1 个),让 ESP32 能远程复位 Hub——
Hub 偶尔枚举不出来时不用跑到机架前,符合本项目「远程救砖」的一贯思路。
R716 10 kΩ 上拉保证 ESP32 复位期间(KEY_OE# 被 R609 拉高 → 595 输出高阻)
RESET_N 仍是高电平,Hub 不会跟着被复位。
⚠️ PCA9555 的 4 个备用脚不能拿来做这件事——它们直接接了地(见 §9.1 的注), 固件严禁把它们配成输出。
文档随设计推进更新。修改任何一节,请同步更新 §11 的验证项。
22. 两板架构:电源底板 + 主板载板(2026-09-04 用户拍板)
22.1 为什么改,改了什么
原方案是一块板 + 三条线束 × 5 台(§15.4)。改成两块板对插:
┌──────────────────────────────────────────────────────────┐
│ 上板(载板) 5 块小米8 主板(反面朝下)+ USB Hub + VBUS 开关 │
│ 顶针顶侧键 / 1.25mm 座接 EDL / P+P− 焊盘 + 电容组 │
└───────────────────────────┬──────────────────────────────┘
2.54 排针(只走电源 + 低速控制,**没有 USB**)
┌───────────────────────────┴──────────────────────────────┐
│ 下板(电源板)12V 进 → 五路 4A → eFuse → 分流 → 排针座 │
│ ESP32-S3 + DAC + 六片 INA226 + 两片 595 + PCA9555 │
└──────────────────────────────────────────────────────────┘
分工
| 下板(纯电源 + 控制大脑) | 上板(载板) |
|---|---|
| J1 12V 进线 / F1 / Q1 反接 / TVS / 泄放 | 5 块主板定位孔 + 立柱 |
| 五路 Buck + DAC + eFuse + 分流电阻 + INA226 | U32 USB2517I + Y1 + 全部 strap + U31 3V3 LDO |
| U13 输入侧检流、U19 辅助 3V3、U30 12V→5V | U24~U28 TPS22918 VBUS 负载开关 |
| ESP32-S3 + 74HC595 ×2 + PCA9555 | J23 上游 USB-C |
| 侧键驱动管 Q1x3~Q1x5 | 5 组侧键顶针、5 组 EDL(1.25mm 2P 座 + 模拟开关) |
| J22 调试 USB-C | 5 组 P+/P− 焊盘 + §6.3 电容组 |
两处按工程判断定的(用户没明说):
- 侧键驱动管留在下板。 移上去不省针数(每台仍是 3 根控制线),却要重画五路的按键部分。 留下等于只把 J7~J11 换成排针针位,原理图改动最小。
- EDL 开关放上板。
FORCED_USB_BOOT是 1.8 V 逻辑脚、旁边挂着 ESD 管; 把 TP1204/TP1205 拉到下板再拉回来,等于在这个脚上挂一段长残桩。 开关就近放在 1.25mm 座旁边,穿排针的只剩 1 根控制线。
跟着 Hub 一起上去的四样,少一样都白改:U32 本体、U31(§9.5 要求就近供电)、 U24~U28(VBUS 开关隔着连接器等于把 VBUS 绕远)、J23 上游 USB-C (留在下板的话上游那对 D± 还是要穿排针)。改完之后一根高速差分都不穿连接器。
22.2 排针接口定义(2026-09-04 定稿,原理图 P5-BTB 已画完)
用两条 2×20(各 40 针,合计 80 针),分列板子两端。 不是 §22.2 初稿说的「一条 2×32 或两条 2×16」—— 64 针按通道切怎么都不整齐(5 路 × 11 针 = 55,任何 32/32 的切法都会把某一路劈开), 用两条 2×20 反而干净:J24 = CH1 + CH2 + 全局,J25 = CH3 + CH4 + CH5, 多出来的 16 针全部接地,正好给 4A 回流加粗。
下板装公头(C55020601 AZ-PZ2.54-V11-2*20P,塑高 2.5 / 配合针长 6,直插镀金),
载板装母座(C5307344 PC104-2×20,塑高 10.5,直插)。对插 = 13.0 mm。
选型全过程见 §22.3f(2026-09-05 定稿,此前那两个占位料号已作废)。
编号约定(2026-09-05 两颗符号都在 EDA 里实测过,逐脚读回坐标): 第 r 行 = 引脚 2r−1(左列)/ 2r(右列),第 1 行在符号中心上方 95 个单位。 两列 x 偏移 ±30,行距 10。
✅ 公母同一套编号(旧的「两套编号」陷阱已随换件消失)
换件前是两套:下板公头 DIP 式(第 r 行 = r / 41−r)、载板母座 IDC 奇偶式
(第 r 行 = 2r−1 / 2r),查线只能按行号对。换成 C55020601 + C5307344 之后
两颗完全一致,都是 IDC 奇偶式,VO1_P 在两块板上都是 1 / 3 / 5 脚。
原理图侧本来就不会错 —— c1_conn.py 直接 import p5_btb.py 里那两张按行组织的表
来生成载板页,两边共用同一个事实来源,没有任何手工转写。
⚠️ 但 PCB 上那条风险还在:符号编号一致 ≠ 第 r 行真的对上第 r 行。
公头在下板顶层、母座在载板底层,底层元件在顶视图里是镜像的,
两个封装的焊盘编号 + 摆放镜像共同决定对位关系。
以 pcb2-header-pads.json 导出的 80 个焊盘坐标为准,布板时必须实打实核对一次。
⚠️ 2026-09-05 重排:按载板几何分配,不再按通道号切
原来是 J24 = CH1+CH2+全局 / J25 = CH3+CH4+CH5,那是 09-04 定的、当时载板 PCB 还不存在。
载板画出来之后发现 09-04 那版有一条硬冲突:排母南排前 16 位全是 GND 焊盘,
Ø1.70 / 间距 2.54 ⇒ 相邻边距 0.84 mm,扣掉两边 0.2 净距,Inner1 上每个缝只剩 0.44 mm 铜网,
而 4 A 按 IPC-2221 内层 0.5 oz 要 6.97 mm —— 4 A 的电源面穿不过排母的地针行。
偏偏 09-04 那版把 VO4_P / VO5_P 放在 J32 的北排,它们的站却在排母南边。
新规矩:北排喂北边的站,南排喂南边的站,一路都不许跨行。 依据是载板几何:
J31 焊盘 x 37.87~ 86.13 正对 site1(x 5~72,北) 和 site4(x 41~108,南)
J32 焊盘 x 133.87~182.13 正对 site3(x 148~215,北) 和 site5(x 112~179,南)
site2 (x 76.5~143.5,北) 夹在两颗中间 → VO2_P 取 J31 北排最右三针(x 81~86),
正好顶着 site2 最左边的负载 C811(x 86.0)
重排后五路 VOn_P 全部同侧,Inner1 上最远曼哈顿距离从 ~120 mm(VO4 原来要绕排母端头、
钻手机 2 底下再折回来)降到 ≤42 mm。逐项见 §25.10。
两处随之改的针数(网络表一个都没变,只是落点变了):
| 09-04 | 09-05 | 为什么 | |
|---|---|---|---|
+5V |
3 针(全在 J31 北排) | 10 针,两颗排母 × 南北四处 | 不是为了电流(2.8 A/10 = 0.28 A/针),是为了就近落地,免得在 Inner1 上拉一条横贯全板的脊 |
GND |
33 针 | 26 针 | 让位给 +5V;20 A 回流 = 0.77 A/针,仍宽裕 |
| 信号 | 47 | 54 | = 15 VO + 10 +5V + 25 站内 + 4 全局 |
唯一事实来源是 .claude/p5_btb.py 里的 J24 / J25 两张表,
c1_conn.py 直接 import 它生成载板页,下面两张表是从同一份数据生成的。
J24(对插载板 J31)—— site1(北) + site4(南) + site2 电源 + 全局
| 行 | 北排(奇) 脚 / x mm | 网络 | 南排(偶) 脚 / x mm | 网络 |
|---|---|---|---|---|
| 1 | 1 / 37.87 | VO1_P |
2 / 37.87 | GND |
| 2 | 3 / 40.41 | VO1_P |
4 / 40.41 | GND |
| 3 | 5 / 42.95 | VO1_P |
6 / 42.95 | GND |
| 4 | 7 / 45.49 | +5V |
8 / 45.49 | GND |
| 5 | 9 / 48.03 | +5V |
10 / 48.03 | GND |
| 6 | 11 / 50.57 | POGO1_PWR |
12 / 50.57 | POGO4_PWR |
| 7 | 13 / 53.11 | POGO1_VUP |
14 / 53.11 | POGO4_VUP |
| 8 | 15 / 55.65 | POGO1_VDN |
16 / 55.65 | POGO4_VDN |
| 9 | 17 / 58.19 | EDL_EN1 |
18 / 58.19 | EDL_EN4 |
| 10 | 19 / 60.73 | VBUS_EN1 |
20 / 60.73 | VBUS_EN4 |
| 11 | 21 / 63.27 | SDA |
22 / 63.27 | +5V |
| 12 | 23 / 65.81 | SCL |
24 / 65.81 | +5V |
| 13 | 25 / 68.35 | GND |
26 / 68.35 | UP_VBUS_DET |
| 14 | 27 / 70.89 | GND |
28 / 70.89 | GND |
| 15 | 29 / 73.43 | GND |
30 / 73.43 | VO4_P |
| 16 | 31 / 75.97 | GND |
32 / 75.97 | VO4_P |
| 17 | 33 / 78.51 | GND |
34 / 78.51 | VO4_P |
| 18 | 35 / 81.05 | VO2_P |
36 / 81.05 | GND |
| 19 | 37 / 83.59 | VO2_P |
38 / 83.59 | GND |
| 20 | 39 / 86.13 | VO2_P |
40 / 86.13 | GND |
J25(对插载板 J32)—— site3(北) + site5(南) + site2 信号
| 行 | 北排(奇) 脚 / x mm | 网络 | 南排(偶) 脚 / x mm | 网络 |
|---|---|---|---|---|
| 1 | 1 / 133.87 | +5V |
2 / 133.87 | +5V |
| 2 | 3 / 136.41 | +5V |
4 / 136.41 | +5V |
| 3 | 5 / 138.95 | POGO2_PWR |
6 / 138.95 | VBUS_EN5 |
| 4 | 7 / 141.49 | POGO2_VUP |
8 / 141.49 | EDL_EN5 |
| 5 | 9 / 144.03 | POGO2_VDN |
10 / 144.03 | GND |
| 6 | 11 / 146.57 | EDL_EN2 |
12 / 146.57 | GND |
| 7 | 13 / 149.11 | VBUS_EN2 |
14 / 149.11 | GND |
| 8 | 15 / 151.65 | HUB_RST |
16 / 151.65 | GND |
| 9 | 17 / 154.19 | GND |
18 / 154.19 | VO5_P |
| 10 | 19 / 156.73 | GND |
20 / 156.73 | VO5_P |
| 11 | 21 / 159.27 | GND |
22 / 159.27 | VO5_P |
| 12 | 23 / 161.81 | POGO3_PWR |
24 / 161.81 | POGO5_PWR |
| 13 | 25 / 164.35 | POGO3_VUP |
26 / 164.35 | POGO5_VUP |
| 14 | 27 / 166.89 | POGO3_VDN |
28 / 166.89 | POGO5_VDN |
| 15 | 29 / 169.43 | VO3_P |
30 / 169.43 | GND |
| 16 | 31 / 171.97 | VO3_P |
32 / 171.97 | GND |
| 17 | 33 / 174.51 | VO3_P |
34 / 174.51 | GND |
| 18 | 35 / 177.05 | EDL_EN3 |
36 / 177.05 | GND |
| 19 | 37 / 179.59 | VBUS_EN3 |
38 / 179.59 | GND |
| 20 | 39 / 182.13 | +5V |
40 / 182.13 | +5V |
合计 54 个信号 + 26 个地。 五路 VOn_P 仍是 3 针并联(4 A / 3 = 1.33 A 每针,
母座额定 2.5 A 每针),正对面 3 针 GND 做本路回流(§15.4 各路独立回地不变)——
p5_btb.py 的 plan() 里有断言逐行核这一条。
为什么侧键网络叫 POGOn_* 而不是 KEYn_*
驱动管留在下板(§22.1),所以同一路按键有两个节点:
栅极侧(ESP32 / 74HC595 来的)已经叫 Kn_PWR,漏极侧(穿排针去顶针的)如果叫
KEYn_PWR,两个名字只差一个字母 —— 这种命名迟早会接错。
改叫 POGOn_PWR / POGOn_VUP / POGOn_VDN,同时也点明了载板那头是顶针。
侧键的公共地不占排针:J604 是三键公共地(§13.3),在载板上直接接本路的电源返回地即可。 下板原来 J7~J11 上那三个专门的地针(每键一个)随连接器一起删掉了。
风扇不占排针(2026-09-04 用户定:风扇装 3D 打印外壳上)。 风扇的 12V、PWM、TACH 全部从下板直接出线(J26~J30,见 §22.6)—— 下板本来就有 12V 母线和 ESP32,绕到载板再绕回来毫无意义。
电气复核:三针并联的接触电阻约 5 mΩ,4 A 时压降 20 mV,可接受。 回路电感从线束的约 300 nH 掉到 30~50 nH 量级 —— §6.1 / §6.2 的谐振频率与 阻尼比要按这个重算,结论方向是比原来更过阻尼,C801 用普通铝电解做阻尼依然成立。
22.3 小米8 主板机械数据(从我们自己的 PDF 反推)
⚠️ 纠正一条旧结论:小米8原理图/Xiaomi_Mi_8_Schematic.pdf 的第 1、2 页是正反面位号图
(含完整板框轮廓 + 全部位号),不是原理图。PROGRESS 里「PDF 不含任何机械尺寸、
必须实测」那条是错的,头号阻塞项其实一直不存在。
比例尺标定方法(可复现):原理图页上每个器件都标了封装(0201 / 0402 / …), 把「位号 → 封装」抽出来,再到位号图上量同名器件的矩形,反推 pt→mm:
| 封装 | 样本数 | 长边 pt/mm | 短边 pt/mm |
|---|---|---|---|
| 0201 | 464 | 16.80 | 17.20 |
| 0402 | 35 | 18.96 | 20.16 |
| 0603 | 9 | 18.45 | 20.25 |
取 17.0 pt/mm(0201 样本最多、长短边最一致;大封装偏大是因为画的是焊盘外框)。
主板尺寸:卡尺实测 44.66 × 67.09 mm(2026-09-04 用户实测,以此为准)。 反推比例尺 x 17.15 / y 16.93 pt/mm —— 与上表从 0201 推出的 17.0 只差 0.7%,图纸确认无误。
22.3a 七个定位孔(2026-09-04 从实测照片提取)
⚠️ 又一条旧结论被推翻:先前从位号图上找同心圆,判定「主板没有定位孔、只能靠压板」, 是错的。实物照片上有 7 个金属包边的定位孔,沿板子周边分布。 错因是我在矢量图元里找「同心圆组」,抓到的全是测试点和圆焊盘; 而位号图上的孔要么没画成圆、要么被元件挡住 —— 没有实物对照就不该下这种结论。
坐标从用户标注的照片提取(板体最大连通块定包围盒,按实测长宽标定), 照片方向、板左下角为原点,单位 mm:
| 孔 | X | Y | 位置描述 |
|---|---|---|---|
| H1 | 54.2 | 42.3 | 上边偏右 |
| H2 | 2.6 | 38.2 | 左边缘上 |
| H3 | 61.9 | 33.7 | 右边缘上(与 H4 成对) |
| H4 | 62.1 | 29.2 | 右边缘下 |
| H5 | 2.6 | 27.0 | 左边缘中 |
| H6 | 4.0 | 10.8 | 左下 |
| H7 | 42.6 | 3.7 | 下边偏右 |
精度:包围盒长宽比 1.533,实测 1.502,差 2%(拍摄轻微透视)→ 坐标误差约 ±0.5 mm。 载板上的孔按 Ø2.5 mm 沉孔或长圆槽做,足以吸收这个误差; 装配时以 H2/H5(左边缘那两个,间距 11.2 mm)做主基准,其余给余量。
22.3b 统一坐标系(后续所有机械工作以这张表为准)
顶视坐标系:从上往下看装配体,板 67.09 (X) × 44.66 (Y) mm,左下角为原点。 就是用户那张标红框照片的方向 —— 主板「朝上那面」朝着你。
三个变换关系(都已验证):
- 照片朝向 = 位号图 page1 视图逆时针转 90°(用户 2026-09-04 目视确认)。
换算:
X = 67.09 − y_图,Y = x_图。 - 位号图 page2(反面)= page1 上下翻转(轮廓匹配:边界差 0.0194,
左右镜像是 0.057,差一倍多)。合成后
x_view = 44.66 − x₂,y_view = y₂。 - 验证:按 ① 预测 J600 / J1401 / TP1204 / TP1205 应落在照片的 (392,609) / (735,637) / (688,596) / (650,594) 像素处 —— 照片上那三处正好是 一个中等 BTB 座、底边那条长 BTB 座、以及紧挨着它的两个测试点。三点独立吻合,映射成立。
| 特征 | X | Y | 在哪一面 | 精度 |
|---|---|---|---|---|
| H1 定位孔 | 54.2 | 42.3 | 通孔 | ±0.5 |
| H2 | 2.6 | 38.2 | 通孔 | ±0.5 |
| H3 | 61.9 | 33.7 | 通孔 | ±0.5 |
| H4 | 62.1 | 29.2 | 通孔 | ±0.5 |
| H5 | 2.6 | 27.0 | 通孔 | ±0.5 |
| H6 | 4.0 | 10.8 | 通孔 | ±0.5 |
| H7 | 42.6 | 3.7 | 通孔 | ±0.5 |
| TP1204 (EDL) | 45.41 | 4.99 | 朝上 | ±0.3,本体 0.73×0.74 |
| TP1205 (EDL) | 42.64 | 4.99 | 朝上 | ±0.3,本体 0.73×0.74 |
| J1401 尾插座 | 53.58 | 2.86 | 朝上 | ±0.3,本体 2.27×12.25 |
| J600 电池座 | 23.8 | 4.6 | 朝上 | ±2(位号文字位置,本体没匹配上) |
| J601 侧键 | 2.70 | 4.60 | 朝下(已折算顶视投影) | ±0.3,本体 2.23×1.21 |
| J602 | 5.41 | 6.52 | 朝下 | ±0.3,本体 2.22×1.20 |
| J603 | 3.11 | 6.91 | 朝下 | ±0.3,本体 1.21×2.21 |
| J604 | 2.12 | 2.46 | 朝下 | ±0.3,本体 0.69×1.10 |
触点坐标怎么来的:先按位号文字位置估(±12 mm),后改成匹配器件本体图元,
到 ±0.3 mm。匹配规则:测试点找直径 0.75±0.25 mm 的圆、连接器找附近面积最大的矩形、
侧键找 0.43.5 mm 的焊盘,并且一个图元只能被一个位号认领(不去重会让
TP1204/TP1205 指向同一个圆)。
三点自洽验证:TP1204 与 TP1205 各自量出 0.73 × 0.74 mm(原理图标注 TP0.75mm)、
Y 坐标完全相同、间距 2.77 mm —— 比例尺、图元匹配、坐标变换三样同时对上才可能这样。
⚠️ 仍要注意:
- 7 个孔 ±0.5 mm(实测照片),触点 ±0.3 mm(矢量图元),J600 是 ±2 mm(本体没匹配上,用的还是位号文字位置)。
- 打样前顶针与 EDL 焊盘要拿实物复核,或做成稍大的焊盘 / 可调顶针座。
机器可读版:.claude/mi8_mech.json(孔位与总体)、.claude/mi8_contacts.json(器件本体版触点)。
关于「找精确机械图纸」(2026-09-04 查过,结论:不用找了): 小米8(dipper) 的免费 boardview 在 vinafix 等站上只有 Mi 8 Lite 与 Mi 8X(Mi A3), 都是别的板子;付费站(laptop-schematics / mobilerdx)声称有 BRD 但要账号积分, 而且给的是同一份数据的另一种封装。手机厂商不公开 DXF/STEP。 我们手上这份位号图本来就是矢量的、精度等于原始 CAD,卡尺又把比例尺锁到 0.7% —— 限制精度的从来不是图纸,是提取方法。
关键触点(看图方向,板左下角为原点):
| 触点 | 面 | 位置 mm | 用途 |
|---|---|---|---|
| J600 电池座 | 正面 | (4.7, 43.1) | BM3E 排线,接 P+/P−(§13.5:必须保留原厂排线) |
| J1401 尾插座 | 正面 | (2.5, 18.3) | 尾插小板 FPC → USB-C |
| TP1204 / TP1205 | 正面 | (5.6, 21.6) / (5.8, 24.4) | EDL,间距 2.8 mm,焊盘 0.75 mm |
| J601~J604 侧键 | 反面 | 四个挤在约 2.7 × 2.6 mm 内 | 顶针 |
由此定死主板朝向:反面朝下贴着载板。(用户 2026-09-04 确认「主板装在上板的上表面」, 与此一致:载板在下、主板反面贴上去、正面朝天。)
- 侧键在反面 → 顶针顶得到 ✅(定位孔正好提供对位基准)
- J600 / J1401 在正面朝上 → 排线和尾插小板从上面插 ✅
- EDL 两个测试点也在正面朝上 → 顶针够不着,只能焊两根线到载板上的 1.25mm 2P 座。
反正 §13.5 已经要求把排线焊到载板的
P+/P−焊盘,焊接本来就在装配流程里。
22.3c 侧键坐标的实测校核 + 公差链(2026-09-04)
⚠️ 这一节我连着读错两次:先把两个读数当成「主板厚度」,又把 7.61 读成 1.76 (卡尺屏是旋转的,数字看反了)。以用户口述为准:
| 实测 | 含义 |
|---|---|
| 7.61 mm | 最上面那个侧键 → 下边框 |
| 4.03 mm | 最左边那个侧键 → 右边框 |
拿它校核 §22.3b 从矢量图元提的侧键坐标(顶视,板 67.09 × 44.66,左下原点):
| 实测 | 对应推算 | 差 |
|---|---|---|
| 7.61 | J603 中心 Y=6.91、本体高 2.21 → 远边 8.01 | 0.40 |
| 4.03 | J602 中心 X=5.41、本体宽 2.22 → 近边 4.30 | 0.27 |
两个独立测量都落在 0.3~0.4 mm 内,而且差值正好是「实测量到触点边缘、 推算给的是触点中心」的半宽差 —— 坐标提取方法得到验证。
⚠️ 顶针的公差链(设计必须吃掉这个误差)
顶针实际落点误差 = 坐标提取 ±0.3 + 定位孔 ±0.5 + 装配间隙 ≈ ±1 mm
而手机侧键弹片触点本体才 1.2 ~ 2.2 mm —— ±1 mm 有可能顶偏。
原来写的三条对策里,前两条 2026-09-04 选型时都被否掉了:
| 原对策 | 结论 |
|---|---|
| ❌ 这个高度档没有大冠径的。选定的 YTC1P-2510-01 柱塞只有 Ø0.9 球头(§22.3e) | |
| ❌ 定的是 SMD 贴片顶针(Ø2.0 单焊盘),回流自对中,装完不能调 | |
| 首件必验 | ✅ 现在是唯一的对策,见下 |
所以唯一的办法是首件实测校正:第一块载板先用一块真主板试压,
四个触点逐个测通断;打偏的把实测偏移量填回 mi8_contacts.json 再出第二版。
减小误差本身也有一条路:±1 mm 里 ±0.5 来自定位孔坐标是从照片提的。 用卡尺把那 7 个定位孔重新量一遍,这一项能直接砍掉一半。
另外,四个触点的风险不一样:
| 触点 | 本体尺寸 | 打偏的后果 |
|---|---|---|
| J601 音量+ | 2.23 × 1.21 | 该键失效 |
| J602 音量− | 2.22 × 1.20 | 该键失效(还连着 Fastboot 组合键) |
| J603 电源键 | 1.21 × 2.21 | 最关键,断电重启全靠它 |
| J604 公共地 | 0.69 × 1.10(最小) | 无所谓 —— P− 已经把地送到手机了,它只是冗余 |
22.3e 叠层高度与顶针选型(2026-09-04 实测)
| 实测 | 值 |
|---|---|
| 裸板厚 | 0.8 mm |
| 侧键面(朝下)最高件 = 屏蔽罩,高出该面 | 1.4 mm |
| 同一个屏蔽罩量到另一板面 | 2.2 mm |
自洽校核:0.8 + 1.4 = 2.2 ✔ —— 两个读数描述同一个屏蔽罩,数据可信。
立柱与顶针(2026-09-04 选型定稿,推翻了原来的 2.0 mm)
侧键触点就在板面上(高度 0),而同一面的屏蔽罩高 1.4 mm,所以立柱只有下限 (>1.4 mm),没有上限 —— 立柱越高,屏蔽罩净空越大、板下风道越通。
⚠️ 原来先定「立柱 2.0 mm」再去找「工作高 2.0 mm」的顶针,方向反了,而且买不到。
把立创上唯一成系列的单针 POGO(怡远 YTC1P-XXYY-01,规格书 C5221293.pdf)整族列出来:
| 型号 | 立创 | 自由高 A+B | 行程 D | 压到底 C | 库存(2026-09-04) |
|---|---|---|---|---|---|
| YTC1P-1510-01 | — | 2.00 | 0.35 | 1.65 | |
| YTC1P-1807-01 | — | 2.50 | 0.55 | 1.95 | |
| YTC1P-2010-01 | C5221287 | 3.00 | 0.70 | 2.30 | 8570 |
| YTC1P-2510-01 | C5221288 | 3.50 | 0.80 | 2.70 | 3385 |
| YTC1P-3010-01 | C5221282 | 4.00 | 0.80 | 3.20 | 5355 |
| YTC1P-3015-01 | C5221293 | 4.50 | 1.00 | 3.50 | 330 |
| YTC1P-3515-01 | C5221292 | 5.00 | 1.30 | 3.70 | 3180 |
| YTC1P-4015-01 | C5221281 | 5.50 | 1.30 | 4.20 | 1720 |
规格书里 A/B/C/D 的含义(图纸实测,别按名字猜):B = 露出的柱塞长度,A = 柱塞根部到
法兰底面,C = 压到底的总高,D = 最大行程,且恒有 A+B = C+D = 全高。
型号里的 XXYY:XX.X ≈ A、YY = B×10(1510 那一行是规格书自己的笔误)。
全族「压到底」都 ≥ 2.30 mm,所以 2.0 mm 的间隙一根都用不了 —— 顶到底就变成硬顶块, 20 根针 × 100 g ≈ 2 kg 会把主板从立柱上顶起来。正确顺序是先选顶针,再由它定立柱高。
定稿:立柱 3.0 mm + 顶针 YTC1P-2510-01(立创 C5221288,SMD Ø2.0 单焊盘)。 自由高 3.5 → 压缩 0.5 mm = 62% 行程(约 62 g 接触力),压到底还差 0.3 mm; 屏蔽罩净空 3.0 − 1.4 = 1.6 mm。额定 12 V / 1.5 A、接触电阻 ≤100 mΩ、寿命 1 万次。
⚠️ 立创参数页把 2510 的「工作高度」写成 2.3 mm,是错的(那是 2010 那一行的值); 同族其它型号的参数页都和规格书一致。以规格书图纸为准。
⚠️ 冠径只有 Ø0.9 球头(柱塞 Ø0.9 / 外管 Ø1.5 / 法兰 Ø2.0), 这一族没有 §22.3c 想要的 Ø1.5~2 大冠径。所以那 ±1 mm 公差链不是靠针头吃掉的, 只能靠首件实测校正(§22.3c 的对策 3)。四个触点里 J601/J602/J603 窄边约 1.2 mm, 是必须打准的;J604 只是三键公共地,而 P− 已经把地送到手机了 —— J604 打偏不影响功能, 它是冗余而不是关键路径。
叠层累计(从载板顶面往上)
载板顶面 ─┬─ 3.0 立柱 ─┬─ 0.8 主板 ─┬─ h_up(正面元件高,**还没量**)
│ │ └─> 主板最高点 = 3.8 + h_up
└─ 顶针工作段 3.0(自由高 3.5,压缩 0.5)
🚧 还缺 h_up(正面 = 朝上那面最高元件高出板面多少)。 它决定压板高度和整机层高,但不影响立柱与顶针选型,可以后补。
📌 有压板把主板压在立柱上,所以 Z 向是确定的(只剩立柱长度公差 + 顶针焊高, 约 ±0.15 mm),不需要按 Z 向公差留大余量 —— 选型按接触压力定即可。
22.3d ⚠️ 排针叠高与下板高元件冲突
下板上现在最高的两个件:
| 器件 | 高度 |
|---|---|
| C2 / C3 470 µF 直插电解 | 约 12 mm |
| R9 泄放电阻(立式) | 约 9 mm |
(J23 USB-C 3.2 mm 已经随 Hub 搬到载板,不再是约束。)
→ 两板净空必须 ≥ 13 mm,而标准 2.54 排针 + 插座对插高度只有 8.5~11 mm,不够。
三条出路,推荐第一条:
- 用加高排针(11.0 / 13.0 / 15.0 mm 都有现成料)。改动最小,顺带改善散热。 代价:针变长、回路电感略增 —— 13 mm 针约 10 nH,三针并联约 3 nH, 相对 §22.2 的 30~50 nH 预算可以忽略。
- 把 C2/C3 换成贴片电解 / 固态电容(矮,但容量密度低、要多几颗)。
- 在载板上对着 C2/C3 开孔让位(载板 200×150 完全盖住下板 160×125,所以要真的开孔)。
22.4 EDL(9008)控制口
原理图 Sheet 17(PDF 第 19 页):
VREG_S4A_1P8 ──[R1204 1.8kΩ ±5% 0201]── TP1204 ← 0.75 mm 测试点
FORCED_USB_BOOT ──┬── TP1205 ← 0.75 mm 测试点
└── CR1209 PESD3V3V1BCSF ── GND
短接 TP1204 ↔ TP1205 = 把 FORCED_USB_BOOT 拉到 1.8 V → SoC 进 9008。
串了 1.8 kΩ,短路电流只有 1.8V/1.8kΩ = 1 mA —— 所以不需要继电器、也不需要光耦, 一颗模拟开关(TS5A3157 / NLAS4599 一类,3.3 V 供电,1.8 V 信号在导通范围内, Ron ~1 Ω)就够。每台一颗,放在 1.25mm 2P 座旁边。
⚠️ 别用普通 N-MOS 直接跨接两点:源极那侧导通后会被抬到 1.8 V, 3.3 V 栅压只剩 Vgs=1.5 V,落在阈值附近。要么用模拟开关,要么用 5 V 栅压驱动。
时序:先短接、再插 USB(等价于原厂短接法的「保持短接再连线」)。
固件里的顺序是 EDL_EN=1 → VBUS_EN=1 → 等枚举 → EDL_EN=0。
EDL_EN1~5 从哪来:第三片 74HC595(U33,2026-09-04 新增)
排针接口要 5 根 EDL_EN,但 §8.1 的 GPIO 已经排满,两片 74HC595 的 16 路输出
也全被占掉了(15 路侧键 + HUB_RST),PCA9555 只剩 4 个空脚 —— 差一路。
所以在 U22 之后再级联一片 74HC595(U33,位号见 P6-FAN-EDL 页):
U21 ──QH'(9)──> U22.SER(14) [SR_CAS]
U22 ──QH'(9)──> U33.SER(14) [SR_CAS2] ← 本轮新增,U22.9 原来是悬空的
U33: QA=EDL_EN1 QB=EDL_EN2 QC=EDL_EN3 QD=EDL_EN4 QE=EDL_EN5 QF/QG/QH 备用
SRCLK / RCLK / OE# 三根与前两片共用,不占新 GPIO。
移位链从 16 位变成 24 位,先移入的那个字节落在 U33 上 —— 固件要跟着改。
载板侧已画(2026-09-04,C4-SITE1~5 各一套)
| 位号 | 器件 | 接法 |
|---|---|---|
U41~U45 |
TS5A3157DBVR(C353034,SOT-23-6) |
COM(4) 与 NO(1) 分别接 1.25mm 座的两针;NC(3) 不接;V+(5) = +3V3_HUB;IN(6) = EDL_ENn |
J61~J65 |
A1251WV-S-2P(C225104,1.25 mm 2P) |
两根线焊到主板正面的 TP1204 / TP1205;两个固定脚接地(与 C3-USB 上的 J17 一致) |
R741~R745 |
100 kΩ | EDL_ENn 下拉到地 |
C761~C765 |
100 nF | 开关去耦 |
⚠ EDL_EN 的 100 kΩ 下拉不在下板,在载板上,紧挨着那颗模拟开关。
理由和按键 MOS 栅极下拉一样(§8.1 复位安全三条):下拉要靠近被驱动的器件,
否则排针一断开、载板那头就浮空。ESP32 复位期间 595 输出高阻,
下拉保证五台手机不会被误拉进 9008。
22.6 散热:强制风冷(2026-09-04 用户拍板)
先说被否掉的方案:曾提议在侧键面屏蔽罩与载板之间那 0.6 mm 缝里塞导热垫, 把 SoC 的热导进载板铜箔。用户否决,改用风扇。
风道(用户定)
┌──────── 顶部 1 个大风扇,向外排 ────────┐
│ ↑ ↑ ↑ ↑ ↑ │
→→ ┌─┴───────────────────────────────────┬─┐ ←←
侧面 │ 载板:5 块主板 │ │ 侧面
2 个 │ ─────────── 13 mm 缝(天然风道)──── │ │ 2 个
吸入 │ 下板:五路功率级 │ │ 吸入
→→ └─────────────────────────────────────┴─┘ ←←
4 进 1 出 = 机箱正压 —— 灰尘从缝隙往外走而不是往里吸,长期运行更干净。 两板之间那 13 mm 缝正好是侧面进风的天然风道,顺带吹到下板的功率级。
热负荷与风量
| 来源 | 估算 |
|---|---|
| 5 × SDM845 满载 | 10 ~ 15 W |
| 下板五路 Buck(92%)+ eFuse + 分流 | ≈ 9 W |
| 合计 | ≈ 25 W |
Q = P/(ρ·cp·ΔT),ρ·cp ≈ 1.2 kJ/m³K、ΔT = 15 K →
Q = 1.4 L/s = 5 m³/h ≈ 2.9 CFM。
4 个 40 mm 风扇随便超过 —— 风量不是瓶颈,风道和正压才是设计要点。
电气(全部在下板,不占排针)
| 项 | 选择 |
|---|---|
| 风扇 | 侧面 4 × 小(40 mm 级)+ 顶部 1 × 大,均 12V |
| 电流 | 4×0.10 + 1×0.30 ≈ 0.70 A @12V = 8.4 W |
| 供电 | 下板 12V 母线,风扇接插件放下板边缘 |
| 驱动 | 低边 N-MOS + PWM,一路驱动全部 5 个风扇 |
| ⚠️ | 风扇是感性负载,MOS 漏极必须并续流二极管 |
| PWM | ESP32 IO47(LEDC 硬件 PWM)—— §8.1 原标「备用」 |
| TACH | ESP32 IO48 |
TACH 的接法(一个脚监 5 个风扇):风扇 TACH 多为集电极开路,
5 个并到同一个脚做线或。全转时脉冲率约为单扇的 5 倍,
停一个频率就掉约 1/5 —— 能检出「有风扇停了」,虽然分不出是哪一个。
要分辨到具体哪个,就得把进风与排风分成两组独立控制,得再找一组 PWM/TACH 脚。
(RXD0 已经在 2026-09-04 划给 UP_VBUS_DET 了,只剩 TXD0 一根,不够。)当前不做。
⚠️ TACH 必须分压,直连 IO48 会打穿 ESP32(2026-09-04 画图时才想明白)
这一条初稿漏了,但它是低边调速 + TACH 组合的必然后果:
低边 MOS 关断时,风扇的「地」被抬到接近 12 V;而 TACH 是以风扇自己的地为参考的 集电极开路输出,于是 TACH 线也跟着浮到 12 V。直接接 3.3 V 的 IO48 就是往 GPIO 上灌 12 V。
实际画法(P6-FAN-EDL 页):
+12V ──[R730 10k]──┬── TACH_RAW ── J26~J30 的 pin3(5 个并联)
└──[R731 10k]──┬── FAN_TACH → IO48
└──[R732 3.3k]── GND
- IO48 上的最高电压 = 12 × 3.3 / 13.3 = 2.98 V,在 3.3 V 以内,不需要钳位管。
- 代价:PWM 关断期间读到的是稳定高电平,测不到转速;只有导通期间才有脉冲。 这是低边调速的固有限制,不是接线错 —— 固件要么在占空比 100% 的时候采转速, 要么按导通窗口去数脉冲。
- 想彻底解决就得换 4 线 PWM 风扇(风扇常供电、PWM 是独立输入脚, TACH 直接以板地为参考)。风扇型号还没定,如果最终选了 4 线风扇, 这一段的 MOS + 续流管 + 分压全都可以删掉,改成 PWM 脚直驱 + TACH 上拉到 3V3。
已画元件(P6-FAN-EDL 页,2026-09-04)
| 位号 | 器件 | 作用 |
|---|---|---|
| Q6 | AO3400A | 低边开关,切 5 个风扇的回流 |
| D2 | SS34 | 续流二极管,K 接 +12V、A 接风扇回流 |
| R733 / R734 | 1 kΩ / 100 kΩ | 栅极串阻 / 栅极下拉(复位期间风扇不转) |
| R730 / R731 / R732 | 10 k / 10 k / 3.3 k | TACH 上拉 + 分压 |
| C738 | 22 µF/25 V 1206 | 风扇 12 V 本地储能 |
| J26 ~ J30 | KF2510-3A(2.54 mm 3P) | 每个风扇一个:pin1 = +12V,pin2 = 风扇回流,pin3 = TACH |
对 12V 输入预算的影响
原预算:五路 4A × 4.2V ÷ 0.92 ÷ 12V ≈ 7.6 A; 加风扇 +0.70 A → 约 8.3 A,10 A 适配器仍有余量(§1 规格不用改)。
测温仍然放载板
风扇是给手机降温的。板上已有的两路 NTC(IO1 电感区 / IO2 MOS 区)测的是
下板功率级,拿它做反馈等于测错地方。而 ESP32-S3 的 ADC1 只有 GPIO110,
IO4IO10 已被 EFUSE_EN/VBUS_EN 占满,没有多余 ADC 脚。
所以把 I²C 引到载板(排针 +2 针),放一颗数字温度芯片。
现有 I²C 已挂 9 个器件,再加 1~2 个没压力。
待定
- 风扇具体型号、外壳风道尺寸(等 3D 外壳方案)
- 顶部排风扇的风量要 ≥ 4 个进风扇之和的多少,才不会把机箱压得过头(一般不用管, 正压是有意为之;但外壳要留泄压缝)
22.5 推翻 / 需要重算的地方
| 位置 | 怎么改 | 状态 |
|---|---|---|
| §6.1 / §6.2 | 线缆电感 300 nH → 板对板 30~50 nH,压降与 Q 重算 | ⬜ 还没算 |
| §6.3 / §6.4 | 电容组从「装在排线端」改成「装在载板 P+/P− 焊盘旁」,条件自动满足 |
⬜ 电容组还没画到载板上 |
| §13.3 | 侧键从飞线改成顶针 | ✅ 下板侧已改(POGOn_*) |
| §15.1 / §15.2 | Hub 与 VBUS 开关移到上板;J17~J21 不是取消,是跟着搬到载板(见下) |
✅ |
| §15.4 | 线束表作废,改成 §22.2 的排针接口表 | ✅ |
| §10 PCB 布局 | 下板接口区重排(连接器分边决策作废);上板是第二块 PCB | ⬜ 没动 |
| 原理图 P4 / P4B | Hub 页整页搬到上板工程 | ✅ 已复制到 Board2 并从下板删除 |
| 原理图 P5-HARNESS | 从线束页改成板对板接口页 | ✅ 已改名 P5-BTB 并重画 |
| 设计文档 §8.1 | IO47 = FAN_PWM、IO48 = FAN_TACH,从「备用」改成已分配 |
✅ 另加 IO44 = UP_VBUS_DET |
| 设计文档 §8.2 | I²C 设备表加载板上的温度芯片 | ⬜ 芯片型号还没选 |
⚠️ 修正初稿的一句话:上面原来写「J17~J21 取消」。实际上 J17J21 是
A1251WV-S-4P(1.25 mm 4P)出线座,不是 USB-A 母座(USB-A 母座是更早的 J12J16,
Hub 改造那一轮就已经删了)。它们从下板整体搬到载板,位号和接法都不变 ——
变的只是插上去的东西(§13.5:从「USB-A 转 C 短线」换成「J1401 转接小板」)。
22.7 原理图落地结果(2026-09-04,两板拆分已完成)
EasyEDA 工程 Zy1993/五路手机直供电源板 里现在是两个 Board:
| Board | 原理图 | PCB | 内容 |
|---|---|---|---|
Board1 phonerail-5ch-psu |
11 页 | PCB1(160×125,已布线) |
下板:电源 + 控制 |
Board2 phonerail-carrier |
3 页 | PCB2-CARRIER(空) |
上板:载板 |
下板 11 页(页序已排好)
| # | 页 | 本轮变化 |
|---|---|---|
| 1 | P1-INPUT | 无 |
| 2 | P1B-5V | 摘掉 U31 + C736 + C737(Hub 专用 3V3 LDO 跟 Hub 一起上载板),现在是纯 12V→5V |
| 3~7 | P2-CHANNEL / P2B~P2E | 每页删 2 个连接器:J2~J6(Micro-Fit 出线)+ J7~J11(6P 侧键出线);三路侧键漏极改挂 POGOn_PWR/VUP/VDN 端口 |
| 8 | P3-CONTROL | 新增 FAN_PWM(IO47) / FAN_TACH(IO48) / UP_VBUS_DET(IO44=RXD0) |
| 9 | P3B-EXPAND | U22 的 QH'(pin9) 原来悬空,现在引出 SR_CAS2 去级联 U33 |
| 10 | P5-BTB(原 P5-HARNESS) | 整页作废重画:J24 / J25 两条 2×20 排针,47 信号 + 33 地 |
| 11 | P6-FAN-EDL(新建) | 【A】U33 第三片 595 → EDL_EN1~5;【B】风扇低边驱动 + TACH 分压 + J26~J30 |
从下板整页删掉的:P4-USB、P4B-HUB(已先复制到 Board2 再删)。
载板 11 页(2026-09-04 全部画完,方案 D 改造后)
2026-09-04 深夜方案 D 改造:C3-USB 删掉 J17~J21 五个 1.25mm 出线座, 新增 C5-J1401A / C5-J1401B(五颗 BM24-50DS 座)和 C5-AUX (每路的 ESD + CC 上拉 + 口温电阻)。USB 链路变成:
C2-HUB 的 U32 → C5-AUX 的 U5n → C5-J1401 的 J7n → 原厂尾插排线 → 手机 J1401。 D± 不再经过 C3-USB,那一页现在只负责切 VBUS。 生成脚本:.claude/c5_j1401.py/.claude/c5_aux.py/.claude/c3_usb.py。
| 新增位号 | 器件 | 在哪 |
|---|---|---|
| J71 ~ J75 | BM24-50DS/2-0.35V(51)(C424561) |
C5-J1401A/B |
| U51 ~ U55 | USBLC6-2SC6(C2687116)D± ESD |
C5-AUX |
| R761 ~ R765 | 56 kΩ(C25796)CC1 → VBUS 的 Rp |
C5-AUX |
| R771 ~ R775 | 100 kΩ(C25741)口温 → GND(阻值从主板 BIAS-20k-TSKIN 分压反推,见 §13.5) |
C5-AUX |
已删:J17 ~ J21(A1251WV-S-4P 出线座)。
载板原来的 8 页
| # | 页 | 内容 |
|---|---|---|
| 1 | C1-CONN | 排母 J31 / J32(对插 J24 / J25)+ U31 AMS1117-3.3(5V→3.3V,载板唯一 3.3V 源)+ U34 LM75BD 温度芯片(0x48) |
| 2 | C2-HUB | 从下板搬来的 Hub 页(U32 + Y1 + 全部 strap + J23),新增 R721/R722 上游 VBUS 检测分压 |
| 3 | C3-USB | 从下板搬来的 VBUS 开关页(U24 |
| 4~8 | C4-SITE1~5 | 每台手机一页:P+/P− 焊盘 + §6.3 电容组 + 4 根侧键顶针 + EDL(1.25mm 座 + 模拟开关 + 下拉 + 去耦) |
为什么手机位一台一页:一套 16 个元件,五套 80 个塞一页会挤成一团 ——
和下板「一路一页」(P2 / P2B~P2E)保持同一个结构,而且五页由
.claude/c4_site.py 同一段代码生成,改一处五页一起变。
载板位号分配
| 位号 | 器件 | 在哪 |
|---|---|---|
| J31 / J32 | 2×20 排母(C5307344 PC104-2×20,直插,塑高 10.5) |
C1-CONN |
| U31 / C736 / C737 | AMS1117-3.3 + 10µF + 22µF | C1-CONN |
| U34 / C760 | LM75BD + 100nF | C1-CONN |
| R721 / R722 | 10k / 20k,上游 VBUS 分压 | C2-HUB |
| TP801/802, TP811/812 … TP841/842 | P+(红) / P−(黑) 焊盘(C9900007423 / C9900007426) |
C4-SITE1~5 |
| C801 |
§6.3 电容组(每套 6 颗) | C4-SITE1~5 |
| J41 ~ J60 | 侧键顶针,每台 4 根(PWR / VUP / VDN / J604 公共地) | C4-SITE1~5 |
| J61 ~ J65 | EDL 1.25mm 2P 座 | C4-SITE1~5 |
| U41 ~ U45 | TS5A3157DBVR 模拟开关 | C4-SITE1~5 |
| R741 ~ R745 / C761 ~ C765 | 100k 下拉 / 100nF 去耦 | C4-SITE1~5 |
载板上的占位型号(打样前必须换)
顶针→ ✅ 已换成C9900001338C5221288YTC1P-2510-01(2026-09-04,见 §22.3e)。c4_site.py里P['POGO']已改,C4-SITE1~5 五页重生成并复验通过。排母→ ✅ 已换成C9900025309C5307344PC104-2×20(2026-09-05,见 §22.3f)。 塑高 10.5 + 公头塑高 2.5 = 对插 13.0 mm,是库里唯一够得到的一族; 同时从贴片变成直插,80 个通孔脚自带过孔。c1_conn.py/p5_btb.py已改并重生成两页,编号体系换件后公母统一(§22.2)。
载板位号表 J41~J60(侧键顶针)的最新型号
| 型号 | YIYUAN YTC1P-2510-01 |
| 立创 | C5221288(Extended Part) |
| 封装 | SMD-1_BD2.0-H3.6,单焊盘 Ø2.0 贴片 |
| 符号 | 只有 1 个引脚(引脚在符号中心左侧 15 单位;老那颗是 20,所以坐标必须读回不能推) |
| 图上名字 | 改短成 POGO(默认名 13 字会和相邻顶针叠字);supplierId 未动,BOM 照旧 |
上游 VBUS 检测(C2-HUB 新增)
UP_VBUS_DET 在 §22.2 里占了一根排针,但载板上原来没有源头。
J23 的 VBUS 是 5 V,而排针那头是 ESP32 的 IO44(3.3 V 域),所以要分压:
VBUS_UP(5V) ──[R721 10k]──┬──[R722 20k]── GND
└── UP_VBUS_DET → 排针 → IO44
5×20/30 = 3.33 V;USB 上限 5.25 V 时 3.5 V,仍在 ESP32 绝对最大值 3.6 V 以内, 且远高于 VIH(≈2.48 V)。主机没插时 VBUS = 0,读到 0 —— 这正是要的判据。
本轮新增的位号
| 位号 | 器件 | 在哪 |
|---|---|---|
| J24 / J25 | 2×20 排针(C55020601 AZ-PZ2.54-V11-2×20P,直插,塑高 2.5) |
P5-BTB |
| U33 | 74HC595D(C5947) |
P6-FAN-EDL |
| C739 | 100 nF | P6-FAN-EDL |
| Q6 | AO3400A | P6-FAN-EDL |
| D2 | SS34(C8678) |
P6-FAN-EDL |
| C738 | 22 µF/25 V 1206 | P6-FAN-EDL |
| R730 / R731 | 10 kΩ | P6-FAN-EDL |
| R732 | 3.3 kΩ(C25890,新料) |
P6-FAN-EDL |
| R733 | 1 kΩ | P6-FAN-EDL |
| R734 | 100 kΩ | P6-FAN-EDL |
| J26 ~ J30 | KF2510-3A 2.54 mm 3P(C2940511,新料) |
P6-FAN-EDL |
R735~R739(EDL_EN 的 100 kΩ 下拉)故意不在下板,见 §22.4 末尾。
验证结果
| 下板 Board1 | 载板 Board2 | |
|---|---|---|
| 页数 | 11 | 8 |
| 六项几何验证 | ✅ 全过 | ✅ 全过 |
| 跨页对账 | ✅ 0 漏接 / 0 待补 | ✅ 0 漏接(62 个网络) |
port_audit.py |
✅ 513 个,可疑 0 | ✅ 260 个,可疑 0 |
| 存盘后重开复验 | ✅ | ✅ |
port_audit.py 现在带 --board Board2 就扫载板(页表在 .claude/eda-parts.json
的 schematic_boards 里)。
画图时踩到的三条新坑(都已写回 skill)
-
create()的 rotation 参数和setState_Rotation()差 180°。 同样传 270:create得到 SS34 的 pin1(K) 在下,setState_Rotation得到 pin1(K) 在上。 所以 §6 那张「rotation 90/270 → pin1 在哪」的表只对 create 成立。 -
同样是
create(270),不同型号的极性元件方向还不一样。 P5 上 2200µF 电解(C49256788)create(270)得到 pin1 在上; C4-SITE 上同一颗料同样create(270)却得到 pin1 在下。 结论只有一条:极性元件一律读回getAllPins()再断言,不要相信任何一张方向表。c4_site.py里就断言「电解 pin1 必须比 pin2 的 y 大」,不过就直接终止。 -
引脚跨距连同族都不统一。 红色测试点的引脚在
cx−20,黑色测试点在cx−10; 0402 是 ±20 而 1206 是 ±15。按名义值算线会画出斜线,而sch_PrimitiveWire.create()对斜线直接抛create failed!(这次就是这么被拦下的)。c4_site.py现在统一「读回坐标 → 断言横平竖直且非零长度 → 才下发」。
三条合起来是同一件事:这个 API 里任何几何量都必须读回来,不能推。
23. Board3:J1401 尾插转接小板(2026-09-04 画完,当晚作废)
这块板已经从工程里删掉了(Board3 / phonerail-usbtap / PCB3-USBTAP 全部删除,
生成脚本挪到 .claude/obsolete/t1_usbtap.py)。原因见 §13.5:改回方案 A,
装原厂尾插小板 + 一根改端子的 USB-A 转 C 线,本板要解决的问题全部消失。
留下这一节,是因为画它的过程中挖出来的四条结论在别处仍然有效。
23.1 ⚠️ 立创的 BM24 封装焊盘编号是错的(仍然有效,见 §13.4 末尾)
小米8 的 J1401 是奇偶行编号(1,3,5…49 一排 / 2,4,6…50 另一排),
而立创的 CONN-SMD_BM24-50DP-2-0.35V51 和 BM24-50DS 封装都是DIP 绕圈式。
这一条同时也是 §13.4 那张引脚表的独立佐证 —— 三条证据(符号画法、
44/46/48/50 = GND/D+/D−/GND 的差分对包地、奇数排全音频偶数排全数字)互相印证,
说明 §13.4 的表是对的。将来若有人再想自制转接板,先读 §13.4 末尾。
23.2 BM24 只有 10 次插拔寿命
Hirose 规格书 Durability 一栏写的是 10 mating cycles。 方案 A 下同样成立 —— 原厂尾插排线插上 J1401 之后就别反复拔, 调试期要拔的话记着次数,备件按每台手机 2 根排线备。
23.3 Rp / Rd 分压核算(解释了为什么 A 转 C 线就够)
手机侧 PMI8998 在 CC 上挂 Rd = 5.1 kΩ ±20%,A 转 C 线的 C 头里是 Rp = 56 kΩ:
V_CC = VBUS x Rd / (Rp + Rd)
标称:5.00 x 5.1/(56+5.1) = 0.417 V
最低:4.75 x 4.08/(56.56+4.08) = 0.320 V
最高:5.25 x 6.12/(55.44+6.12) = 0.522 V
UFP 侧 vRd-USB = 0.25 ~ 0.61 V(Default USB 档),三个角点全在窗口内,
离两端都有 ≥70 mV 余量。往上 0.701.16 V 是 1.5 A 档、1.312.04 V 是 3.0 A 档 ——
所以买到阻值给错的线(22 k / 10 k)会让手机以为能取 1.5~3 A,而 TPS22918 给不了。
到手务必用万用表量一下 CC 对 VBUS 是不是 56 kΩ。
23.4 为什么「把转接板直接做进载板」做不到(当时的分析,结论仍然成立)
两条各自独立的硬阻碍:
- 面朝向:§22.3b 定死「主板反面朝下贴着载板」(侧键在反面,顶针要往上顶), 而 J1401 在正面朝天,焊在载板上的 BM24 够不着。翻过来装也不行 —— BM24 对插高度只有 0.8 mm,主板正面的屏蔽罩超过 0.8 mm,贴不下去。
- 自对准范围只有 ±0.3 mm(Hirose:alignment range of 0.3 mm), 而 §22.3c 的公差链是 ±1 mm,差 3 倍。BM24 必须装在能自由浮动、 由人手对准后插进去的东西上 —— 原厂尾插排线正好就是这个东西。
23.5 画图时的两条 API 经验(已写回 skill §8b / §8c)
- EasyEDA 的
create()会在元件引脚处把导线截断。想画一条穿过芯片本体的直通线做不到 —— 中间那段直接消失。所以 USBLC6 这种「1/6 内部短接」的直通器件, D± 在网表里天然是两段,只能各起一个名字。 xpage.py对单页板会误报:只出现一次的 netport 在多页工程里意味着漏接, 在单页板上只是「给这段线起个名字」。
24. BM24-50DS 自建封装(2026-09-04 定稿)
器件已建在个人库:BM24-50DS/2-0.35V(51) HRS-PIN
(device 771dbf002b714bb79cde47cf86aa0fb1,lib 543725e8f0454017a5691e7e570aeef6,
封装 BM24-50DS_HIROSE-PIN = 940f093c1578426aa81e91ebf0bfbd76,符号是立创原符号的副本)。
c5_j1401.py 已改用它,C5-J1401A/B 重生成,三道验证全绿。
BOM 仍指向立创 C424561(Supplier Part / Convert to PCB / Add into BOM 都改回 yes 了 ——
lib_Device.create() 的 property 参数会被吞掉,必须紧跟一次 lib_Device.modify() 补,见 §24.5)。
生成脚本:.claude/fp_bm24.py(--push 重画,--verify 只读回校验)。
24.1 几何从哪来 —— 不是外推,是从官方样本的矢量图里反算的
来源:Hirose BM24 系列官方样本 D47680_en(2021.12③ / Aug.1.2026), "Receptacle → Recommended PCB layout"。样本只给了一张通用图 + 一张 A/B/C 尺寸表, 图上标的尺寸不足以直接建封装,剩下的是从 PDF 里把矢量段坐标提出来量的:
- 标定:图上
P=0.35 mm占 6.706 pt、B=3.15 mm占 60.355 pt → 19.1603 pt/mm,两处自洽。 - 顺带确认那张图画的是 20 芯那一款(C=7.3 / B=3.15 都能对上表)。
| 量 | 值(50 芯) | 怎么得到的 |
|---|---|---|
| 信号焊盘 | 0.18 × 0.48 mm | 宽 0.18 是标注的;长 0.48 样本没标,由外缘 2.6 与内缘 1.64 相减除 2 得出 |
| 同排间距 | 0.35 mm | P |
| 每排 25 个,跨距 | 8.40 mm | B = 24 × 0.35,中心到中心 |
| 两排 y | ±1.06 mm | (2.6+1.64)/2 = 2.12 的一半;和 Header 图上标的 1.06 对得上 |
| 电源焊盘 | 0.49 × 0.76 mm | 0.49 是标注的(它标的是电源焊盘的宽,不是信号焊盘的长 —— 尺寸线量的是 95.44→104.83 那一段,别看错);0.76 是标注的 |
| 电源焊盘中心 x | ±6.03 mm | C = 12.55 是两个电源焊盘的外缘到外缘 → (12.55−0.49)/2 |
| 禁布区 | ±5.785 × ±0.82 mm | 两电源焊盘内缘之间 × 两排焊盘内缘之间(样本画成阴影,注 pattern prohibited area) |
| 本体 | A = 12.25 × 2.3 mm,高 0.8 | 装配层用 |
样本上那个 0.14MAX 是中线上允许穿过禁布区的一条细缝。
我们不用它 —— G1 是地、G2 是 VBUS,这两个电源触点绝不能连起来。
封装里画了:52 个焊盘(顶层)、丝印外框 13.2 × 2.9(在所有焊盘之外,不压焊盘)+ 1 脚标记、 装配层本体框 12.25 × 2.3、文档层的禁布区框(布板时铺铜别灌进去)。
锡膏:Hirose 推荐钢网 0.1 mm 厚、DS 侧开口率 80%(信号开口 0.39 × 0.18,比焊盘短)。 封装里用的是默认「锡膏 = 焊盘」,打样时如果自己出钢网文件要按上面缩;走嘉立创贴片则不用管。
24.2 焊盘编号约定(fp_bm24.py 的 ODD_ROW_TOP)
奇数脚 1,3,5 … 49 → +Y 那一排 1 脚在 −X 端(x = −4.20)
偶数脚 2,4,6 … 50 → −Y 那一排 49/50 在 +X 端
pin 51 = 1/2 脚那一端的电源触点 (x = −6.03)
pin 52 = 49/50 脚那一端的电源触点 (x = +6.03)
和 c5_j1401.py 里的 PWR = {'GND': 52, 'VBUS': 51} 是配套的。
24.3 ⚠️⚠️ 唯一没有实证的一位:哪一排是奇数排(镜像位)
⚠️ 2026-09-06 载板 v2 把 J7n 翻到了底层(rot 0 时奇数排在南,§25.16)。下面的推理是按顶层装法写的, 实测时以底层装法为准 —— 层翻一次手性翻一次。
BM24 的 DS 座完全对称(样本注 2 原文 This connector has no polarity; 本体图两端一模一样、上下两排也一模一样,没有任何 1 脚标记), 所以「奇数脚在哪一排」不是这颗座子本身的属性,而是小米8 那块板子的布局事实, 图纸查不到 —— 我们只有原理图,没有小米8 的 PCB。
把编号往位置上贴,一共有 4 种候选:
| 1 脚在 −X 端 | 1 脚在 +X 端 | |
|---|---|---|
| 奇数在 +Y 排 | A(现在选的) | C |
| 奇数在 −Y 排 | B | D |
- A ↔ D、B ↔ C 差一个 180° 旋转 —— 贴片时转个方向就能换,不用重打板。
- A ↔ B、C ↔ D 差一个镜像 —— 相当于每个奇数脚和它的偶数搭档对调
(D+ 会落到 45 脚
SPKR_OUT_P上)。旋转换不掉,错了要重打载板。
原来 §13.5 写的「两种候选差一个 180° 旋转」只覆盖了前一半,已在上面更正。
打样前必做的那一次实测(两个探点,零成本、零风险)
拿手机主板(不通电)+ 万用表通断档,在 J1401 上量:
- 先认哪一端是 1/2 脚端:两个电源触点(焊盘大,0.49 × 0.76 mm,好戳)分别对主板地量电阻。 ~0 Ω 的那个是 G1,G1 就在 1/2 脚那一端(§13.4)。
- 再认哪一排是奇数排:从 G1 那一端数,两排各自的第 2 个信号触点分别对地量。
- 奇数排的第 2 个 = pin 3 = GND ✔
- 偶数排的第 2 个 = pin 4 =
VREG_L19A_3P0,不是地 通的那一排就是奇数排。
这两点选得刻意:都紧挨着 G1 那一端,不用在 0.35 mm 间距里数到中间去;
而且判据是「通/不通」不是读数,探针滑一格也不会读错
(滑到 pin 1 = MIC_BIAS1、pin 5 = CDC_MICIN,都不是地)。
量完对照下表,落到哪个候选就把 fp_bm24.py 的 ODD_ROW_TOP 改一下重跑
(--push 一遍,1 秒的事);1 脚在哪一端那一位则留给贴片方向,封装不用动。
| 实测结果 | 要做的事 |
|---|---|
| 奇数排 = 载板上朝 +Y 的那一排 | 什么都不用改(当前就是 A) |
| 奇数排 = 朝 −Y 的那一排 | ODD_ROW_TOP = False,重跑 fp_bm24.py --push |
✅✅ 2026-09-05 已实测:A,什么都不用改
用户拿主板 + 万用表量的,两条结论:
| 实测 | |
|---|---|
| 右端那个大触点是 G1(对地导通) | ⇒ J1401 的 1/2 脚端在右端(顶视、接口边朝下) |
| 下面那一排(靠板边那一排)是奇数排 | ⇒ 镜像位定了 |
第二张照片确认了唯一那个几何前提:排线从 J1401 直接朝板下边缘出去
(软板一路下到尾插小板,板上印着 MAIN + 指向主板的箭头)。
所以「靠板边那一排」= 排线侧 = 内侧排。
推导链(每一环都是已实测的事实,不是推测):
J1401 靠板边那一排(= 内侧排) ← 实测:奇数排
↕ 公头A 内侧排
↕ 排线 1:1 直通,内侧↔内侧 ← §13.5 用户实测
↕ 公头B 内侧排
载板 J7n 朝手机那一排(+Y) ⇒ 奇数排
载板这一侧为什么是「朝手机那一排」:排线出 J1401 → 越过手机板边 → 台阶式下折
(折线平行于连接器长轴)→ 回头插进 v = −3.0 的 J7n,所以在 J7n 处软板本体朝 +v 伸出。
而 to_board() 对五个位都保证「封装本地 +Y = 朝手机主板」(CH1~3 rot 0、CH4/5 整位 180°)。
⇒ ODD_ROW_TOP = True 就是对的,封装、原理图、摆位一个都不用动。
第二位(贴片方向)同时也自洽了:折叠不翻长轴方向,所以 J1401 的左端(G2 = USB_VBUS)
对应载板座子的左端;我们的封装是 pin51(VBUS) 在 −X、pin52(GND) 在 +X、J7n 摆 rot 0,
⇒ VBUS 端落在 −X = 手机左端 ✔,和 §13.5 推出的「52 = GND、51 = VBUS」对上。
⚠️ 首件仍要按 §24.4 量一次
VBUSn对 GND 的电阻 —— 那是验证,不是决定。
可选的零成本复核(还没做,做了这一位就彻底钉死)
不需要地参考,两根表笔点相邻触点:奇数排上从 G1 端数,
位置 17-18-19 互相导通(SPKR_OUT_N 33/35/37)、22-23-24 互相导通(SPKR_OUT_P 43/45/47);
偶数排同样位置是 VREG_BOB / GND / 口温,不导通。
这一步必须在下单载板 PCB 之前做完—— 2026-09-05 已做完,见上。 (当时写的退路:把 50 个焊盘全引到板边测试点、首件焊好再跳线 —— 用不上了。)
24.4 还有一个老的待实测项(§13.5 已记,这里只做交叉引用)
G1/G2 落在我们这颗座子的哪一端(即 51/52 谁是地)。
它属于上面表里「1 脚在哪一端」那一位,贴片时转 180° 就能纠,所以不致命。
首件上电前量一次 VBUSn 对 GND 的电阻即可(负载开关默认关断,零风险)。
24.5 建库时踩的两条 API 坑
lib_Footprint.copy()对系统库的封装静默失败(返回undefined,不抛错), 系统库封装也openInEditor()不了(返回false)。 所以「复制立创封装再改编号」这条路走不通 —— 只能lib_Footprint.create()建空封装、 自己把 52 个焊盘画出来。反过来说这也是好事:几何直接按官方样本落,不继承立创的错。lib_Device.create()的property参数会被吞掉:建出来的器件Add into BOM/Convert to PCB都是 no(意味着根本不会转到 PCB), 供应商编号也全丢。必须紧跟一次lib_Device.modify(uuid, lib, u,u,u,u, {...})补上, 而且property要用{name, addIntoBom, addIntoPcb, otherProperty:{...}}这个嵌套结构。
25. 载板 PCB(PCB2-CARRIER,2026-09-04 从零布起)
生成脚本 .claude/pcb2_place.py(--outline 板框 / --mech 机械要素 / --push 摆件)。
截图 PCB2-carrier-v1.png、PCB2-site1.png、PCB2-j23.png。
25.1 板框与排布(用户拍板)
220 × 135 mm,四角 R5,五块主板 3+2 双排面对面,第二排居中:
| X | Y | 旋转 | |
|---|---|---|---|
| CH1 | 5.0 | 85.5 | 0(接口边朝下) |
| CH2 | 76.5 | 85.5 | 0 |
| CH3 | 148.0 | 85.5 | 0 |
| CH4 | 40.75 | 5.0 | 180(接口边朝上) |
| CH5 | 112.25 | 5.0 | 180 |
(坐标是主板本体左下角,主板 67.09 × 44.66。)
为什么能这么省地方:小米8 主板的接口全部挤在同一条边上 ——
侧键 x 25.5 / J600 x≈23.8 / EDL x 42.6,45.4 / J1401 x 47.559.7,y 全部 < 8 mm。
所以每台手机只要一条 18 mm 的服务带贴着那条边,两排面对面就能共用中央通道:
y 130.16 ┬ CH1 CH2 CH3 (主板,正面朝天)
y 85.5 ┼ ─────── 接口边 ───────
│ 服务带 A:C8n1 / TP8n1,2 / C8n2~6 / J6n / U4n / J7n / U5n / U2n
y 67.5 ┼ ── 底层:J31 (62,67.5) · Hub (110,67) · J32 (158,67.5) ──
│ 服务带 B(同上,上下镜像)
y 49.66 ┼ ─────── 接口边 ───────
y 5.0 ┴ CH4 CH5 左右各空出 35.75 × 44.66 的口袋
左口袋放 J23 上游 USB-C + U31(3V3 LDO)+ U34(测温)+ R721/R722;右口袋暂空。
25.2 三条硬决定
- J31 / J32 排母在底层(layer 2)。 下板公头朝上,载板母座必须朝下。
⚠️ 「第 r 行对第 r 行」不能靠脑补两边的引脚表 —— 底层元件在顶视图里是镜像的。
pcb2_place.py --push会把载板侧 80 个焊盘的绝对坐标导出到.claude/pcb2-header-pads.json;下板放 J24/J25 时按同一装配坐标系 把 pin k 摆到同一个 (x, y) 即可,数值对上就一定插得上,不用推理。 装配坐标系取载板坐标系,下板 160×125 居中 → 下板原点 = 载板 (30, 5), 所以下板侧目标坐标 = 导出值 − (30, 5)。 - USB Hub(U32 + Y1 + strap + 去耦,共 26 件)也在底层,压在通道正中 (110, 67)。 顶层通道被两条服务带占满;而 Hub 若放进左右口袋,到最远那台的 D± 要走 200+ mm, 超过 USB2517I 手册要求的 6 inch(152 mm)。放中间后最长约 92 mm。 底层本来就要贴 J31/J32,不增加工序。 ⚠️ 底层元件落在两板之间那 13 mm 缝里 —— 布下板时别让 C2/C3(12 mm 电解)撞上。
- 35 个手机定位孔做 NPTH(Φ2.5,不金属化),立柱必须用尼龙。
主板那 7 个孔是金属化的、连着手机地。做成金属化孔 + 金属立柱 =
五台手机的地在载板上并成一根,4 A 回流会从专用的
P−针里跑掉一部分, 直接违反 §6.4「每路独立回流」。
25.3 ⚠️ 顶针封装:立创的焊盘会让侧键短路(本轮抓到的真错误)
立创给 C5221288(YTC1P-2510-01)的封装 SMD-1_BD2.0-H3.6 焊盘是 Ø2.5,
而顶针法兰只有 Ø2.0。单看没问题,按实测坐标密排就致命:
| 触点对 | 间距 mm |
|---|---|
| J603–J601 | 2.346 |
| J603–J602 | 2.333 |
| J601–J604 | 2.217 ← 最近 |
2.217 − 2.5 = −0.28 mm → 两个焊盘直接叠在一起,音量+ 会被永久按住。
原理图侧完全看不出来(网表是对的),只有 PCB 摆位的几何检查能抓到。
已自建封装 POGO-SMD1P_D1.9(个人库,器件 YTC1P-2510-01 D1.9 =
1c8e0ea1e66142a8860d6812b1dbe356):单焊盘 Ø1.9,净间距 0.317 mm,
过 0.2 mm 规则;法兰 Ø2.0 只比焊盘大 0.05 mm/边,回流照样自对中。
c4_site.py 已改用它,C4-SITE1~5 重生成、三道验证全绿、PCB 已重新导入。
教训写进 skill §9f:用实测坐标钉死位置的器件,摆位前先把焊盘直径和 实测最小间距对一遍,别等 DRC。判据 =
最小间距 − 焊盘直径 ≥ 设计规则净间距。
25.4 服务带的内容与排法(本体坐标,v<0 = 接口边外侧)
| 行 | v | 内容 |
|---|---|---|
| 1 | −3.2 | TP8n1(u21) C8n6(23.5) TP8n2(26) C8n2(31) C8n3(36.5) J6n(44) J7n(57.5) |
| 2 | −8.0 | C8n4(31) C8n5(36.5) R74n(41) U4n(45) C76n(49.5) U5n(57.5) R76n(61.5) R77n(64) |
| 3 | −11~−13 | C8n1(12, −11) C70n(39.5) U2n(45) C71n(49.5) C72n(52.5) R70n(55.5) |
排法的三条理由:① 要接排线 / 焊飞线的(P+P− 焊盘、EDL 座、BM24 座)全在行 1,
贴着手机边,飞线最短;② J7n 摆在 u≈57.5,正对主板 J1401(u 47.5~59.7);
③ C8n1 那颗 Ø10 电解摆到最左(u=12),那一段只有它,不跟任何东西抢地方。
pcb2_place.py 的本地检查有四项:位号齐全、不越框、分层重叠、
顶层元件不许压进主板投影。直插件(C8n1 / TP8n1,2)两层都算,
且顶层按罐体 Ø12.5 留、底层只按引脚焊盘留 —— 用同一个框会把 J31 误判成撞上 C811。
25.5 这一版还欠什么
| # | 待办 | 说明 |
|---|---|---|
| 1 | ✅ J23 方向定稿,位置已改(见 §25.6) | 方向判据两条,都不是算出来的:① 这个封装的 12 个信号焊盘在连接器背面、4 个屏蔽固定孔靠近口,所以口朝板内是错的;② 前端面比最外侧铜还往外 2 mm,焊盘框算不出来,是从渲染图量的(板框紫线 + 信号焊盘列左沿两点标定),得出「中心离前端面 5.134 mm」。位置 2026-09-04 深夜从左口袋改到右口袋:rot=90、中心 x=214.866,前端面仍与板边齐平 |
| 2 | ✅ Hub 26 件已逐脚对位手排 | 见 §25.6。原来是 3 mm 网格粗排 |
| 3 | ⬜ 设计规则 / 铺铜 / 布线 | 一根都还没布。⚠️ 载板已切 4 层(§25.6),pcb_rules.py 的差分几何可以照抄,但规则配置还挂在两层板能力集上,要先换掉 |
| 4 | ✅ 右口袋已用掉 | J23 挪过去了(§25.6)。左口袋现在只剩 U34/C760 |
| 5 | ⬜ 主板 7 个定位孔的孔径没量 | 载板现在开 Φ2.5。立柱销径要配主板孔径,卡尺量一下就定了 |
| 6 | ⬜ C801 高 16 mm,是载板最高件 | 外壳内高按它留(§24 那次已拍板照装) |
25.6 布线前的四处返工(2026-09-04 深夜,用户拍板)
这一轮不是加东西,是把上一版摆位里四个会咬人的地方修掉。 四处全是「原理图侧完全看不出来、几何包围盒检查也过」的那一类。
① 载板切到 4 层(2 层做不了)
转板过来默认两层。三条硬理由:
- 11 对 USB HS 差分要 90 Ω。 §10.1 的 W0.28 / S0.18 是按嘉立创四层 1.6 mm 叠层(L1-L2 介质 h=0.2104)算的。两层板的介质是整个 1.5 mm, 同样阻抗线宽要 2 mm 以上 —— 排不下,也没有参考面。
- 五路 4 A(合计 20 A) 没有内层电源面就只能靠外层大面积铜, 而顶底两面都摆满了元件。
- 两面都是元件面,地回流会被割得很碎。
叠层沿用下板,但层的角色是镜像的:
| EasyEDA id | 下板(§10.1) | 载板 | 为什么不一样 | |
|---|---|---|---|---|
| L1 | 1 | 信号(D± 走这层) | 信号:服务带、P+/P− 焊盘、U5n、U31 | |
| L2 | 15 | 完整地平面 | 电源面(分割灌铜) | |
| L3 | 16 | 电源面 | 完整地平面 | |
| L4 | 2 | 控制信号 | 信号:J31/J32、整个 Hub |
为什么载板要把地平面放到 Inner2 而不是 Inner1:载板的 U32 在底层,
所有长距离 D±(5 对下游 + 1 对上游)都从底层出发。底层的参考面是 Inner2 ——
Inner2 必须是完整地。反过来(Inner1 = 地)的话底层 D± 就以分割的电源面为参考,
直接违反 §10.1 那条「以完整地平面做参考」。
嘉立创四层 1.6 mm 标准叠层上下对称(L1-L2 与 L3-L4 都是 0.2104 mm 介质),
所以 W0.28 / S0.18 这组几何照搬即可,不用重算。
② J23 从左口袋挪到右口袋 —— 上游 D± 原来只剩 8% 余量
§25.2 选「Hub 压在通道正中」时只核了下游(最远 92 mm),没核上游。 J23 在左口袋 x=5、Hub 在 x=110,上游曼哈顿 140 mm, 而 USB2517I 手册的上限是 152 mm。
挪到右口袋之后(实测读回的焊盘坐标):
| 直线 | 曼哈顿 | |
|---|---|---|
| UP(J23 → U32) | 103.6 | 104.4 |
| USB1 → U51 | 44.7 | 57.0 |
| USB2 → U52 | 32.5 | 43.3 |
| USB3 → U53(最远下游) | 101.7 | 113.3 |
| USB4 → U54 | 57.2 | 66.9 |
| USB5 → U55 | 19.6 | 27.6 |
两头都进到 115 mm 以内。用户对上游口从哪一边出没有偏好,按走线最优定。
几何:rot=270 → 90(口朝 +X),中心 x = 220 − 5.134 = 214.866,
y = 62.0(让信号焊盘列 x≈212.4 正对 Hub 的上游脚行 y≈62.55)。
壳体前端面仍与板边齐平 —— 这是把 §25.5 #1 那条标定几何镜像过去,不是重新量的。
顺带:R717/R718(CC1/CC2 的 5.1k 下拉)原来被 Hub 的网格排法捞走了,
摆在底层、离 J23 105 mm。CC 脚挂这么长的残桩没有意义。
现在贴着 A5/B5 焊盘、和 J23 同在顶层,实测 1.59 mm。
R721/R722(上游 VBUS 分压)原来在左口袋陪着老 J23 —— 方向是反的。
分压要跟着高阻端走:UP_VBUS_DET 是高阻节点,要短;VBUS_UP 是低阻,
长跑无所谓。现在移到 J31 pin36 边上(底层,实测 3.27 mm)。
③ U31 就近 Hub —— §22.7 写了但没落实
§22.7 白纸黑字:「§9.5 要求的『就近 Hub 供电』是 PCB 摆位约束,与分页无关」。
上一版 U31 在左口袋 (25, 42),离 Hub 90 mm。
现在 U31 (105, 71) / C736 (98, 71) / C737 (112.5, 68.8),
顶层 y 67.5~72.5 那条横带原本是空的(J31/J32 在底层,服务带 A 从 y 72.5 起)。
实测 U31 的 3V3 输出脚到 U32.pin64 = 8.62 mm。
④ Hub 26 件从网格粗排改成逐脚对位手排
U32 是 QFN-64,脚距 0.5 mm,而 0402 件本体 0.54 mm 宽 —— 一个脚一个件地排是排不下的。所以每条边分两圈(A 圈 6.3 mm、B 圈 8.0 mm), 件按 1.2 mm 间距错开。手排相对网格排法真正多做的事是让出三条通道:
| 通道 | 位置(相对 Hub 中心) | 给谁 |
|---|---|---|
| 西侧扇出 | x < −4.45,y −3.8~+1.8 | 五对下游 D±(10 根),整条左边不放件 |
| 南侧竖井 | x −2.4~−0.2,y < −4.45 | XTAL1/2 下到 Y1 + UP_DP/DM 南下再西行 |
| 晶振窝 | (−4.2, −9.2) 一带 | Y1 + C740 / C741 |
A 圈 y=−6.3 上 C743(x−2.65) 与 C745(x+0.05) 之间那 2.16 mm 就是南侧竖井,
四根线(XTAL 用 0.2、UP 用 0.28)刚好过得去。
实测的对位距离(读回焊盘坐标算的,不是脚本里的意图值):
| 件 | 对哪个脚 | mm | |
|---|---|---|---|
R708 |
63 RBIAS | 1.43 | 精密偏置,全簇最近 |
C743 |
62 VDD18PLL | 1.43 | |
C742 |
25 VDD18 | 1.51 | |
C744/745/746/749/750 |
64/57/52/24/46 +3V3 | 1.46~2.30 | |
C747/C748 |
5/10 +3V3 | 3.55 / 3.10 | 夹在 D± 中间,只能放到扇出区之外 |
R712/R715/R714/R719/R709 |
42/56/54/40/44 | 1.42~1.86 | |
R711/R716/R720 |
41/43/45 | 3.1 | B 圈,纯配置下拉/上拉,够 |
Y1 |
61/60 XTAL | 4.95 / 5.76 | 见下 |
C740/C741 |
Y1 的两个端子 | 1.48 / 1.83 |
晶振离芯片 5~5.8 mm 是通道的代价,不是疏忽。 UP_DP/DM 必须从南边出去再西行,
Y1(3.6 × 2.9)放不进它们的竖井,只能退到西南。24 MHz 下这个距离有充分余量,
真正要紧的「负载电容贴着晶振端子 + 地回路短」已经做到(1.5~1.8 mm)。
C747/C748 那 3.1~3.5 mm 同理:pin5 / pin10 夹在十根 D± 中间,
件放进去就堵死扇出。这两颗靠 Inner2 的 +3V3 灌铜就近打孔补偿,不靠这段走线。
⑤ 载板自己的 M3 孔压在手机上(pcb2_clear.py 抓到的真错误)
四个 M3 孔 (8,8)/(212,8)/(8,127)/(212,127) 是在五个手机位拍板之前放的,
之后没复核。上面两个落在 CH1 / CH3 的手机本体投影里,
其中 (8,127) 的 Ø6 焊盘和 CH1 的定位孔 P1H2 直接重叠 0.93 mm。
这个错误 pcb2_place.py 的包围盒检查抓不到 —— 定位孔和 M3 孔都是自由焊盘,
不属于任何元件,根本不在它的检查范围里。
新写的 .claude/pcb2_clear.py 按焊盘真实形状两两算净间距,才把它翻出来。
板顶那条 y 130.16~135 的 4.84 mm 缝里塞不下 Ø6 焊盘,
三个手机横排也已经把 x 方向占满(5+67.09+4.41+67.09+4.5+67.09+4.91 = 220.09),
所以上面两个孔只能退进中央通道 / 右口袋:
MH = [(8, 8), (212, 8), (7, 60), (213, 45)]
pcb2_place.py 已加断言:M3 孔不许落进任何手机本体投影,
也不许离 35 个定位孔中的任何一个近于 Ø6/2 + Ø2.5/2 + 0.2 = 4.45 mm。
⚠️ 副作用,是外壳设计要回答的问题:CH1~CH3 那一排(板子上半部分) 最近的安装点在 45 mm 之外,220 mm 跨距上没有支撑。 三条出路:外壳做侧边导轨托住上沿 / 在中央通道
(127, 67)加一个中跨孔 (实测那一块顶底两层都是空的)/ 缩板。目前没做决定。
新写的检查脚本:.claude/pcb2_clear.py
/c/Python314/python .claude/pcb2_clear.py [--min 0.2] [--top 40]
按焊盘真实形状(RECT/OVAL 按轴对齐矩形、真圆按圆心距、POLYGON 按点表包围盒) 两两算净间距,分「同一封装内」(只报负间距)与「跨元件」(判据 0.2 mm)两类。
为什么不用 EasyEDA 自己的 DRC:没布线时它会刷出 1200+ 条「连接性错误」,
真正的间距错误埋在里面看不见(成因见 drc_read.py 的注释)。
写这个脚本踩到的两个 API 陷阱(已写进 skill §9g / §9h):
- 焊盘归属哪个元件,只能靠 primitiveId 前缀。
pcb_PrimitivePad.getAll()回来的对象上没有getState_ParentComponentPrimitiveId(TypeError: not a function);用 try/catch 包起来的话它会静默地把所有焊盘 都当成自由焊盘,看不出错。真正的判据是 「焊盘的 primitiveId 以父元件的 primitiveId 为前缀」—— 元件 C701 =356da09e850d14fa,它 1 脚 =356da09e850d14fae16。 (坐标匹配也不行:有浮点尾巴,且 POLYGON 焊盘的 x/y 根本不是形心。) - ⚠️ 焊盘的 rotation 是弧度,元件的 rotation 是角度。
pcb_PrimitivePad.getState_Rotation()回来1.5707963267948963(= π/2),pcb_PrimitiveComponent.getState_Rotation()回来90。 按角度判rot % 180 == 90的话,所有旋转过的矩形焊盘长短边都会被认反。 实测后果:J23 那 12 个 0.30 × 1.30 的信号焊盘被误判成两两重叠 0.30 mm (真实净间距 +0.20 mm),13 条假报。 这类错误最阴的地方是只错一半 —— 不旋转的焊盘全对, 所以看上去像「某个封装有问题」,而不像「换算错了」。
这一轮的验证结果
| 检查 | 结果 |
|---|---|
pcb2_place.py 本地四项(位号齐全 / 不越框 / 分层重叠 / 顶层不压主板投影) |
✔ 161 个元件,顶层 133 / 底层 28 |
| M3 孔断言(不压手机投影 / 离定位孔 ≥ 4.45 mm) | ✔ |
pcb2_clear.py 跨元件焊盘净间距 ≥ 0.2 mm |
✔ 814 个焊盘全过 |
pcb2_clear.py 同封装内负间距 |
✔ 0 对 |
| 铜层数 | ✔ 2 → 4(id 1 / 15 / 16 / 2 启用) |
截图 PCB2-carrier-v2.png(全板)。
25.7 布线前置:设计规则、地平面、两个中跨孔(2026-09-05)
这一轮做的是「布线之前必须先有的东西」,一根走线都还没画(原因见末尾)。
① 载板设计规则整套下发(.claude/pcb2_rules.py)
转板过来一直挂在 JLCPCB Capability(Two Layers Board) 上,而板子早就是四层了。
做法完全照抄下板的 pcb_rules.py(那边的文件头是唯一说明书,两个 config 形状的坑
和「别去 GUI 换配置下拉框」那条都适用),只有三处不同:
| 下板 PCB1 | 载板 PCB2 | |
|---|---|---|
| 差分对 | 7 对 | 11 对 |
| 功率线宽档 | 2 档(PWR4A / PWR12V) | 3 档(PWR4A / PWR5V / PWR1A) |
| 线宽指派 | 12 个网络 | 12 个网络 |
为什么是 11 对:载板上每一路 D± 被 ESD 器件 U5n 切成两段 ——
USBn_DP/DM(U32 → U5n,长段,走底层)和 USBn_DPJ/DMJ(U5n → J7n,约 5 mm,走顶层)。
两段都要建对,否则短段会按普通信号布、在 ESD 器件那头留一截不受控阻抗。
5 长 + 5 短 + UPSTREAM = 11。载板没有 DEBUG 那一对(ESP32 在下板)。
几何 W0.28 / S0.18 直接照搬不重算:嘉立创四层 1.6 mm 标准叠层上下对称 (L1-L2 与 L3-L4 都是 0.2104 mm 介质),载板虽然层角色是镜像的, 底层 D± 以 Inner2(完整地)为参考,介质厚度与下板顶层 D± 以 Inner1(地)为参考完全相同。
⚠️ 顶层那 5 段 *J 的参考面是 Inner1,也就是分割的电源面,不是完整地。
段长只有约 5 mm、又紧挨 ESD 器件,可以接受;但要保证每个 U5n↔J7n
下方的 Inner1 是同一块铜,别让分割缝横穿这 5 mm。
✅ 2026-09-05 Inner1 铺完后已实测(.claude/inner1_diffref.py,把两根线的包围盒
外扩 1 mm 当窗口,逐窗口栅格化 Inner1 上所有铜面):五段窗口里都只有 GND-INNER1
一块铜、一个连通域、覆盖 100%(连反焊盘的洞都没有)。五块 VOn_P 岛离得最近的
是 VO4(右沿 x=100)对 CH1 的窗口(x 57.65~64.45),差着一整个服务带。
⇒ 这条约束是满足的,不是「可以接受」而已。改岛的边界或挪 U5n/J7n 之后要重跑这个脚本。
三档功率线宽的依据(IPC-2221 外层 1 oz,ΔT≈20 °C):
| 规则 | 默认 / 最小 | 挂哪些网络 | 依据 |
|---|---|---|---|
PWR4A |
1.5 / 0.3 mm | VO1_P~VO5_P |
每路 4 A |
PWR5V |
1.2 / 0.3 mm | +5V |
§9.4 最坏 2.8 A(1.2 mm 可载 3.6 A) |
PWR1A |
0.6 / 0.25 mm | VBUS1~5、+3V3_HUB |
下行每口 0.5 A;Hub 3V3 最坏 0.42 A |
最小值一律留到 0.25~0.3 mm,理由同 §10.1:规则是按网络生效的,
+5V / VBUS 上挂着 0402 去耦(焊盘才 0.57 mm 宽),卡大线宽会让几十个焊盘
扇不出去、刷出一屏假 DRC。载流靠灌铜保证,不靠 DRC。
--check 审计十一项全过:铜层数 4 / 四层板能力集(最小线宽 0.102、过孔 0.30-0.20、
含 0.5 oz 内层条目)/ 三条线宽规则存在 / 差分几何 W0.280 S0.180 /
非差分间距下限 0.2000 / 对内 USBPAIR 0.15 / 11 对差分 / 12 个线宽指派 / 11 条对内间距规则。
② Inner2 整板地平面已铺好
一块 GND-INNER2,板框内缩 0.5 mm 的 R5 圆角矩形,preserveSilos=false,
重建后 81 块填充,已存盘。脚本是 .claude/pcb2_pour.py(--push 一气跑完:
清旧 → 建边框 → 重建 → 确认 → 存盘,中途不能停,理由见下面第 3 条)。这是载板上唯一不依赖任何未决事项的铜面 ——
Inner1 的分割电源面当时要等排母定了才能划 —— 排母 2026-09-05 定稿并落到 PCB 上(§22.3f / §25.9),
Inner1 已于同日铺完,见 §25.11。
③ 两个中跨 M3 孔(用户拍板,§25.6 ⑤ 那条待办到此关闭)
孔位不是拍脑袋定的,是拿真实焊盘 + 五个 Ø12.5 电解罐体做网格搜索找出来的 (判据:孔中心到任何铜/罐体的净间距,NPTH Ø3.2 算):
| 候选窗口 | 位置 | 净间距 | |
|---|---|---|---|
| CH1|CH2 缝下 | (76.6, 80.1) | 5.28 mm | ← 选它 |
| CH2|CH3 缝下 | (148.1, 80.1) | 5.28 mm | ← 选它 |
| 走廊正中 | (127.9, 67.5) | 2.90 mm | 窄一半,且离要支撑的地方远 18 mm |
选 y≈80 而不是走廊正中的两条理由:
- 要支撑的是 y 85.5~130 那一排手机,80.1 离它只有 5 mm,67.5 差了 18 mm。 插 BM24 原厂排线时的按压力正好作用在这个无支撑的上半部分。
- 走廊正中被
C811/C831两个 Ø12.5 电解罐夹着 (罐体分别占 y 68.2580.75 和 y 54.4166.91),只剩一条 6.9 mm 高的缝; 而三台手机之间那 4.41 mm 的 x 向空档一路通到 y 84,宽敞得多。
⚠️ y 再往上就被顶针 J48 / J52(y 87.96,CH2/CH3 的侧键触点)逼住:
y=83 时净间距掉到 2.41,y=84 只剩 1.41。80.1 是这个窗口的最宽处。
规格与原有四个一致:Ø3.2 孔 + Ø6 焊盘 + 接 GND(金属化,锁到外壳等于把载板地 接到机壳 —— 这和 §25.2 决定 3「手机定位孔必须 NPTH」不冲突,那一条防的是 五台手机的地在载板上并成一根,载板自己的地本来就是一个网络)。
pcb2_clear.py 重跑:816 个焊盘(原 814 + 2),跨元件净间距全过。
截图 PCB2-carrier-v3.png(全板)/ PCB2-midspan-mh.png(MH5 附近)。
④ 查清一个必须记住的事实:J31/J32 的占位封装是 SMD,排距 4.80 mm
实测回读 J31 的 40 个焊盘:20 列 × 2.54 mm 列距,2 行 × 4.80 mm 排距, 全部在 layer 2(底层) —— 不是 layer 12,也就是说它是贴片焊盘,不是插装。
对照两边的封装名:
| 器件 | 封装 | |
|---|---|---|
| 下板公头 J24/J25 | C9900001574 2.54 双塑双排针 2*20P L17MM |
HDR-**TH**_40P-P2.54-V-R2-C20-**S2.54**-1 |
| 载板母座 J31/J32 | C9900025309 双排插装排母 2*20 40PIN 2.54 间距 |
HDR-**SMD**_40P-P2.54-V-F-R2-C20-**LS6.7** |
本节写于换件之前,两颗都已作废(2026-09-05 →
C55020601+C5307344,见 §22.3f)。 下面这两条结论仍然有效,而且正是换插装件的直接理由,所以整节保留。
4.80 mm 排距本身不是错:贴片排母的触点在壳体内仍是 2.54 间距,
焊脚是鸥翼状往外掰的,LS6.7 就是两排焊脚外沿的跨距(4.80 + 焊盘长 ≈ 6.7)。
所以它和 2.54 的公头能对插。
真正的问题有两个:
- 器件名写着「插装」,封装却是 SMD。 立创的封装数据在这个工程里已经错过一次 (§23.1 的 BM24 焊盘编号)。选型时以封装名和实际焊盘为准,别信器件名。
- 贴片排母承 5 路 × 4 A = 20 A、还要反复插拔,焊脚的机械保持力和接触电阻 都不如插装件。§22.2 里「三针并联接触电阻约 5 mΩ」的估算是按插装件写的。 换真件时优先选插装(TH)排母。
⚠️ 换件之后 80 个焊盘会整体移位(排距从 4.80 变成插装件的 2.54, 壳体宽度和定位柱也会变),而它们正压在要铺电源面的走廊正中。 这就是这一轮没有继续铺 Inner1、也没有开始布线的原因(用户 2026-09-05 拍板: 先停下,等排母选定再动布线)。2026-09-05 排母已定稿并实施完毕,见 §25.9。
这一轮暴露出来的四条 EasyEDA 坑(已写进 skill §9j~§9l)
- 铺铜优先级是「数字小的先铺、占地盘」,而不是反过来 ——
下板
pcb_pour.py里 GND=1 / 电源岛=5 的写法是反的(那边铜面从不重叠所以没出事)。 create()的pourPriority参数不生效 —— 优先级是按层、按创建顺序从 1 编的。 ⚠️ 别拿modify(id, {pourPriority})去补设:不生效,还会把客户端弄卡死(见下条)。 ✅ 正确做法是靠创建顺序:电源岛先建(拿小数字、赢),GND 底填最后建。 2026-09-05 在本板 Inner1 上做了对照实验:先建的 12×12 岛完整活着, 后建的 30×30 底填多出一个环(洞),几何相同但后建的那块被吃得一点不剩。pcb2_pour.py的plan()顺序就是优先级,--push会回读断言。- 「重建所有」点了没反应 = 客户端卡在后台任务上(窗口底部一条 0% 进度条;
健康时那个 DOM 扫描返回空数组,判据很干净)。
location.reload()之后一次就通; ⚠️ 重载会丢掉重载前建的铺铜边框,即使 save 过,所以--push必须一气跑完。 ⚠️ 而location.reload()会被「文档有未保存改动」静默挡掉 —— 调用返回成功、 标签栏和windowId都不变。可靠顺序是:关对话框 → 删掉刚建的边框 →save()→window.onbeforeunload = null→location.reload(true)→ 轮询windowId直到它变掉。 - 每个下发脚本必须自己
openDocument—— 这一轮就因为上一条命令开了 PCB1, 把下板的 14 块铜面重铺并存了盘(无损失,但两边返回值都看着正常, 只有铜面名字能看出打错了对象)。
另外记一条不是坑的正常行为:preserveSilos=false 时,铺铜区域里没有本网络的
焊盘/过孔,整块会被当孤岛删光 —— 边框还在、getAll() 数得到,但填充是 0。
所以扇出必须排在铺铜之前。
25.8 载板 GND 扇出(2026-09-05)—— 顺带查出 BM24 的一个硬约束
Inner2 整板地平面铺好之后,它其实只靠 20 个直插焊盘吊着
(五路的 C8n1 负极 + TP8n2、J23 的四个屏蔽脚、6 个 M3),
另外 222 个贴片 GND 焊盘根本没连到平面上。所以铺完铜必须接着做扇出。
脚本 .claude/pcb2_fanout.py —— 复用下板 pcb_fanout.py 的规划器,只换板子常量。
结果
| GND 贴片焊盘 | 222 个 |
| −33(当时排母未定)→ 2026-09-05 换成直插件后不再需要扇出,通孔脚自己就是过孔(§25.9) | |
| 实际目标 | 189 个 |
| 大焊盘走盘内过孔阵列 | 11 个焊盘 / 85 个过孔(U32 的 4.8×4.8 散热盘一个就占 25 个) |
| 普通焊盘旁打过孔 | 125 个(+125 条出线,中位 0.63 / 最长 1.77 mm) |
| 落盘合计 | 210 个过孔,全部 net=GND,Ø0.610 / 孔 Ø0.305 |
| ⬜ 打不下的 | 53 个,见下 |
出线分布 105 条顶层 + 21 条底层 —— 底层那 21 条是 Hub 簇和 J31/J32 之外的底层件。
⚠️ 这里改了
pcb_fanout.py两处只在载板上才会暴露的写死前提(下板行为不变): ①todo原来只收layer == L_TOP的焊盘 —— 下板 391 个元件全在顶层所以没事, 载板两面都是元件面,改成模块常量FANOUT_LAYERS(载板覆盖成(1, 2)); ② 下发 JS 里出线的层写死成1—— 载板底层焊盘的出线会被画到顶层去、悬空且看不出来。 改成按焊盘自己的layer走。
⚠️ 打不下的 53 个:51 个是五颗 BM24 的 GND 脚,这是几何上不可能,不是脚本的毛病
每颗 J71~J75 有 13 个 GND 脚,五颗共 65 个,只有 14 个(最外侧那些)打得下过孔。
算一下就知道为什么:
BM24 信号焊盘 0.1803 x 0.4801 mm,间距 0.35 mm(§24 自建封装,实测回读)
相邻焊盘边缘净距 = 0.35 − 0.18 = 0.17 mm
Ø0.6 过孔要离别的焊盘边缘 = 0.3 + 0.2(安全间距) = 0.50 mm ⇒ 塞不进去
两排之间的中间通道倒是够(两排 y = ±1.06,焊盘高 0.48 ⇒ 内边缘 ±0.82, 通道净高 1.64 mm > 2 × 0.5),但通道里过孔彼此要 0.6 + 0.2 = 0.8 mm 中心距, 而脚距只有 0.35 —— 三个脚才放得下一个过孔,且引线还要横穿别的脚。
所以 0.35 mm 间距的连接器不能靠「旁边打过孔」扇出,只能逃逸布线: 前排(y 81.44)一律往南出、后排(y 83.56)一律往北出 (同一排相邻焊盘之间只有 0.17 mm,连 0.102 的最小线宽都塞不下, 横向穿不过去,每个脚只能直着离开连接器),出了焊盘阵列再打过孔。
这属于布线阶段的活,等排母定了连同 D± 一起做。打样前必须确认这 65 个 GND 脚 真的都接到地平面上了 —— USB 的回流路径全靠它们。
顺带记一条工作顺序
pcb_fanout.py 文件头那条「布局一动就要 --clean → 重新 dump → `--push``,
三步不能省也不能并」对载板同样成立。换排母 = 布局变动(2026-09-05 已按这个顺序重来过一遍,§25.9),
这 210 个过孔届时要全部清掉重来 —— 脚本才是这一轮的产出,过孔是副产品。
扇出之后的 DRC 基线(2026-09-05,下一轮照着这个数比对)
pcb_Drc.check() 跑完,DRC 面板:
全部 (551)
同封装内间距错误 (115) 贴片焊盘 到 贴片焊盘 (115) ← 封装自带,永远修不掉,见下
连接性错误 (436) GND(107) +5V(15) VBUS1~5(各6) +3V3_HUB(33) ...
间距错误 —— **0 条** ← 210 个过孔 + 126 条出线一条没违规
「间距错误」是 0,说明这一轮落的铜是干净的。另外两支都是预期之内:
-
连接性错误 436 条 = 还没布线。GND 那 107 条里,51 条是 BM24 的 GND 脚、 33 条是故意没扇的 J31/J32,剩下的是平面被分成的几个孤立块。
-
同封装内间距错误 115 条 = 封装自带的引脚间距,不是设计错误,成因逐个核过:
位号 焊盘对 最小净间距 成因 J71~J75(BM24-50DS)228 0.170 mm 0.35 间距 − 0.18 焊盘宽,见 §24 U32(USB2517I QFN-64)4 0.125 mm 0.5 mm 脚距 J23(USB-C)3 0.200 mm 正好卡在判据边界(浮点) 安全间距规则全表抬到了 0.2 mm(§25.7 ①),比这几颗连接器自己的脚距还严, 所以必然报。三个数都在嘉立创四层工艺下限(0.1 mm)之上,可以打。
⚠️ 别去调低全局安全间距来「修」它们 —— 那等于把全板的保护一起放掉。 EasyEDA 已经把这一支单列成「同封装内间距错误」,和跨元件的「间距错误」是分开的。 看 DRC 只看「间距错误」那一支;「同封装内」那一支确认成因之后就忽略。
22.3f 板对板连接器定稿(2026-09-05,取代 §22.2 / §22.3d 里的两个占位)
用户 2026-09-05 授权「你来定选型」。结论如下,§22.2 与 §22.3d 里凡是写 C9900001574 /
C9900025309 的地方一律以本节为准。
| 型号 | 立创 | 关键参数 | |
|---|---|---|---|
| 下板 J24/J25 公头 | AZ-PZ2.54-V11-2*20P(宝讯 BXCONN) | C55020601 | 2×20 / 2.54 / 直插;塑高 2.5、配合针长 6、端接针长 3;3 A/针、触头镀金;−40~+105 °C |
| 载板 J31/J32 母座 | PC104-2*20(洲日 ZHOURI) | C5307344 | 2×20 / 2.54 / 直插;塑高 10.5;2.5 A/针;行距 2.54;−40~+105 °C |
对插高度 = 2.5 + 10.5 = 13.0 mm,由塑料对塑料定位。 配合针长 6 mm 插进 10.5 mm 的腔体,PC/104 母座是通孔式(针可以一路穿过去), 所以针不会先顶死、高度确实由塑料决定。
为什么是这一对
-
高度是唯一的硬约束,而这是库里唯一够的组合。 把 EasyEDA 的立创库里 「间距 2.54、标了塑高」的排母全扫了一遍(
lib_Device.search,十几个关键词):塑高 料号 10.5 mm C5307344PC104-2*20← 选它 10.5 mm C5307345PC104-2*40尺寸不对(§22.2 已定两条 2×20) 8.5 mm C55020541/C5124634/C9900025309(贴片)对插只有 11 mm,够不到 8.3 mm C351652.54-2*20P母长PC104同上 8.5 mm 那一档配 2.5 mm 塑高的公头只有 11 mm,差 2 mm。没有「加高排针」能补 —— 库里 2.54 的双排排针塑高全是 2.5。
-
从贴片改成插装,这是比高度更重要的一处改善。三个好处:
- 20 A 总电流 + 反复插拔,靠的是插装脚的保持力;§22.2 里「三针并联接触电阻约 5 mΩ」 本来就是按插装件估的。
- 80 个通孔脚本身就是过孔,直接把
VOn_P/+5V/ 33 个GND连到 Inner1/Inner2。 §25.8 里被迫跳过的「J31/J32 那 33 个 GND 脚扇不出去」问题自动消失。 - 行距从占位件的 4.80 mm(贴片鸥翼脚外掰)回到规范的 2.54 mm。
-
电流:取两者较小值 2.5 A/针。
VOn_P每路 3 针并 4 A = 1.33 A/针(余量 47%);+5V3 针 2.8 A = 0.93 A/针;GND33 针。都很宽裕。 -
PC/104 本来就是板间堆叠总线连接器,机械设计目标就是「两块板叠起来还要能反复拆装」, 和本项目的用法完全一致。
这个决定带出来的三条硬约束
-
⚠️
C2/C3的罐高必须 ≤ 11.5 mm(13.0 − 1.5 mm 余量)。 现在的C22383480是立创的通用「470uF 25V」,商城页面一个参数都没标, §22.3d 那个「约 12 mm」是估的、不是查来的。反正它要挪(见下),重选时把高度定死。 Ø8 × 11.5 是 470 µF/25 V 的标准罐,好买。 ⚠️ 别顺手换成聚合物电容(库里C48970541Ø8×11 / ESR 20 mΩ 看着更好)—— 输入体电容的 ESR 正是阻尼输入侧电缆 LC 的东西,和 §6.2 输出侧同一个道理, 换成低 ESR 会让输入滤波欠阻尼。§3.4 要的是「低 ESR 铝电解」,不是聚合物。 -
⚠️
C2/C3/C4/C5/C6必须挪 —— 它们压在 J24 要占的位置上。 载板 J31 中心 (62, 67.5),下板坐标 = 载板 − (30, 5) ⇒ J24 中心 (32, 62.5), 本体 53.34 × 5.08 mm ⇒ 占 x 5.3359.96 / y 58.6765.04。实测重叠:重叠 C2(17, 63) Ø88.00 × 5.08 mm C3(26, 63) Ø88.00 × 5.08 mm C4/C5/C6(33, 60/63/65.5)3.20 × 1.29 / 2.50 / 0.79 mm J25 中心 (128, 62.5) 那一侧没有冲突。
-
⚠️ 两板之间没有可用的立柱位。 载板 6 个 M3 里只有两个中跨孔映射进下板内 (下板 (46.6, 75.1) / (118.1, 75.1)),而实测那两处在下板上是占着的 (前者甚至和焊盘重叠 0.27、和过孔重叠 1.03 mm)。 所以两板间距只能由连接器的塑料对塑料保证,没有机械兜底。 下板重排接口区时若能顺手让出这两个位置,就能加两根 13 mm 立柱把间距定死 —— 值得做。
到货必须核的两件事
- 触头镀层:
C5307344商城没标镀层(只写了「触头材质:黄铜」)。 PC/104 一般是镀金的,但没写就得实物确认 —— 20 A、反复插拔,镀锡会随插拔次数劣化。 - 母座腔体深度 / 配合针长:确认 6 mm 的针插到底时两个塑料真的贴合 (而不是针先顶到腔体底)。量一次对插后的板间距,应为 13.0 mm。
换件要改的地方(实施清单)
| 文件 | 改什么 |
|---|---|
.claude/eda-parts.json |
✅ 已加 C55020601 / C5307344,旧两颗标了「已作废」 |
.claude/p5_btb.py |
✅ 公头器件换 C55020601;引脚公式 r / 41−r → 2r−1 / 2r;ROW0 100 → 95 |
.claude/c1_conn.py |
✅ 母座器件换 C5307344;引脚公式与 ROW0(95)都不用动 |
| P5-BTB / C1-CONN 两页 | ✅ 已重新生成:verify_sch 两页 PASS(C1-CONN 带 --nc c1-nets-nc.json)、xpage 0 漏接、port_audit 下板 513 / 载板 330 全部可疑 0 |
| §22.2 逐针表 | ✅ 已按新编号重写(1/3/5 而不是 1/2/3),两块板共用一张表 |
.claude/pcb2_place.py |
⬜ HDR 摆位不变(中心 (62,67.5)/(158,67.5)),但焊盘从贴片 4.80 行距变成通孔 2.54 行距 |
| 载板 PCB | ✅ 已走完:clean2() 清过孔 → pcb2_place.py --push → pcb2_parts_dump.py + dump_pads.py → pcb2_fanout.py --push(SKIP_HDR=False)→ pcb2_pour.py --push。逐项见 §25.9 |
实测到的符号几何(2026-09-05,两颗一起量的)
公头 C55020601 / 母座 C5307344 —— 两颗完全一样
20 行,行距 10,左列 x = cx−30,右列 x = cx+30
第 1 行 y = cy + 95(不是公头原来那颗的 +100 ⇒ p5_btb.py 的 ROW0 要改)
第 r 行 = 引脚 2r−1(左)/ 2r(右)
量法:在 C1-CONN 上临时各放一颗、getAllPins() 读回 40 个引脚号与相对坐标,
同一次调用的 finally 里删掉(前后元件总数都是 69,无残留)。
✅ 编号体系已实测:§22.2 那个编号陷阱换件之后消失了
两个新符号各在 C1-CONN 上临时放了一次、把引脚号与坐标读回来(读完同一次调用里删掉,
verify_sch + xpage 复核过页面无残留)。结果两颗完全一致:
20 行 x 左右两列,列 x 偏移 ±30,行距 10
第 1 行: 引脚 1(左) / 2(右) 第 2 行: 3 / 4 ... 第 20 行: 39 / 40
即两颗都是 IDC 奇偶式:第 r 行 = 引脚 2r−1(左)/ 2r(右)。
而旧的一对是两套不同的编号(下板 DIP 式 第 r 行 = r / 41−r, 载板 IDC 奇偶式 第 r 行 = 2r−1 / 2r),§22.2 专门为此写了一节警告 「只能按行对,不能按引脚号对」。换件之后两块板从此同一套编号,这条陷阱自动消失。
⇒ p5_btb.py 的引脚公式要从 r / 41−r 改成 2r−1 / 2r;
c1_conn.py 的公式不用动(本来就是 2r−1 / 2r)。
两边仍然共用 p5_btb.py 那张按行组织的表,事实来源不变。
⚠️ 但 PCB 上那一条还在:符号编号一致 ≠ 第 r 行真的对上第 r 行。
公头在下板顶层、母座在载板底层,底层元件在顶视图里是镜像的 ——
pcb2_place.py --push 导出的 pcb2-header-pads.json 仍然是唯一靠得住的对位依据,
下板照那 80 个坐标摆,布板时实打实核一次。
25.9 换件落到载板 PCB 上(2026-09-05 夜)
§22.3f 定的 C55020601 + C5307344 在这一轮走完了从原理图到 PCB 的整条流程。
结论:能换,而且换完 DRC 和换件前的基线一模一样(间距错误那一支 115 条,
全是 J71~J75/U32/J23 封装自带的引脚间距,见 §25.8 末尾)。
导入变更只有 14 条
C1-CONN 整页是脚本重画的,7 个元件的 UUID 全新 ⇒ 每个一条「移除元件 + 增加元件」。 没有网络层面的变更,说明两页的网表在换件前后完全等价(这正是想要的: 换的是封装和引脚编号,不是电路)。
⚠️ 对话框里的 「包含设计规则」必须保持不勾 —— 勾上会拿原理图侧的规则覆盖
pcb2_rules.py 下发的那 11 条。这次核过了是不勾的。
换成通孔件逼出来的连锁改动:五个 Ø10 电解整体上移 2.5 mm
这是换件真正的代价,而且原理图侧完全看不出来:
贴片排母只占底层,所以 J31/J32 从来没和顶层的东西打过架。 换成直插之后顶层也占位(40 个通孔脚的焊盘区 50 × 4.24 mm), 而中央走廊在那两条带上正好被两排电解夹住: 上排三站的罐底 y = 68.25、下排两站的罐顶 y = 66.95,中间只剩 1.30 mm。
三条出路里只有一条走得通:
| 方案 | 结论 |
|---|---|
| J31/J32 往下挪 | ✗ 下面 3 mm 处是下排各站的行 3(U27/C704 等,y ≤ 63.91),窗口 0.7 mm 不够 |
| J31/J32 往左右挪躲开罐子 | ✗ J31 可以(左移 5 mm 就避开 C811),J32 不行 —— 左移会撞底层的 Hub 簇,右移出板 |
| 把五个罐子往手机那侧收 | ✅ 罐体在服务带里 u 5.75~18.25 这一段是独占的(行 1/2/3 的件都从 u=21 起),v 可以一直收到「不进手机投影」为止(v ≤ −6.25) |
BAND['c1'] 的 v 从 −11.0 改成 −8.0(和行 2 齐平):
| 罐体边 → 手机板边 | 3.00 mm(keep-out 边 1.75 mm) |
| keep-out 边 → J31/J32 焊盘 | 1.63(上排)/ 1.43(下排)mm |
| 实测可行区间 | v ∈ [−9.0, −6.75] 本地四项检查全过 |
顺带的好处:罐子离手机的 P+/P− 焊盘(v = −3.2)更近了 2.5 mm,
§6.3 那一组电容的回路更短。
通孔脚自己就是过孔,§25.8 的一条待办直接消失
pcb_fanout.one_net() 的 todo 本来就写着 not p['hole'] —— 通孔焊盘一律不进扇出清单。
所以 J31/J32 那 33 个 GND 脚不需要扇出,SKIP_HDR 关掉即可,
§25.8 里「排母的 33 个 GND 脚扇不出去」这条待办随换件一起关闭。
换件后重跑的结果和换件前完全一致:210 个过孔、失败 53 个(BM24 那 51 个 + C749 + 1)。
Inner2 地平面:81 段 → 213 段
重铺之后填充段数从 81 涨到 213,包围盒仍是整板 (0.6, 0.6)~(219.4, 134.4)。 涨的原因是那 80 个 2.54 间距的通孔在内层开了两条反焊盘带 (Ø1.7 焊盘 + 0.2 净距 ⇒ 相邻反焊盘之间只剩 0.44 mm 的铜网)。 平面没有被切断(网还在),但Inner1 的电源岛不要指望从排母底下横穿, 颈宽要绕着这两条带走。
这一轮踩到的三个坑
pcb2-parts.json不能在元件摆好之后随便重抓 —— 焊盘的x/y跟着元件转, 但pad数组里的 w/h 不转(方向记在pad.rotation上)。摆好之后直接抓, 得到的是「位置转了、尺寸没转」的四不像包围盒,pcb2_place.box()再按 rot 翻一次 ⇒ 凭空报出 12 条假问题(手排的 0402 互相重叠、J23 越框)。 新脚本.claude/pcb2_parts_dump.py把焊盘位置反转回元件本地系再存, 和「刚导入、全是 rot=0」时抓的那份等价。pcb_fanout.clean()在载板上是破坏性的 —— 它删「layer !== 11 的所有导线」。 下板除板框外没有别的线所以没事;载板上有 丝印 50 + 装配 100 + 文档 20 = 170 条 会被一起删光,DRC 和几何检查一条都不报。 ⇒pcb2_fanout.py里另写了clean2(),只删过孔和信号层 (1/2/15/16) 的导线, 并回读断言 3/9/13 三层还在。- ⚠️ 板框是 layer 11 上的
pcb_PrimitivePolyline,不是Line。 「剩余导线里还有没有 layer 11」不能当板框还在的证据 —— 第一版断言就是这么写错的, 清理明明是对的却报「板框被清光了」。要查板框得查pcb_PrimitivePolyline。
本轮验证结果(全过)
verify_sch.py P5-BTB ✔ PASS
verify_sch.py C1-CONN --nc c1-nets-nc.json ✔ PASS(U34.3 OS 有意悬空)
xpage.py 全工程 ✔ 真正漏接 0
port_audit.py 下板 513 / 载板 330 ✔ 可疑 0
pcb2_place.py 本地四项 + M3 断言 ✔ 161 元件(顶 133 / 底 28)
pcb2_clear.py 跨元件净间距 >= 0.2 mm ✔ 816 个焊盘
DRC 511 = 同封装内 115 + 连接性 396 + 其它 0(与基线一致)
截图 PCB2-carrier-v4.png / P5-BTB.png / C1-CONN.png。
25.10 排母逐针分配按几何重排(2026-09-05 夜,取代 §22.2 的 09-04 版)
铺 Inner1 之前先摸底,摸出 §22.2 那张「定稿」表和载板几何对不上。这是布线开始前 最后一次能免费改接口的机会(下板 PCB 还没布),所以先改表再铺铜。
硬冲突:4 A 的电源面穿不过排母的地针行
排母南排(y = 66.23)在两颗的前 16 位全是 GND 焊盘。焊盘 Ø1.6993、间距 2.54 ⇒ 相邻焊盘边距 0.84 mm,扣掉两边各 0.2 mm 净距,Inner1 上每个缝只剩 0.44 mm 铜网。
VOn_P 是 4 A,按 IPC-2221 内层 0.5 oz、ΔT 20 °C 要 6.97 mm —— 把一路三针周围
所有的缝加起来也只有约 1.8 mm。结论是硬的:跨行走不通,不是难看的问题。
09-04 那版为什么会跨行
它是按通道号切的(J24 = CH1+CH2+全局 / J25 = CH3+CH4+CH5),当时载板 PCB 还不存在。 载板画出来之后,五路的落点是:
| 网络 | 09-04 排母引脚 | 本站负载 | 负载在排母哪一侧 |
|---|---|---|---|
VO1_P |
J31 北 x 37.9~43.0 | x 14.5~43.1 | 北 ✔ |
VO2_P |
J31 北 x 45.5~50.6 | x 86.0~114.6 | 北(但要东行 55 mm) |
VO3_P |
J32 北 x 133.9~139.0 | x 157.5~186.1 | 北(东行 35 mm) |
VO4_P |
J32 北 x 141.5~146.6 | x 69.8~98.3 | 南 ✘ 跨行 |
VO5_P |
J32 北 x 149.1~154.2 | x 141.3~169.8 | 南 ✘ 跨行 |
+5V |
J31 北 ×3 | x 45.5~194.4,南北都有 | 两侧,要横贯全板 |
跨行的唯一出路是绕排母端头(三个通道:x<132.8 / 87.2~132.8 / >183.2)。
VO4_P 会变成一条约 120 mm 的蛇形岛(西行 → 钻手机 2 底下 → 南下 → 再西行 50 mm),
VO5_P 的站就在 J32 正下方却要绕 40 mm 再折回来。
新规矩:北排喂北边的站,南排喂南边的站
依据是载板几何 —— 每颗排母正上方一个站、正下方一个站:
J31 焊盘 x 37.87~ 86.13 正对 site1(x 5~72,北) 和 site4(x 41~108,南)
J32 焊盘 x 133.87~182.13 正对 site3(x 148~215,北) 和 site5(x 112~179,南)
site2 (x 76.5~143.5,北) 夹在两颗中间 → 取 J31 北排最右三针(x 81.05~86.13),
正好顶着 site2 最左的负载 C811(x 86.0)
重排后(逐针表见 §22.2,事实来源是 .claude/p5_btb.py 的 J24/J25):
| 网络 | 引脚 x / 行 | 最远负载曼哈顿 | 同侧 |
|---|---|---|---|
VO1_P |
37.9 / 40.4 / 42.9 北 | 32.1 mm | ✔ |
VO2_P |
81.0 / 83.6 / 86.1 北 | 42.0 mm | ✔ |
VO3_P |
169.4 / 172.0 / 174.5 北 | 25.1 mm | ✔ |
VO4_P |
73.4 / 76.0 / 78.5 南 | 28.4 mm | ✔ |
VO5_P |
154.2 / 156.7 / 159.3 南 | 26.3 mm | ✔ |
+5V |
10 针,两颗 × 南北四处 | 37.1 mm(到 Hub 的 C736) | —— |
最远行程从 ~120 mm 降到 ≤42 mm,五路全部同侧、一路都不跨行。
顺带把 +5V 的「横贯全板脊」也消掉了
09-04 版 +5V 只有 3 针、全在 J31 北排,而它的 12 个负载散在 x 45.5~194.4、
南北都有 ⇒ Inner1 上必须拉一条 150 mm 长、≥4.3 mm 宽的脊,横穿五路 VOn_P 的地盘。
改成 10 针分散取电(J31 北 45 / J31 南 1112 / J32 南北 12 / J32 南北 20)之后,
每个入口只喂本站的 0.8 mm 走线就够,
Inner1 上不用给 +5V 留任何东西**。同理 U2n + C70n,段电流 ≤0.6 A ⇒ **顶层 0.5+3V3_HUB(420 mA,局部)也不做岛。
⇒ Inner1 的最终规划简化成:5 块 VOn_P 岛 + GND 底填(原来是 5 + +5V + +3V3_HUB + 底填)。
针数变化(网络表一个都没变,只是落点变了)
| 09-04 | 09-05 | |
|---|---|---|
| 信号 | 47 | 54 = 15 VOn_P + 10 +5V + 25 站内 + 4 全局 |
| GND | 33 | 26(20 A 回流 = 0.77 A/针) |
五路 VOn_P 的「正对面 3 针 GND」(§15.4 各路独立回地)一条不少,
p5_btb.py 的 plan() 里逐行断言。
原理图画法跟着改了一处:GND 也走 netport
重排之后 GND 不再是「右列从第 1 行起的连续块」,而是散在两列的若干段
(J24 北 1317 / 南 15,14,1820;J25 北 911,20 / 南 58,1519)。
给每一段配母线 + 地旗的话,旗会掉进相邻行的端口里(行距只有 10,而旗高 15~20,skill §7)。
所以两页统一改成每个引脚一个 netport(含 GND)。
实测 verify_sch --nets 回读到 GND 26 个引脚,netport 命名的 GND 与地旗合并到同一个网络,
40 个端口叠在 10 的行距上渲染也没打架(截图确认过)。
本轮验证结果(全过)
verify_sch.py P5-BTB ✔ PASS(导线 80 / 端口 80)
verify_sch.py C1-CONN --nc c1-nets-nc.json ✔ PASS
xpage.py 全工程 ✔ 真正漏接 0
port_audit.py 下板 544 / 载板 361 ✔ 可疑 0
载板 PCB 导入变更 ✔ 65 条,全部是 J31/J32 的「修改网络」,无元件增删
PCB 上 80 个焊盘的网络 vs 逐针表 ✔ 全部一致(脚本逐行比对)
pcb2_place.py / pcb2_clear.py ✔ 161 元件 / 816 焊盘
重扇 210 孔 + Inner2 重铺 185 段 ✔
DRC ✔ 518 = 同封装内 115(与基线一致)+ 连接性 403 + 其它 0
截图 P5-BTB.png / C1-CONN.png。
25.11 载板 Inner1 分割电源面(2026-09-05 夜)—— 五块 VOn_P 岛 + GND 底填
事实来源 .claude/pcb2_pour.py 的 ISLANDS,改铜面改那里再 --push。
两个校核脚本都必须过(见本节末)。
落地的形状
Inner1 只有两类铜:五块 VOn_P 岛(优先级在前,先占地盘)+ GND 底填(优先级最后)。
+5V / +3V3_HUB 不开岛 —— §25.10 把 +5V 重排成 10 针分散取电之后,
每个入口只喂本站的 U2n + C70n、段电流 ≤0.6 A,顶层 0.5~0.8 mm 走线就够。
| 岛 | 网络 | 主体矩形(mm) | 颈(x0~x1 → y) | 面积 |
|---|---|---|---|---|
| VO1 | VO1_P |
12.5, 67.6 ~ 44.3, 84.0 | 不用开颈 | 491 mm² |
| VO2 | VO2_P |
80.0, 67.6 ~ 116.0, 84.0 | 不用开颈 | 541 mm² |
| VO3 | VO3_P |
152.0, 70.5 ~ 188.0, 84.0 | 168.5~175.9 → 67.6(朝下) | 475 mm² |
| VO4 | VO4_P |
68.0, 50.8 ~ 100.0, 63.5 | 71.5~79.9 → 67.4(朝上) | 406 mm² |
| VO5 | VO5_P |
139.5, 50.8 ~ 172.0, 63.5 | 152.8~160.6 → 67.4(朝上) | 411 mm² |
上排的 VO1 / VO2 不用单独开颈:它们左右都没有别的排母针挡路, 整块矩形直接压到 y=67.6(南排针 y=66.23 的反焊盘上沿 67.28 之上 0.32 mm)。 VO3 不行 —— 它左边就是 J32 的 POGO3 三针,只能从针缝里开一条 7.4 mm 的颈下去。
每一条边界都是被具体的焊盘顶住的
排母针 Ø1.699 + 0.2 安全间距 ⇒ 反焊盘半径 1.05 mm。逐条:
| 边界 | 顶住它的焊盘 | 反焊盘沿 |
|---|---|---|
| VO1 右 44.30 | J31.7 +5V (45.489) |
44.439 |
| VO2 左 80.00 | J31.33 GND (78.509) → 79.559;兼顾 MH5 Ø6 (76.6, 80.1) → 79.6 |
79.6 |
| VO3 主体左 152.00 | MH6 Ø6 GND (148.1, 80.1) |
151.30 |
| VO3 颈左 168.50 | J32.27 POGO3_VDN (166.889) |
167.939 |
| VO3 颈右 175.90 | J32.35 EDL_EN3 (177.049) |
175.999 ← 全板最窄的颈 7.40 mm |
| VO4 颈左 71.50 | J31.28 GND (70.889) |
71.939(吃掉 0.44,实测仍够) |
| VO4 颈右 79.90 | J31.36 GND (81.049) |
80.199 |
| VO5 颈左 152.80 | J32.16 GND (151.649) |
152.699 |
| VO5 颈右 160.60 | J32.24 POGO5_PWR (161.809) |
160.759 |
颈宽下限 7.0 mm 的来历(IPC-2221 内层 0.5 oz,不是外层):
A = (I/(0.024·ΔT^0.44))^(1/0.725),ΔT=20 °C ⇒ 4 A 需 188 mil² / 0.685 mil = 6.97 mm。
⚠️ 一条本轮才踩到的坑:铺铜的焊盘连接方式
默认规则 copperRegion 是十字花(connectMode: 0,辐条 0.254 mm)。
十字花下铜面多边形把自己的焊盘也挖空,只留 4 条描边辐条 ——
于是几何校核量到的最窄断面是 0.3 mm,看着像断路,其实是度量假象。
但假象和真断路在数据上分不出来,所以给五路 VOn_P 单独挂了 PLANE-DIRECT
(.claude/pcb2_rules.py 的 PLANE_RULE,connectMode: 1 = 全连接),
铜面就是一整块,怎么量都不含糊。GND 留默认十字花 —— 它有 ~200 个通孔焊盘
(光两颗排母就 160 针)要手焊,而回流被 26 根排母针分掉。
📐 「0.254 mm 辐条扛不住 4 A」是个看着对但错的直觉:IPC 的线宽表是给长导体的, 辐条只有 0.254 mm 长、两端都焊在大铜面上。单条 R ≈ 0.99 mΩ,4 条并联 0.25 mΩ, 4 A 上压降 1 mV / 发热 16 mW,ΔT ≈ PL/(8kA) ≈ 0.02 K。 所以改全连接是为了几何可验证,不是因为十字花会烧。
两个必须都过的校核(都不看 EDA 报的「段数」)
getState_PourFills() 把一块铜面吐成十几个 fill,那多半是切块不是断开(相邻块共边),
段数分辨不出「碎成孤岛」和「切块」。唯一靠得住的判据是把所有环画进同一张栅格再做连通域。
/c/Python314/python .claude/inner1_check.py # 下发前:按 ISLANDS 多边形 + 反焊盘预测
/c/Python314/python .claude/inner1_verify.py # 下发后:按 EDA 实际吐出来的铜实测
/c/Python314/python .claude/inner1_diffref.py # §10.1:顶层 5 段 *J 差分下方是不是一整块
实测(2026-09-05,栅格 0.05 mm):
| 岛 | 连通域 | 本网通孔焊盘 | 最窄横断面 | 最窄纵断面 |
|---|---|---|---|---|
| VO1 | 1 | 5/5 在主域 | 25.20 @ y=82.63 | 12.90 @ x=30.68 |
| VO2 | 1 | 5/5 | 29.20 @ y=69.08 | 11.70 @ x=107.73 |
| VO3 | 1 | 5/5 | 7.20 @ y=67.73 | 10.60 @ x=187.88 |
| VO4 | 1 | 5/5 | 7.70 @ y=66.03 | 8.40 @ x=80.38 |
| VO5 | 1 | 5/5 | 7.60 @ y=63.48 | 9.25 @ x=152.83 |
VO4 那条 8.40 mm 的纵断面在 x=80.38 —— 挡路的是 TP832(P− 的 Ø2.7 焊盘,
反焊盘半径 1.55)加三个 GND 扇出过孔,是预期之内的。
DRC:499 = 同封装内间距 115(与基线一模一样)+ 连接性 384 + 间距错误 0。 连接性从铺岛前的 396 掉到 384,正是五块岛接上的那 12 处。
截图 PCB2-inner1.png(整板)/ PCB2-inner1-left.png / PCB2-inner1-right.png(走廊两半)。
截图脚本 .claude/shot_pcb_layers.py <out.png> 15,12 <uuid> [x0 y0 x1 y1] ——
只显示指定铜层,截完自动恢复图层可见性。
25.12 差分对布线(2026-09-06)—— 连接器侧 5 对已完成,长距离 6 对待做
事实来源 .claude/pcb2_route_dp.py 的 SITE_J / PATHS,配套本地校核在同一个文件里。
⚠️ 先纠一个摆位错误:U5n 装反了(已改)
USBLC6-2SC6 是直通器件:pin1/6 = I/O1、pin3/4 = I/O2,一排朝连接器、一排朝主机。
BAND['u5'] 的 rot 从来没设过(默认 0),结果朝连接器那一排背对着 J7n,
两条网络都得绕过封装走。已改成 rot 180。
SOT-23-6 是对称封装,转 180° 之后 6 个焊盘落在完全相同的 6 个位置,只是引脚编号对调
⇒ 没有任何新的间距冲突(pcb2_clear.py 816 焊盘复核过),但必须跑完整的
「重摆 → GND 扇出 clean/dump/push → 重铺铜 → 重验」流程(扇出 210 孔、
Inner1 五块岛最窄颈 7.20 mm、inner1_diffref 五段全过,全部与改之前一致)。
顺带的收益:VBUS1(pin5) 也跟着换到朝 U2n 那一侧;长差分对的换层点从
「U5n 与 BM24 焊盘之间那条 2.0 mm 窄缝」挪到了开阔走廊。
自动布线器在载板上不可用(结论,别再试)
按下板那一轮的做法配好并跑过(pcb2_route_diff.py 里 --snap/--config/--run/--watch/--finish/--rollback
一整套都留着,配置项逐条回读断言):22 个网络里只画出 J23 自己那两条 A6↔B6 / A7↔B7 的
短接线,全板 0 个过孔,30 秒内就"跑完",console 只有一句
ProgressManager: can not remove progressGroup[win_progress_0] not exist。
板框是合规的单条闭合多段线、四层、规则齐全、22 个网络也确实选中了(46 个焊盘)——
它就是没在找路。改成手工逐段算坐标 + 本地校核。
✅ 已完成:5 对 USBn_DPJ/DMJ(U5n ↔ J7n)
五个服务带同构,所以只写一遍站内坐标 (u, v),to_board() 映射到五个位置。
DPJ全程顶层:出 J7n.6 → 外移到 v=-5.20 → 东行 → 进 U5n.3。5.05 mmDMJ两端 u 次序与 DP 相反(J7n 上偏西、U5n 上偏东)⇒ 必须交叉, 用两个过孔沉到底层从 DP 底下穿过去再上来。9.19 mm,偏斜 4.14 mm(容差 5)。 底层那一段的参考面是 Inner2 整板地,比顶层还干净。
出线宽度是算出来的,不是拍的:BM24 焊盘 0.1803 宽 / 间距 0.35 ⇒
0.35 − 0.09015(焊盘半宽) − 0.20(安全间距) = 0.05985 半宽 ⇒ 线宽上限 0.1197 mm。
取 0.11(净距 0.205);0.12 会差 0.00015 mm 卡在判据线上,实测报错。
出了焊盘阵列、两根线还只隔 0.35 时用 0.20(0.35−0.10−0.10 = 0.15 = 对内间距),
分开之后才放宽到 0.28。
⇒ pcb2_rules.py 的 DIFF['strokeWidthMin'] 随之从 0.20 降到 0.10
(同 §10.1 里 PWR4A 把最小值降到 0.3 的道理:规则按网络生效,
一个网络上既有 0.28 的主干也有进细间距焊盘的颈)。
验证:本地净距校核(线-焊盘 / 线-过孔 / 线-线 / 过孔-×4,一般 0.20、对内 0.15)全过; 下发 60 段导线 + 10 个过孔;重铺铜之后 DRC 回到 479 = 同封装内 115(与基线一致)+ 连接性 364 + 间距错误 0。
⚠️ 加完线和过孔一定要重铺铜再看 DRC。 不重铺时刷出 40 条间距错误 (「到过孔」20 +「到钻孔」20)—— 那是铺铜还不知道新过孔的存在、没让开它们。 重铺之后 GND-INNER1 的环数 217→227、INNER2 330→340,正好是 10 个新过孔的反焊盘。
✅ 已完成:6 对长差分(USBn_DP/DM ×5 + UPSTREAM)—— 详见 §25.13
(下面这段走廊表是当时的踏勘结果,留作背景;实际怎么走看 §25.13。)
当时的踏勘:底层走廊
底层走廊已经扫出来了(pcb2_route_dp.py --corridors 可复现),照着走别再猜:
| 用途 | 纬线 | 底层通的区间 |
|---|---|---|
| 南高速 | y = 56.0 | x 40~215 整段通 |
| 南高速(西行) | y = 60.5 / 61.0 | x 40~104 整段通 |
| 北高速 | y = 75.0 / 76.0 | x 40 |
| 北高速(绕开 Hub) | y = 84.0 | 58.7 |
| 竖向(Hub 西侧) | x = 100.0 / 101.0 | y 55~78 整段通 |
⚠️ 每一对都至少要换一次层,两条独立的原因:
- U32 的引脚次序和目的地次序对不上:西边缘从南到北是 port1..5, 而 port1/2/3 去北排三站、port4/5 去南排两站 —— 正好反过来。 十根线在一层上无论怎么绕都要交叉 6 处。
- 奇偶性:一根线"西行→北行→西行"(右转再左转)之后左右关系回到原样, 所以就算次序对得上,到 U5n 那一端 DP/DM 谁在东谁在西也未必对。
交叉要挑 Inner1 是 GND 的窗口做:x 100~139 / y 50~67.5 是一大片 GND
(VO4 岛止于 x=100、VO2 岛止于 y=67.6、VO5 岛从 x=139.5 起),Hub 西侧的换层就放这里。
换完层之后 inner1_diffref.py 要扩展成"沿实际走线逐段查参考面"再跑一遍。
25.13 六对长差分布线(2026-09-06 第三轮)—— 载板差分对全部布完
事实来源是 .claude/pcb2_dp_long.py(坐标 + 每一条的理由),
校核 / 下发仍走 .claude/pcb2_route_dp.py。
/c/Python314/python .claude/pcb2_route_dp.py --dump # 改了布局/铜就重抓障碍表
/c/Python314/python .claude/pcb2_route_dp.py # 只算 + 本地净距校核
/c/Python314/python .claude/pcb2_route_dp.py --push # 下发(先删本网 1/2 层旧线)
/c/Python314/python .claude/pcb2_net_conn.py # 按实际铜算 22 个网络的连通域
/c/Python314/python .claude/inner1_diffref.py --routes # §10.1:沿实际走线查参考面
决定全局走法的那道隘口:x 112~116
Hub 北边的 C751(10 µF 1206,底层,(113.0, 74.0))加上 C815 的 GND 扇出孔
(113.047, 77.5),把北高速在 x=113 处掐成两个窗口(线心可用范围):
| 窗口 | 线心 | 能塞几对 |
|---|---|---|
| 底层·低窗 | 76.185 ~ 76.72(0.535 mm) | 1 对 |
| 底层·高窗 | 78.28 ~ 81.52 | 够,但东边 (117.067, 78.392) 那个孔把 x=117 的天花板压到 77.75,出隘口必须马上降下来 |
| 顶层同一段 | 75.58 ~ 76.16 | 1 对(C751 在底层,顶层是通的) |
南边过不去:Hub 南侧 A 圈那排 0402 占了 y 60.2861.12、x 105114,
上下都只剩 0.05 mm,只有 y≈56 一条缝,塞不下三对。
所以三对东行的(pair2/3/5)只能一对一个窗口,南北次序被 U32 的引脚次序锁死:
爬升后由西到东是 1,2,3,5,转东后由北到南就是 2,3,5 ——
正好对上「pair2 在 x=133 北拐、pair3 继续东行、pair5 在 x=121 南下」的需求,不用额外交叉。
六对各自怎么走
| 对 | 走法 | 长度 |
|---|---|---|
| 1 | 底层西行 → x 98.3/98.8 爬升 → 西行 74.70/75.55 → site1 | 54.5 / 55.9 |
| 2 | 底层西行 → 爬升 → 高窗 78.29/78.83 → 降到 77.16/77.70 → 缓降到 75.05/75.70 → site2 | 56.8 / 53.6 |
| 3 | 底层西行 → 爬升 → 低窗 76.20/76.63 → 降到 73.85/74.35 → 抬回 75.00/75.70 → site3 | 123.1 / 119.9 |
| 4 | 一出焊盘就上顶层南下(全板唯一要横穿其它对的一对)→ 底层西行 60.30/61.00 → site4 | 63.9 / 62.6 |
| 5 | 底层爬升 → 顶层过隘口 75.68/76.14 → 底层南下 → site5 | 47.4 / 46.1 |
| UP | U32 南边一出焊盘上顶层(竖井底层被扇出孔堵死)→ 顶层东行 61.10/61.70 → x=128 沉底层 → 60.00/60.75 → J23 | 108.0 / 106.0 |
最长的 pair3 是 123 mm,加上 *J 那 9 mm 一共 132 mm,
在 USB2517I 手册的 152 mm(6 inch)以内。对内偏斜最大 3.3 mm(容差 5)。
这一轮改的两件事(不是布线本身)
VO2_P岛东边界 116 → 119(pcb2_pour.py的ISLANDS)。 pair5 过隘口那一段在顶层,参考面就是这块岛;边界停在 116 的话, 下沉的两个过孔(x=118)会落到 GND 底填上,那一小段要跨分割缝(违反 §10.1)。 放到 119 之后inner1_check/inner1_verify仍全过(VO2 一个连通域、 最窄横断面 29.30 / 纵断面 9.80,下限 7.0)。- J23 的
A6↔B6/A7↔B7短接线要自己画。原来那两条是自动布线器留下的, 被--push的「先删本网所有 1/2 层导线」连坐删掉了 —— 少了它们, USB-C 反插方向就没有 D±。四个焊盘在同一列上(B7 61.25 / A6 61.75 / A7 62.25 / B6 62.75), 两两要短接的中间都隔着对方的脚,只能绕到连接器东侧 x>213.5 沉底层跨过去。 为此给pcb2_route_dp.py加了NET#2这种「同网络第二条支路」的 key(netof())。
⚠️ 三个这一轮才踩到的坑
drc_read.py不加--pcb2跑的是下板(默认 UUID 是下板的)。 第一次读到 649 条、里面全是KEY_OE#/SDA这些下板网络,白查了半天。- DRC 的「连接性」结果在程序化建线之后是陈旧的,要
location.reload()才刷新。 刚下发完跑出来是 403(我的网络每个还报 2~7 条「与其他相同网络的对象断开了连接」), 而pcb2_net_conn.py按实际铜算是 22/22 全连通、pcb_Net.getNetLength()也等于算出来的长度。 重载客户端之后立刻变成 338(比布线前的 364 少 26 = 12 个网络 ×2 + J23 的 B6/B7)。 ⇒ 别信刚下发后的连接性数字;间距错误那一支倒是即时更新的。 - 45° 切角的半径会把线甩进旁边焊盘的净距圈。
chamfer()默认 r 从 0.6 降到 0.35, 而且在焊盘阵列附近还要多插一个共线点把切角压到 0.150.2 ——0.18 mm)。USB1_DM的让位拐角、J23 那四条出线都是这么救回来的(差 0.04
收工时的数字
| 项 | 值 |
|---|---|
| 导线 / 过孔 | 270 段 / 38 个(含 *J 那 5 对) |
| 本地净距校核 | 全过(一般 0.20 / 对内 0.15) |
pcb2_net_conn.py |
22 / 22 个差分网络各 1 个连通域 |
inner1_diffref.py --routes |
每条顶层走线只压在一块铜上(pair5 那段是 VO2_P,其余 GND) |
inner1_check / inner1_verify |
五块岛全过 |
| DRC(载板) | 453 = 同封装内 115(与基线一致)+ 连接性 338 + 间距错误 0 |
25.14 载板电源与杂散信号布线(2026-09-06 第四轮)—— 栅格迷宫布线器
差分对收工之后还剩 77 个网络、三百多个端点:五路的 VBUSn、+5V / +3V3_HUB、
十五根 POGO*、EDL_ENn / VBUS_ENn、CC1_n / THERM_n、Hub 的十几根配置线、
SCL/SDA,外加 §25.8 欠着的 BM24 那 65 个 GND 脚的逃逸布线。
这一批和差分对是两类活:差分对要管耦合 / 参考面 / 偏斜 / 换层窗口,是几何设计,
所以写死坐标才说得清理由;这一批绝大多数是「从 A 走到 B、别撞上东西」。
所以新写了 .claude/pcb2_route_sig.py:一个栅格迷宫布线器,
产出照样过 pcb2_route_dp.check()(和差分对同一份净距判据),路径怎么来的不重要。
/c/Python314/python .claude/pcb2_route_sig.py # 算 + 本地校核,不下发
/c/Python314/python .claude/pcb2_route_sig.py --push # 下发(没布通的网络要加 --force)
收工时的数字
| 项 | 值 |
|---|---|
| 网络 / 路径 / 导线 / 过孔 | 77 / 431 / 991 段 / 160 个 |
净距校核(check(),一般 0.20) |
全部通过 |
pcb2_net_conn.py(按实际回读的铜算连通域) |
72 / 75 通 |
inner1_verify / inner1_diffref --routes |
五块岛仍各 1 个连通域、最窄颈 7.20 mm;顶层差分下方仍只压一块铜 |
| DRC(载板) | 166 = 同封装内 115(与 §25.8 基线一模一样)+ 连接性 51 + 间距错误 0 + 物理错误 0 |
连接性 51 的构成(全部是已知的、还没做的活,不是错误):
VO1~VO5_P 各 6~7 条 = 31(五路的贴片电容还没打孔接到 Inner1 岛,见下面「下一步」)、
+3V3_HUB 4 + VBUS_UP 2 + SCL 2 + POGO5_VDN 2 = 10(四个网络各差一两段,见下)、
GND 10(J23 的两个屏蔽脚 + Hub 簇 4 个 0402 的地脚 + 1 个过孔,§25.8 遗留)。
对比布线前:499 → 166,连接性 384 → 51。
布线器的三条判据(都不是"看着差不多",是算出来的)
- 栅格 0.1 mm,障碍先胀
QERR = g·√2/2再栅格化。 只标"格心落在铜里"的格时,铜边界到最近的被标记格心可以差到将近一整格 (实测一个 Ø0.61 过孔的边在 x=52.781、最近格心在 52.7,差 0.081 > 0.0708), 于是距离场会高估 0.08 mm,净距校核在下发前一刻才炸。 先胀再栅格化之后真实净距 >= edt − QERR才严格成立。 - 窗口先小后大、栅格先粗后细(0.1 → 0.05 → 0.025)。 排母 2.54 间距 / Ø1.699 焊盘 ⇒ 缝宽 0.841 mm,0.25 的线要 0.65,明明过得去, 但 0.1 mm 栅格上离缝心最近的格心可能偏 0.04,加上 QERR 就差那么一点点 —— 于是"从排母针缝里穿过去"在粗栅格上整片不可达。
- 线宽阶梯:正常宽度过不去就收窄再试(信号到 0.15,功率按
TRACK_RULES的 min)。 Hub 卫星圈是 1.2 mm 网格上的 0402,缝只有 0.659 mm, 0.25 的线要 0.65 —— 量化余量一进去就过不去,0.20 才通。 ⇒W_SIG定 0.20(不是 0.25)。
⚠️⚠️ 这一轮抓到的最阴的一个 bug:expand() 会静默丢掉路径末端的过孔
pcb2_route_dp.expand() 的语义是「第 i 点的层 = 从这一点走到下一点那一段的层」,
换层的过孔打在第 i+1 点上 —— 但它显式跳过最后一个点(i + 1 < n - 1),
最后一点的层被当成占位符。于是「走到目标焊盘正上方再换层落下去」这种路径,
过孔被静默丢掉:两层的铜各画各的,中间断开。
三道校核全都抓不到:
净距校核只看撞没撞(断开当然不撞)、inner1_verify 只看铜面、
DRC 的连接性又要 location.reload() 才刷新。
踩到两次,第二次更贵:
- 布线器自己的路径:
$25N40/SDA/VBUS_DET/XTAL2/VBUS_EN3五个网络断开; - 手写的
bm24_pre():五个站 50 个 GND 过孔全部丢掉, 两条梳子 + pin52 的连线整个悬空,DRC 报出 J7n 的 pin 1/2/8/12/47/52 断开(GND 55 条)。 补上之后 GND 从 55 掉到 10。
⇒ pcb2_route_sig._end_via():末点上有换层就补一个重复点。所有路径(含手写的)都要过这一道。
BM24 周围的车道分配(§25.8 那条待办的落地方案)
§25.8 判定"51 个 GND 脚旁边打不下过孔、只能逃逸布线"是对的, 但它写的"前排一律往南、后排一律往北"没用上两排之间的中央通道。实际只有三块地方能走线:
┌ 后排北侧 v > -1.70,到手机投影边 v=0 ── 后排 7 个 GND 脚的梳子(v=-1.10,5 个过孔)
│ 中央通道 v ∈ [-3.82, -1.70],净高 1.64 ── THERM / CC1 两条东行车道 + pin2/pin8 的过孔
└ 前排南侧 v ∈ [-4.30, -5.06],净高 0.76 ── 前排 pin 12/16/24 的梳子(v=-4.68,宽 0.20)
三条算式(每一条都卡在 0.2 mm 上,改动前先重算):
| 算式 | 结果 | |
|---|---|---|
| 前排梳子 v=-4.68 | 到焊盘南沿 0.38 − 0.10;到 *_DPJ 东行段上沿 0.38 − 0.10 |
两边都 0.28 ✔ |
| pin 2 / pin 8 上不了这条梳子 | *_DPJ 过了 v=-4.65 放宽到 0.20,u=54.35 处只剩 0.35 − 0.055 − 0.10 |
0.195(差 5 µm)✘ |
| 中央通道里 GND 与 THERM/CC1 不能共存 | 前排的脚往北出必须竖着穿过通道,会切断任何东行车道;想换层绕过去,通道里过孔离相邻竖线只有 0.35 − 0.305 − 0.055 | < 0 ✘ |
所以:通道判给 THERM/CC1(它们没有别的出路,R76n/R77n 在东南),
pin 2 / pin 8 在通道最西端就地打孔,其余前排 GND 走南缝。
南梳子上打不下过孔(南北各只有 0.38,要 0.505),所以往东伸到 u=60.5 再打两个。
⚠️ pin 52 的扇出在 site1~3 朝东(u=64.48)、site4/5 朝西(u=62.58) ——
西边那两个正好堵在 THERM/CC1 的车道出口上。本脚本把五个站统一成朝东,
删除框放到 u <= 65.2 把旧的收进去。
顺带修掉的两个方向错误(原理图看不出来、几何检查也过的那一类)
R76n装反(pcb2_place.BAND['r76']rot 0 → 180): pin1=CC1 要朝东(CC1 从中央通道的车道出口 u=62.3 过来)、pin2=VBUS 要朝西 (VBUS 从 U5n 的 u=57.5 过来)。rot 0 时两根线各自绕过整颗电阻、当场交叉, 五个站的VBUSn全部布不通。这和 §25.3 的顶针、§25.12 的 U5n 是同一类错误。+5V从 0.80 收到 0.60:§25.10 重排逐针分配之后它是 10 针分散取电、 段电流 ≤0.6 A,0.60 mm 外层 1 oz 可载 ~2 A。0.80 在排母到服务带那条 已经站满 EN/POGO 线的走廊里挤不过去(实测五处布不通)。
布线器上必须记住的四条工程约定
- 先给所有网络的所有焊盘留好出线段,再开始布线(escape routing 先行)。
不这么做的话先布的网络会把后布的网络出焊盘的那 0.6 mm 占掉:
实测
VBUS2斜穿 U25 东侧让+5V出 U25.1 只剩 −0.02 mm,+3V3_HUB竖着切进 U42.5 让隔壁 0.95 mm 外的EDL_EN2出不来。 - 出线段的方向 = 焊盘长轴(长短边 ≥1.3 时)背离元件形心;接近方的焊盘(0402、晶振)
才按"背离形心的那根轴"。只用后者会把
J23.A5判成往南出、正好压在 B8 焊盘上。 - 生成树用 Prim,不是最近邻链。
+3V3_HUB有 33 个焊盘, 最近邻链会串成一条长蛇,好几段被逼着绕过整个 Hub 卫星圈。 - 障碍表要摘掉"下发时会被删掉的铜":本脚本负责的网络(整网重画)+ 五个 BM24 框里的旧 GND 扇出。不摘的话第二次跑会把自己上一轮的线当障碍, 既不幂等,还会刷出「和马上要删掉的那条线撞了」的假冲突。
⚠️ 铺铜必须重来一遍,而且客户端要真的重载
布完线之后 DRC 是 696,其中 445 条是「铺铜区域(填充) 到 过孔 / 钻孔」——
新打的一百多个过孔在旧的铜面里没有反焊盘。布线之后必跑 pcb2_pour.py --push。
跑的时候踩到一个坑:location.reload() 会弹出浏览器的「离开该页面 / 留在该页面」确认框
(文档有未保存改动),点了「留在该页面」页面根本没重载,
客户端仍卡在后台任务上 —— 表现就是 工具 → 铺铜管理器… 点了没反应、
重建所有 按钮找不到,getState_PourFills() 一直是 0 段。
⇒ 重载前先 eda.pcb_Document.save(),否则等于没重载。
还剩的四个网络(都差一两段,成因已定位)
| 网络 | 差的那一段 | 成因 |
|---|---|---|
+3V3_HUB |
U32.46 / R716.2 各一段 | Hub 卫星圈 A 圈(6.3 mm)+B 圈(8.0 mm) 把 QFN 围死,缝只有 0.659 mm,几根线抢同一条缝 |
VBUS_UP |
到 R709.1 |
同上:R709 在 A 圈东侧,出口被 B 圈的 R716/R720 夹住 |
SCL |
J31.23 → U34.2(~70 mm) | 和 SDA 抢同一条通道;SDA 先布,占掉了唯一那条 |
POGO5_VDN |
J32 → J59 | 走廊被十五根 POGO 线切碎之后没缝了 |
这四个不是布线器的毛病,是 Hub 卫星圈的摆位太挤 + 左下角只有一条通道。
真要收干净,两个方向(都要用户拍板,因为会动已经验过的东西):
① 把 Hub 的 B 圈(R711/R716/R720,纯配置电阻)从半径 8.0 挪到 9.5,
A/B 圈之间就从 0.7 mm 变成 2.2 mm —— 代价是这三颗的 GND 扇出过孔要重做;
② SCL/SDA 改成从 J31 的东端绕,或者把 U34(测温) 从左口袋挪到离 J31 近的地方。
45° 走线(2026-09-06 用户拍板:全板不许有直角走线)
在 pcb2_route_dp.py 里加了三个工具,两个脚本共用:
| 函数 | 干什么 |
|---|---|
sharp_corners() |
列出所有转向角 > 45° 的拐点(换层点不算 —— 那是过孔,不是拐角) |
chamfer45() |
逐个拐点把 45° 斜切的半径试出来:0.50 → 0.06 依次退让,取第一个过净距的 |
smooth_micro() |
先抹掉微台阶(偏离前后连线 < 0.15 mm 的中间点),再切 |
结果:差分对 10 → 0,信号线 72 → 0,全板一个直角拐点都没有,
净距校核、pcb2_net_conn、inner1_verify、inner1_diffref 全部保持通过,
DRC 仍是 166(和 45° 化之前一模一样)。
四条实现上的判据(每一条都是踩出来的):
- 只切转向角 > 45° 的拐点。 已经是「正 + 斜」的 45° 拐是标准形态, 再切一刀会变成两个 22.5°,反而更糟。
- 切完只校核斜切段本身。 被缩短的那两段是原来那两段的子集,净距只增不减。
- 净距余量必须按
need()算,不能只算净距再拿CLR比。 对内间距是 0.15,*_DPJ/*_DMJ就是贴着这个数并排走的 —— 一律按 0.20 判的话,这五对的拐角全都"切不动"(第一版就是这么卡住的,10 → 5)。 smooth_micro只给布线器的产出用,差分对不抹。 而且绝不能删线宽换挡点 —— BM24 出线靠 0.11 / 0.20 / 0.28 三档才合法, 把换挡点当"共线冗余点"删掉,整条就按最宽的那一档画,当场违规(实测 275 → 211 段,两处炸)。 顺带:抹平不是保守操作(斜切才是),所以校核里必须连本轮新打的过孔一起查 —— 只查线的话会把线挪进别人的孔里(实测USB5_DM撞USB3_DP的孔)。
⚠️ T 形接头不算拐角,保持直角。 BM24 那两条 GND 梳子上, 中间几根出线段是「梳子 + 支线」的 T 形接头 —— 线本身没有拐弯,只是两条线相交。 最西那一根已经和梳子写成同一条路径,所以它那个 90° 切成了 45°; 其余的按 T 形保留。前排梳子所在的通道只有 0.76 mm, 就算全部改成 45° 分支,斜切半径也只能到 0.10 mm(算式:0.3093 − r ≥ 0.20),肉眼看不出区别。
25.15 载板收尾:五路 VOn_P 电容打孔 + §25.8 遗留的悬空 GND(2026-09-06 第五轮)
DRC 从 166 掉到 125 = 同封装内间距 115(基线)+ 连接性 10 + 间距错误 0 + 物理错误 0。
连接性剩下的 10 条全是 §25.14 末尾那四个网络(+3V3_HUB 4 / VBUS_UP 2 / SCL 2 /
POGO5_VDN 2),要用户拍板才能动。这一轮之后,载板上不需要拍板的活全部做完。
| 脚本 | 干什么 | 产出 |
|---|---|---|
.claude/pcb2_vo_vias.py |
25 个贴片电容焊盘各打一个过孔下到 Inner1 的岛上 | 25 线 / 25 孔 |
.claude/pcb2_gnd_patch.py |
自己找出悬空的 GND 连通域再补孔 | 5 个域 → 6 线 / 5 孔 |
.claude/pcb2_npth.py |
从铺铜反焊盘里反解封装自带的非金属化孔 | 见下 |
一、五路 VOn_P 的电容(连接性 51 里的 31 条)
每个 VOn_P 网络 10 个焊盘:5 个通孔(C8n1.1 电解正极 / TP8n1 / 排母 3 针)
本来就落在 Inner1 的岛上;剩下 5 个贴片焊盘(C8n2/3 100µF、C8n4/5 22µF、
C8n6 100nF)只有顶层铜,和岛之间没有任何通路。⇒ 每个旁边打一个过孔。
选点判据(pcb2_vo_vias.place(),pcb2_gnd_patch 共用同一套):
| 方向 | 只取 8 个方向(0/45/90…);一段直线不行才拐一个 45°,不许直角 |
| 起步距离 | 过孔铜边到本焊盘 ≥ 0.15(同网,不是 DRC 约束,是不想做 via-in-pad) |
| 净距 | 借 pcb2_route_dp.check() 同一份判据,异网 ≥ 0.20 |
| 岛内余量 | 过孔中心离岛边界 ≥ 0.61/2 + 0.30 = 0.605 |
| 线宽 | PWR4A 最小 0.30;从 1.00 起往下退让,25 个里 20 个用到 1.00、5 个 0402 用 0.60 |
25 个全部一段直线搞定。铺完铜 inner1_verify 五块岛仍各 1 个连通域、
5 焊盘 + 5 过孔全在主域、最窄断面 7.20/9.10/10.15/7.35/7.60 mm(下限 7.0)。
inner1_verify.py这一轮加了过孔的校核。原来只查本网通孔焊盘 —— 贴片电容全靠这一个孔接岛,孔要是掉进边角碎片里,原来那版一个字都不会说。
二、§25.8 遗留的悬空 GND(连接性 51 里的 10 条)
pcb2_gnd_patch.py 不抄 DRC,自己算:把 GND 的焊盘/过孔/导线当图,
一个连通域里只要有一个过孔或一个通孔焊盘就算落到平面上,
一个都没有的域就是悬空的。算出来 5 个:
C749.2 / R710.2 / U32.19 / J23.A1B12 / J23.B1A12。补完再跑,0 个。
⚠️ 下发不能用 pcb2_route_dp.push() —— 它整网重画,对 GND 就是把 210 个扇出孔
连同 BM24 的梳子一起删光。改成只动自己那几个对象,靠 _pcb2_gnd_patch.json
记账(上一轮画在哪),下次 --push 先按坐标删掉再重画。
不记账实测踩过:改完选点逻辑直接再推,板上多出一对旧坐标的过孔(425 而不是 423),
而且新画的细线被 EasyEDA 并进了旧的粗线里 —— 现象是"改了没生效"。
⚠️⚠️ 这一轮最值得记住的:封装自带的孔,API 一个都读不出来
J23(USB-C 母座)的封装里有两个 Ø0.60 的非金属化定位孔,
在 A1B12 / B1A12 两个 GND 焊盘的外侧角上:(213.660, 59.100) 和 (213.660, 64.900)。
它们不在 pcb_PrimitivePad.getAll() 里;pcb_PrimitiveRegion / pcb_PrimitiveFill 是空的;
pcb_Primitive.getPrimitiveByPrimitiveId('e55') 返回空;
pcb_Document.getPrimitiveAtPoint() 只回最上面那条线。
能看见它们的只有两处:DRC(「挖槽区域 到 导线」)和内层铺铜给它们让出来的反焊盘。
⇒ pcb2_npth.py:把 Inner1/Inner2 的铺铜环读回来,拟合出里面所有的圆弧,
用「已知过孔的反焊盘半径 − 过孔半径」标定铺铜净距(实测 0.3583 mm,234 个样本,
离散度 0.005),再反推每个圆的真实孔径;圆心对不上任何焊盘/过孔的就是封装自带的孔。
全板扫出 423 段弧,滤掉铺铜自己的圆角(孔径 ≈ 0)和板框 R5(≈ Ø8.08),只剩这两个。
/c/Python314/python .claude/pcb2_npth.py --write # 写 _pcb2_npth.json,布线脚本读它
两类孔的待遇完全不同(一条条用 DRC 试出来的,写在 pcb2_vo_vias.holes() 里):
| 线能不能压上去 | 过孔能不能靠近 | |
|---|---|---|
焊盘自己的孔(SLOT / ROUND,金属化) |
能 —— 它就是焊盘的一部分 | 不能,钻孔间距 ≥ 0.30 |
| 封装自带的非金属化孔 | 不能,DRC 报「挖槽区域 到 导线 距离 0mil」 | 不能 |
一开始把两类混在一起判,结果是「谁都连不上 J23 的屏蔽脚」——
J23.1/J23.4 是 SLOT 0.80×1.50 的槽孔焊盘,焊盘上任何一点离自己的槽都不足 0.80 mm,
按那个判据连焊盘本身都碰不得。
这一轮踩到的另外两条
- 净距校核只看铜,钻孔是另一条规则。 第一版给
J23.A1B12打的孔正落在J23_4的焊盘里(同网,铜的判据直接跳过)—— 校核全过,DRC 报 「钻孔 到 钻孔 距离 0mil,应该 >= 11.8mil」。⇒fits()里同网的通孔焊盘 和同网的过孔都要按DRILL = 0.33再判一遍(规则要求 0.2997,留 30 µm 余量)。 - 线的起点默认在焊盘中心,但要能往外退。
place()的starts()沿出线方向 从中心一路退到焊盘边内 0.02 mm,取第一个过的 —— 焊盘正中有孔时(J23 那两个) 只有退到边上才过得去。25 个电容一个都没用上这一条(全部从中心起步)。
追加(2026-09-06 第五轮后半):U34 挪到 J31 旁边,四个网络收掉两个
用户拍板「直接把 U34 挪到 J31 附近」。之前按「只动布线」试了一轮(见下),
SCL / POGO5_VDN 其实已经布通了,但 SCL/SDA 仍是 70 mm 的长跑;挪件之后 ~4 mm。
| 原来 | 现在 | |
|---|---|---|
U34(LM75BD)/ C760 |
左口袋 (36, 12) / (36, 6.5),顶层,贴着 CH4 量进风侧空气 | (68.0, 72.1, rot 90) / (72.6, 72.1, rot 90),底层,J31 北排 pin 21/23 正上方 |
SCL / SDA |
J31.21/23 → 左下角,~70 mm,两根抢左下角唯一那条通道 | ~4 mm,底层直连 |
| DRC | 125 | 121 = 同封装内 115 + 连接性 6(+3V3_HUB 4 / VBUS_UP 2) |
⚠️ 它量的东西变了:原来是进风侧空气温度,现在是两排手机之间排母走廊的温度。 风扇闭环(§22.6)的阈值要按新位置重新定 —— 这是挪件的代价,不是 bug。
位置是被三样东西夹出来的(pcb2_place.BOT_GLOBAL 里有注释):
顶层塞不下(J31 焊盘顶 69.62 到 U24 底 71.25 只有 1.6 mm);底层这条带子上沿是
USB1_DM 那对长差分(手写几何,y≈74.7,不能动),竖放时北排焊盘压在上面(实测 −0.14);
横放后 4.38 mm 高的焊盘只能落在 y 72.01~72.17 之间,再往左 U34.4 撞
USB1_DM 在 (63.45, 74.70) 的换层过孔。旧位置的 5 个 GND 扇出孔按框删掉。
只动布线那一轮的结论(pcb2_route_sig.py 里两处改动,都保留了):
- 出线方向要有备选。
entry_stub()现在返回全部合法方向,route_net()在首选方向 布不通时换一个再试。R709.1(VBUS_UP)原来「背离形心」= 朝东扎进 A/B 圈之间 0.268 mm 的 死胡同,U34.2原来朝南顶着板边 —— 两个都是只布这一个网络、整板空着也布不通, 不是拥挤,是方向选错。换方向之后SCL通了。 - POGO 按两端直线距离从短到长排。site4/5 的
VDN源在最东、靶在最西, 后布就被另外两根夹死;提前之后POGO5_VDN通了。 - 试过把
+3V3_HUB提到卫星圈配置线之前,更糟:它 33 个焊盘先铺满 Hub 周围,XTAL1/CFGSEL0/PRTDIS6/PRTDIS7/HUB_RST五根全布不通(4 → 7)。已回退。 大网络必须排在点对点的小网络之后。
⇒ 剩下 +3V3_HUB(U32.46 / R716.2)和 VBUS_UP(R709.1)三段,
全在 Hub 卫星圈 A/B 两圈之间,只动布线穷尽了:要收干净只剩方案 ①(B 圈半径 8.0 → 9.5)。
顺带一条 pcb2_vo_vias.fits() 的 bug:本轮新打的同网过孔之间没判钻孔间距,
U34 相邻三个 GND 脚的孔排成一列、中心只隔 0.23 mm。已按 DRILL 补上。
25.16 载板 v2:元件全部到底层,排线穿槽(2026-09-06 用户拍板)
用户两条指令:① 把载板正面的器件全部放到背面,在背面重新布局;② 排线通过板内开的细长槽 穿过去接到载板。补充:器件可以放到主板投影下方(底层),方便布线。
脚本 .claude/pcb2_place.py(v2,文件头有完整说明);v1 存档 obsolete/pcb2_place_topside_2026-09-06.py,
v1 的全部铜/元件状态在 .claude/_pcb2_snap_topside.json(pcb2_snapshot.py 抓的,1586 线 / 416 孔 / 7 铺铜)。
截图 PCB2-v2-all.png / PCB2-v2-bottom.png / PCB2-v2-ch1.png。
落地结果
| v1 | v2 | |
|---|---|---|
| 顶层元件 | 131(服务带 105 + 顶针 20 + J23/U31 组 6) | 20(只有顶针) |
| 底层元件 | 30 | 141 |
| 穿线槽 | 无 | 10 条(每站 2 条,3.0 mm 宽,跑道形,layer 12 挖槽区域) |
| C8n1 Ø10×16 电解 | 顶层立装(载板最高件 16 mm) | 底层卧倒(占高 10 mm) |
| Hub 簇中心 | (110, 67) | (100, 68) |
| 铜 | 全部布完 | 全部清空(1416 线 + 16 条漏网的 + 416 孔 + 7 铺铜),要重来 |
本地检查(无重叠 / 无越框 / 无人压槽 / 顶层只有顶针 / 底层件离螺钉头 ≥ 2.8/3.5)
与 pcb2_clear.py 焊盘级净距(跨元件 ≥ 0.20)全过;--verify 回读焊盘坐标核了镜像语义
(J23 口朝 +X、R717/R718 对上 A5/B5、J71/U51/U24 都在 layer 2)。
槽的几何(本体坐标,v<0 = 接口边外侧)
| 槽 | u | v | 尺寸 | 给谁 |
|---|---|---|---|---|
| 电池槽 | 5 ~ 43 | −4.2 ~ −1.2 | 38 × 3.0 | BM3E 排线 + 保护板整体穿过(J600 在 u≈23.8) |
| 尾插槽 | 47 ~ 64 | −4.2 ~ −1.2 | 17 × 3.0 | 尾插排线 + BM24 插头(J1401 在 u 47.5~59.7) |
两槽之间 4 mm 筋;槽东端到本体边 3.09 mm,再到邻站 4.41 mm。EDL 两根飞线(TP1204/1205,u 42.6/45.4) 走电池槽东端或尾插槽西端。排线从主板正面(z = 3.8)越过接口边、向下穿槽、在底面继续往 −v 走, 不用折返,所以 TP8n1/2 与 J7n 都排在槽外侧(走廊)的行 A。
⚠️ 槽长按经验估,打样前必须拿实物量:BM3E 保护板长度(决定电池槽 38 够不够)、
尾插排线 / BM24 插头宽度(决定尾插槽 17 够不够)。改 SLOTS 一行重跑 --outline 即可。
底层排法(本体坐标)
v −1.2~−4.2 ═══ 电池槽 ═══ 筋 ═══ 尾插槽 ═══
v −7.5 行 A TP8n1(21) C8n6(23.5) TP8n2(26) C8n2(31) C8n3(36.5) J6n(43.5, v −8.5) J7n(56)
v −12 行 B (西半边空着:差分对 / 电源线的高速路) U5n(56) R76n(60) R77n(62.5)
v +3 行 C C8n4(20.5) C8n5(26) R74n(31) U4n(35) C76n(38.5) · C70n(49.5) U2n(54) C71n(58) C72n(60.5) R70n(63)
v +8 C8n1 引脚 (23.5, 8),罐体往 +v 躺到 v≈27.5(keep-out 12.5 × 17)
行 C 全在主板投影下方,紧贴槽的内侧。跨槽的网络(+5V / VBUSn / EN 进 VBUS 组,EDL 两根进 U4n, VOn_P 岛接 C8n4/5 与 C8n1)都得从槽端绕:4 mm 筋(u 43~47)或槽东端(u > 64,到邻站电池槽之间有 12.5 mm)。 4 A 主路径(排母 → TP8n1)不跨槽,仍在走廊里。
全局件(板坐标,全部底层):J31 (62, 67.5) / J32 (158, 67.5) 没动;Hub 簇 (100, 68),C751 挪到西北角 (96, 74.3) 横放; U31 (87, 73) / C736 (84.5, 77.5) / C737 (92.5, 77.2);U34 (78, 72.6, rot 90) / C760 (78, 76); R721/R722 (83/81, 62.2);J23 (214.866, 62, rot 270) / R717 (210.37, 63.25) / R718 (210.37, 60.75)。
底层镜像语义(实测,写进 skill §9w)
底层 = 封装先在本地系沿 x 轴翻(ly → −ly),再按 rot 逆时针转。两脚件 pin1 方向和顶层一样; rot 0 的 SOT23-6 / BM24 南北两排对调;rot 90 时东西对调。所以 J23 在底层用 rot 270 才口朝 +X, R717/R718 的 y 对调。J7n 在底层 rot 0 时奇数排在南 —— 这改变了插头的物理手性, §24.3 那个「哪一排是奇数排」的镜像位实测必须按底层装法重做。
三条代价(都是决定,写进 §12)
- C8n1 卧倒占高 10 mm,两板净空 13 mm ⇒ 下板在五块罐体投影(
pcb2-bottom-heights.json里 h=10 的五块)下只能放 ≤ 2 mm 的件。 排母 J31/J32 本体 8.5、J6n 3.6、J23 3.2 同理。下板布局前先读这个文件。 - 顶层变成空的(只剩顶针焊盘)⇒ 顶层是一整层自由布线层,比 v1 多出一层;但每站 U4n/U2n 组的 信号都要跨槽,走线比 v1 长 10~30 mm。
- v1 的全部布线作废:11 对差分(
pcb2_route_dp.py/pcb2_dp_long.py的手写几何)、pcb2_pour.py的ISLANDS(五块 VOn_P 岛要重划,且要跨槽)、pcb2_route_sig.py的 77 个网络、 扇出、pcb2_vo_vias.py、pcb2_gnd_patch.py—— 侧车文件(_pcb2_sig_routes.json/_pcb2_gnd_patch.json/_pcb2_vias.json/pcb2-copper.json/_pcb2_route_geom.json)全部过期。 重布顺序:pcb2_rules.py --check(规则没动)→ 重划ISLANDS→pcb2_pour.py --push→pcb2_route_dp.py --dump→ 重写SITE_J(站内坐标,底层版)和 6 对长差分 → 扇出 → 迷宫布线 → vo_vias → gnd_patch。
2026-09-06 补:槽改到远端边(v3)+ C8n1 换矮封装
- 用户第二次调整:槽挪到主板投影外侧、靠板边那一条(本体坐标 v 45.5
48.5),排线按 6 cm 跨过主板正面到远端边、 下穿、折回底面;上排下移 / 下排上移各 2.5 mm(42 五行,SITESy 83.0 / 7.5),板边留 3.5 mm 筋;中跨 M3 孔随之到 y 79.5。 每站器件全部收进主板投影下方(v 21pcb2_place.BAND),走廊只剩 J31/J32、Hub 簇、U31 组、U34、R721/722、J23。 尾插排线全程约 57 mm(J1401 v 2.86 → 远端边 → 槽 → J7n v 36),电池排线约 52 mm。 - C8n1 换矮封装:Rubycon 6.3TPV2200M10X10.5(C3828985,SMD D10×L10.5,液态铝电解 ESR 60 mΩ、纹波 1.19 A,库存 500)。
立创库里这颗器件挂的是直插封装,所以在个人库建了「6.3TPV2200M10X10.5 SMD」(符号复制自立创;封装为
CAP-SMD_BD10.0-L10.3-W10.3-LS11.2-FD_H10.5的副本,渲染图核过焊盘 1 = +)。c4_site.py的P['C2200U']已换, 五页重画 + 六项验证 / 跨页 / port_audit 全过,PCB 导入变更 80 移除 + 80 增加(整页重画的正常现象),pcb2_place.py不再卧倒(CAN_BODY10.3 见方),截图PCB2-v3-c801.png核过极性丝印。 - Inner1 五块岛改成「走廊主体 + 主板下方整条带」(
pcb2_pour.ISLANDSv3),最窄断面 7.05~30 mm,全过。 为差分让位:VO2 主体收到 x 87.3、VO4 收到 x 89 / 89.5(Hub 西侧 x>87.7 顶层差分参考 GND)。 - 为布线做的摆位微调:Hub 西侧 C747/C748 挪到 (88.2, 66.6)/(88.5, 69.625)(十条 D± 车道从 U32 西缘扇开到 0.75 间距、 x 87.7~93.3 放换层过孔);U31 组到 J31 东端南侧 (87.5, 59.5);U34/C760 到 J31 南侧 (58/62.5, 60); R721/R722 (80/78, 61.5);R717/R718 (209, 64.5/59.5)。差分几何本身还没写(下一步)。
2026-09-06 补 2:按实测排线尺寸定槽(v3b)
用户实测:电池排线 8 宽 × 38 长,尾插排线 18 宽 × 55 长。
| 走向 | 槽(本体坐标) | 长度核算 | |
|---|---|---|---|
| 电池排线 | J600 (v 4.6) 越过接口边下穿,折回主板下方的 P+/P− | u 18.8 |
4.6 + 3.8 + 1.6 + ~6 ≈ 16 ≪ 38 ✔ |
| 尾插排线 | J1401 (v 2.86) 跨过主板正面到远端边下穿,折回 J7n | u 37 |
41.8 + 4.2(斜下)+ 1.6 + ~3.5 ≈ 51,余 4 ✔ |
38 mm 的电池排线够不到远端边(光跨主板就要 40),所以电池侧回到接口边;尾插侧 55 mm 走远端边的前提是
J7n 贴着槽放(v 42.5,东端 ≤ 50.8 让开 H1 螺钉头)。每站器件仍全部在主板投影下方
(pcb2_place.BAND v3b:行 A v 3.5 TP+/C8n6/TP−/C8n2/C8n3,行 B v 8.5 C8n4/C8n5 + C8n1 (33, 11),
行 C v 21 EDL 组,行 D v 26 VBUS 组,行 E v 38 R77n/R76n/U5n,行 F v 42.5 J7n,J6n (61.5, 40.5))。
Inner1 主板下方那块收到 v −114;电池槽落在走廊主体里,铺铜自己让开,最窄断面 7.0530 mm,五块实测全过。
U31 组为让开 CH4 的电池槽挪到 (87.5, 60.5) / C736 (80.5, 58.5) / C737 (93, 54),USB1 那对的底层车道改走 y 64.0/64.46。
截图 PCB2-v3b-bottom.png / PCB2-v3b-ch1.png。
2026-09-06 补 3:尾插槽回到 J1401 正下方,J7n 放到主板下方远处(v4,用户拍板)
用户指令:尾插槽放在主板尾插接口(J1401)正下方;载板尾插座放在主板下方远处、50 mm 排线够得到的地方;
连接时尾插排线走载板背面。 事实来源 pcb2_place.py(SLOTS['tail'] / TAIL_LANE / BAND 行 D~F)。
| v3b | v4 | |
|---|---|---|
| 尾插槽(本体坐标) | u 37 |
u 45 |
| 排线路径 | J1401 → 跨过主板正面 → 远端边下穿 → 折回 3.5 | J1401 出线朝接口边 2.9 → 绕过接口边下落 ~5(插头 1 + 主板 1 + 立柱 3)→ 折回主板下方到槽心 2.9 → 穿板 1.6 → 背面往 +v 走 34.1 |
| 长度核算 | ≈ 51 / 55 | ≈ 46.5 / 50(用户给的可达长度),实长 55 再余 5 |
| J7n | (44.5, 42.5) rot 180 | (53.5, 37.0) rot 0,框 u 47.2 |
| U5n / R76n / R77n | J7n 南边行 E v 38 | J7n 北边(插头背后):U5n (49.8, 41.5, rot 180),R76n (52.8, 39.15),R77n (55.8, 39.15) |
| J6n | (61.5, 40.5) | (62.5, 41.0),EDL 飞线随排线走背面 ~40 mm |
| 行 D(VBUS 组) | u 34.5~48 | 整体西移 4.5 → u 30~43.5,让开排线车道 |
| 排线车道 | — | TAIL_LANE u 44.6check() 新增一条),排线要平贴到插头 |
手性的几何推导(决定 J7n 用 rot 0,而不是 v3b 的 rot 180):
- 排线是 1:1 直通(§24.3 用户实测:摊平后同排同序号导通);两个公头同面、相差 180°。
- v4 路径里排线只绕 u 轴弯折(接口边一个 U 形回折 + 槽里一个台阶),不在面内转、不横向翻, 所以排线上任何一点的 u 坐标从头到尾不变。公头 A 的「内排」(沿排线更靠近 B 的那一排)是 J1401 的 −v 排; 排线到 J7n 时是朝 +v 方向来的,公头 B 的内排也是 −v 排。内排对内排、同 u ⇒ J7n 的触点图案就是 J1401 触点图案的平移 (v3b 那条路径同理,也是平移;§24.3 讲的「台阶式 / 朝上座子」那套是母座朝上时的情形,J7n 朝下后不适用)。
- 翻面次数:U 形回折翻一次,台阶不翻 ⇒ 公头 B 朝 +z(朝载板背面),正好插进朝 −z 的 J7n ✔。
- J1401 的 pin1/2 端(G1)在 +u(用户实测右端触点对地导通,顶视接口边朝下)⇒ 平移后 J7n 的 pin1/2 端要在 −u;
自建封装
pin51(pin1/2 端)在本地 −X,底层翻层是「本地 y 翻再转 rot」不改 x ⇒ 底层 rot 0。 rot 180 会把 pin1/2 端(VBUS)放到东边,与 §24.3「VBUS 落到载板这颗的 −X 端」自相矛盾(v3b 没发现,当时把它推给了"事后改焊盘编号")。 --verify回读(CH1,J71 中心 (58.5, 120)):pin1 (54.3, 118.94) / pin2 (54.3, 121.06) / pin51 (52.47, 120) / pin52 (64.53, 120), pin4 (54.65, 121.06) / pin6 (55.0, 121.06) ⇒ 奇数排南、偶数排北,D± 在北排西端,VBUS 西端 ✔。 仍然悬而未决的只有「封装的奇/偶排分配对不对」(§24.3 镜像位)—— 错了 D± 换到南排西端,U5n 绕西端多走 2.5 mm,只改焊盘编号。
站内 D± 短差分(下一步重写 SITE_J):J7n.4=DMJ (49.65, 38.06) / .6=DPJ (50.0, 38.06) 往北 1.6 mm 进 U5n 南排 .3=DPJ (48.85, 40.35) / .1=DMJ (50.75, 40.35)。
两端次序相反,仍然要交叉一次(v3b 结论不变):DPJ 底层直走,DMJ 上顶层从 DPJ 底下穿过去(顶层空的,Inner1 在这里是 GND 底填,参考面干净)。
代价 / 风险:① 排线要从主板反面钻过(立柱只有 3.0 mm),主板反面 u 4463 / v 04 有没有高元件挡道图纸上看不出来,只能试装(§12);
② 排线 18 宽比 BM24 插头宽 6 mm,超出插头的那 3 mm 会搭在 H3 (61.9, 33.7) 螺钉头边上(头 Ø4.5,西沿 59.65;插头东端 59.6),不碰插头本身;
③ H7 (42.6, 3.7) 立柱西沿 44.85 与排线西沿 44.6 差 0.25,排线往东挪半毫米即可。
2026-09-06 补 4:尾插槽挪到与电池槽同一条线(v4c,用户拍板)+ 电池排线直焊座(v4b)
用户指令:尾插槽移到与电池槽同一水平线。⇒ 两条槽都在接口边外侧 v −4.2~−1.2:电池槽 u 18.828.8、尾插槽 u 4565。
排线翻过接口边直接下穿,不再从主板反面 3.0 mm 的缝里钻(补 3 的那条试装风险消失)。背面到 J7n 长了 5.6,
J7n 从 v 37 收到 v 35、中心 u 52.5(让开 H3 螺钉头 3.1):2.86 + 5 + 2.7 + 1.6 + 37.7 ≈ 49.9 ≤ 50,实长 55 余 5。
U5n (48.8, 39.5, rot 180) / R76n (51.8, 37.15) / R77n (54.8, 37.15) 跟着下移 2;TAIL_LANE v −1.2~36.3。手性推导(补 3)不变:只绕 u 轴弯,J7n 仍 rot 0。
同一晚的 v4b 电池侧(§13.5 末尾):J8n 排线直焊座 (22.8, 15.0),电池排线车道 u 18.827.8 / v −1.213,电容组围着 J8n,
C8n1 (34.3, 11.3),Inner1 主板下方那块岛扩到 v 20。
实测:摆位本地检查 / pcb2_clear 846 焊盘 / inner1_check / inner1_verify 五块岛全过,最窄横断面 7.0520.85;
VO3 的纵断面从 12.3 掉到 8.6(x 194.18,CH3 尾插槽 x 193213 在 VO3 走廊主体东端切了个口),仍 ≥ 7.0。
截图 PCB2-v4c-ch1.png / PCB2-v4c-bottom.png。
⚠️ 对长差分方案的影响:补 2 里"USB2/3 上顶层北上 → y 79/80.5 东行"那两条车道会横穿 CH2 的尾插槽(x 121.5141.5, y 78.881.8),
CH1 的槽(x 5070)也压在 USB1 "y 98 东行"的西侧回路之外但 x 36 北上那一段要避开 CH1 电池槽(x 23.833.8)—— 写 pcb2_dp_long.py 时把 10 条槽当障碍。
2026-09-06 补 5:五块主板连槽整体转 180°,接口边一律朝板边(v5,用户拍板)
用户指令:整体旋转主板和槽,两行的槽都靠近板边。⇒ pcb2_place.SITES 的站向翻转(上排 rot 180、下排 rot 0,位置矩形不动):
| v4c | v5 | |
|---|---|---|
| 上排(CH1~3)接口边 | y 83(朝走廊) | y 127.66(朝板边),槽 y 128.86~131.86,离板边 3.14 |
| 下排(CH4/5)接口边 | y 52.16(朝走廊) | y 7.5(朝板边),槽 y 3.3~6.3 |
| 排线 | 从走廊一侧翻下 | 从板边翻下,在背面往板中心走;走廊 y 52.16~83 完全空出来(只剩 J31/J32 / Hub / U31 组 / U34 / J23) |
| 顶针(侧键,v 2.5~7) | 走廊一侧 | 板边一侧 |
| 每站底层件 | 电容组 / J8n 在走廊一侧,J7n/U5n 在远端 | 反过来:J7n/U5n 靠走廊(上排 y 88 |
| Inner1 岛 | 走廊主体 + 主板下方 v −1~20 的窄带 | 走廊主体 + 整条竖带 u 8 |
站内摆位(BAND)、槽(SLOTS)、车道(LANES)、手性推导全部不用改 —— 都是本体坐标,随站一起转。
--verify 里"pin51 在西"改成按本体 −u 判。
实测:本地检查 / pcb2_clear 846 焊盘 / 五块岛全过,最窄横断面 7.05~31.55,VO2 纵断面 7.30(x 87.28,就是那条 Hub 北横带)。
截图 PCB2-v5-bottom.png / PCB2-v5-ch1.png。
⚠️ 对布线的影响:① 走廊北带 y 75.583、x 87100.5 现在是 VO2_P 平面,差分在那里只能走底层(参考 Inner2);
② 五站 U5n 都贴着走廊(离 Hub 近多了,长差分缩短 30~40 mm);③ 10 条槽全在板边,不再挡走廊里的任何车道;
④ 排线从板边翻下来,下板(在载板下面)的边缘 y < 6.3 / y > 128.9 那两条带要给排线让开。
2026-09-06 补 6:v5 差分布线定稿 —— 11 对差分 + Hub 西缘两条 +3V3 车道(已下发,DRC 无新增间距错误)
事实来源:.claude/pcb2_dp_long.py(六对长差分 + +3V3 三条)与 .claude/pcb2_route_dp.py 的 SITE_J(五对短差分,站内坐标)。
v3 版长差分存档在 .claude/obsolete/pcb2_dp_long_v3_2026-09-06.py,只作历史。
出发点的困难:U32(QFN-64,底层)十根 D± 全在西缘 x 95.55、0.5 脚距,中间还夹着 pin5 / pin10 两个 +3V3, 而五个目的地是四面八方(1 西北远处、2 正北、3 东北、4 西南、5 东南)。0.5 脚距的车道之间打不了孔 (孔要离两边车道各 0.645),所以只能像剥洋葱:最北的先拐走,邻居走了才能打孔 —— pair 5 → pin10 → pair 4 打孔上顶层 → pair 3 → pin5 → pair 2。
| 车道 | 层 | 走法 | 备注 |
|---|---|---|---|
| pair 1 | 底 | y 64.25/64.75 直着西行到 x 22.34/22.82,北上进 U51 | 从 J31 底排焊盘(底 65.38)与 U31 pin1(顶 63.35)之间穿过 |
| pair 2 | 底 | 西行到 89.27/89.75 北上,y 80 起 45° 斜到 93.84/95.74 进 U52 | 斜段必须在 pair 3/5 东行车道(y ≤ 77.1)之上;绕开 site2 H1 (89.39, 85.36) |
| pin5 +3V3 | 底→顶→底 | 西行到 90.4 跟 pair 3 北上,(90.4, 70.5) 翻顶层西去 (88.2, 70.5) 下来进 C747 | C747 挪到 (88.2, 71.5) rot 90,夹在 J31 最东列与 pair 2 之间 |
| pair 3 | 底 | 西行到 91.05/91.53 北上,y 76.50/76.98 东行,x 112 压到 75.40/75.88,x 165 北上进 U53 | 压低是为了从 MH (148.1, 79.5) 的 Ø6 焊盘(底 76.5)下面过 |
| pair 4 | 顶 | x 92.2 打孔上顶层(DM 67.95 / DP 68.85),沿 91.5/91.98 南下到 y 52,斜到 (89.6/90.5, 50.3) 下来进 U54 | 全板唯一整段走顶层的一对;底下 Inner1 全是 GND |
| pin10 +3V3 | 底 | 西行到 92.95 跟 pair 5 北上,斜到 (92.5, 70.0) 进 C748 | C748 挪到 (92.5, 71.2) rot 90,夹在 pair 3 与 pair 5 的北上车道之间 |
| pair 5 | 底 | 西行到 93.47/93.95 北上,y 75.50/75.98 东行到 110.30/110.78 南下,y 59.2~61.6 翻顶层跨 UP,y 52.5/52.98 东行,x 160.1/162 南下进 U55 | DP 东沿离 C751 焊盘 0.205;pin13 GND 的孔位留在 (94.6, 71.4) |
| UP | 底 | pin58/59 从 C743/C745 之间的竖井下到 60.12/60.60,一路东行,x 205 抬到 61.25/61.75 平着进 J23 B6/A7 | 不能压在 60.2 —— 会把 B5 (CC2, 60.25) 的走线堵死 |
| J23 短接 | 底+顶 | A6↔B6 / A7↔B7 两个小环,几何照抄 v3,网络对调、跨越段翻到顶层 | 同一对的两根按对内 0.15 判(横线离孔 0.165) |
| +3V3 干线 | 顶 | U31 pin2 旁 (90.3, 61.65) 打孔上顶层,沿 x 90.3 北上到 (90.4, 70.5) 与 pin5 汇合,东去 (92.5, 70.0) 下来进 C748 | 后面信号布线器把这三条 +3V3 当已有障碍,别删 |
| 五对短差分 | 底 + 一段顶 | DMJ 全程底层 45° 斜进 U5n.1;DPJ 翻顶层:出焊盘 0.54 浅斜到 (50.0, 37.0) 打孔,顶层西去 (47.2, 37.4) 下来 45° 进 U5n.3 | 站内坐标,五站同构;两排之间只有 1.515 mm,孔只能落在 y 36.805~37.31 或两侧 |
顶层参考面:所有顶层段都核过「要么全在 GND 上、要么全在同一块岛里」(topref 检查 0 处跨界)。
为此 VO4 岛主体东界从 89 收到 87(pcb2_pour.ISLANDS)—— site4 的短差分顶层段在 x 87.890.9、pair 4 在 x 89.692.2、+3V3 干线在 x 90.3,
原来的 89 正好从中间劈过去。site5 的短差分顶层段整段落在 VO5 岛内部(一整块铜,不跨界)。重铺后 inner1_verify 五块岛各 1 连通域,
最窄 7.05 / 7.20 / 7.70 / 7.60 / 31.55(下限 7.0)。
成对 45° 斜段的规矩:两根线各自的拐点不能同 x / 同 y,第一拐内侧那根早拐 0.2(= 0.48·(√2−1)), 否则斜段上的垂直间距只剩 0.34 < 0.43。转弯时左右次序的判法:向右拐,左边那根变外侧;连拐两次回到原样 —— 五对到站都不用交叉,全靠这条把车道次序排对。
校核:pcb2_route_dp.py 本地净距全过(一般 0.20 / 对内 0.15)、端点全落在本网焊盘、对内偏斜最大 4.75 mm(USB5,容差 5)。
下发 182 线 / 26 孔(回读 178 线,4 条同宽共线段被 EDA 合并,无害)。DRC 634 = 同封装内间距 115(基线)+ 连接性 519(未布线,预期)。
截图 PCB2-v5-dp-hub.png / PCB2-v5-dp-all.png / PCB2-v5-dp-site4.png。
⚠️ 一条工具坑:pcb2_dp_long.chamfer() 原来对每个拐点都切 0.35,包括已经是 45° 的拐(正 + 斜),
切出来的 22.5° 小段会向内挪 0.1 mm —— 实测把 DP4 的抬升段切进了 pin10 车道的净距圈(0.125)。现在转向角 ≤ 46° 不切。
2026-09-06 补 7:v5 载板布线全部完成(扇出 / VOn_P 进岛 / 77 个信号网络)
结论先写:载板 PCB2 布完了。 DRC 115 条,全部是封装自带的「贴片焊盘到贴片焊盘」基线——
间距 0 新增、连接性 0、悬空 GND 连通域 0、五块 Inner1 岛各 1 主域(最窄 7.05)、11 对差分偏斜全过。
铜量:1030 条导线 / 537 个过孔。截图 PCB2-v6-routed-all.png / PCB2-v6-hub.png / PCB2-v6-site4.png。
① GND 扇出(247 孔 / 122 短线)
pcb2_fanout.py 按 v5 重跑。三条和 §25.8 不一样的地方:
- J7n 的 65 个 GND 脚整批不扇(
SKIP_PAD)。它们归bm24_pre()的两条梳子管; 让自动扇出去碰的后果实测是「十个必然失败 + pin 1/2/52 三个『成功』的孔正好落在梳子和车道上」。 - U32 的 pin13 / pin19 往 QFN 肚子里打孔((96.50, 70.25) / (97.25, 71.50))。 西边走廊虽然放得下孔(x ∈ [94.59, 94.625]),但引线出不去:pin13 与 pin14 之间只有 0.20 mm。 引脚环东沿 95.975 到散热盘西沿 97.600 有 1.625 mm 净宽,是这一带最宽敞的地方。
- C745 往南挪 2.7 mm(用户拍板)。原位 (100.05, 61.70) 的 GND 脚四面被堵死:
南
UP_DM东行段 y=60.60(孔要 0.64,只有 0.41)、北是 U32 南排焊盘之间 0.73 的死带(孔要 1.0)、 东 R715(缝 0.667)、西被UP_DP/UP_DM两条竖段夹住(相距 0.5,塞不下 Ø0.6)。 新位 GND 脚 (100.0, 58.60) / +3V3 脚 (100.0, 59.44),孔打在正东 (100.87, 58.60)。
② VOn_P 进岛(55 孔):C8n1.1 和 J8n.1 也是贴片
换成 Rubycon 6.3TPV2200M10X10.5(V-chip)+ 电池排线直焊座之后,
每一路 VOn_P 只剩排母那 3 针是通孔,其余 7 个焊盘(C8n1.1、C8n2~C8n6、J8n.1)都要打孔下岛。
个数按 §10.3「功率网络每个焊盘 3 个孔」:J8n.1(这一路 4 A 的唯一去路)和 C8n1.1(2200 µF 主储能)各 3 个。
⚠️ C8n2~C8n6 仍是各 1 个 —— 这是对 §10.3 的一处有意偏离:
全按 3 个来会往五块岛里再钻 50 个反焊盘,最窄断面(下限 7.0)扛不住;这五颗只承担高频纹波,单孔 1~1.5 A 够用。
③ v5 的 BM24 逃逸:和 v4 反过来
v5 把 J7n 从 rot 180 改成 rot 0 又挪了位置,站内坐标整体差一个仿射映射
u′ = u − 5.00 / v′ = 32.00 − v(v 轴是镜像的)。但照抄映射也不对 ——
v 一镜像,v4 那条「前排外侧 0.76 mm 的缝」换到了另一边,而那一边站着 R76n/R77n。
v5 的实测站内几何:后排(奇数脚,全是 GND)v=33.940;中间大脚 v=35.000(pin51 VBUS u 46.47 / pin52 GND u 58.53); 前排(偶数脚)v=36.060;两排 u 都是 48.30~56.70。
| v4 | v5 | |
|---|---|---|
| 中央通道(1.64 mm) | THERM / CC1 两条东行车道 | 前排 5 个 GND 的梳子(v=35.00,4 个孔) |
| 后排外侧 | 后排 7 个 GND 的梳子 | 同上(v=33.10,5 个孔)—— 但这一侧现在一路空到 v 26,最宽敞 |
| 前排外侧 | 前排 4 个 GND 的梳子 | 只给 THERM / CC1(R76n/R77n 就在正北) |
反过来的理由:v5 后排 25 个脚全是 GND,没有信号脚要往外挤;而 THERM(pin14)/CC1(pin22) 和它们的靶子 R77n/R76n 都在前排外侧。让它们各走各的最短路,中央通道就整条空出来, 不再有 v4 那个「东行车道被竖着穿过通道的 GND 线切断」的死结。
为此挪了 R76n / R77n:v 37.15 → 38.0,R76n 的 u → 52.233。 原来前排逃逸带只剩 0.58 mm(J7n 前排焊盘外沿 36.30 ←→ R76n/R77n 焊盘下沿 36.88), 而 THERM 要往东、CC1 要往北,在 u≈51.8 必然交叉,同层无解;想让 THERM 翻顶层又打不下孔 (要离前排 0.5 ⇒ v ≥ 36.80,又要离 R76n 0.5 ⇒ v ≤ 36.38)。挪完带宽 1.43 mm: CC1 一根直线上去(52.233 是算出来的,好让 pin1 正落在 u 51.800 = J7n.22 正北), THERM 在 (50.95, 37.20)/(54.37, 37.20) 打两个孔走顶层跨过去。
⚠️ THERM 出阵列后第一次拐弯的 v 只有 0.053 mm 的窗口(下受前排焊盘、上受 *_DPJ 的换层孔),
取窗口正中 36.58,而且那两段必须一直保持 0.11 —— 换成 0.15 窗口只剩 0.005,0.20 直接无解。
④ 77 个信号网络:四段必须手写
栅格布线器(0.1 mm 栅格,判据 edt ≥ 净距 + 半线宽 + 0.0708)进不去这几个地方,只能手写坐标:
| 网络 | 卡在哪 |
|---|---|
THERM_n |
上面那 0.053 mm 的窗口 |
+3V3_HUB U32.52→U32.46 |
pin46 在东排被 VBUS_DET/NONREM0 围死,唯一出路是往 QFN 肚子里走(南排焊盘上沿 63.975 与散热盘南沿 65.60 之间那条 1.6 mm 死带) |
+3V3_HUB C750.1→R716.2 |
R716.2 是最东那颗 +3V3 焊盘,南北被 R711.2 / R720.2 两个 GND 脚夹住(各 1.2 mm),只能翻顶层斜拉 |
HUB_RST / VBUS_DET |
R709(y 65.85) 与 R712(y 67.05) 之间只有 0.66 mm。0.15 的线走得过去(上下各 0.23),但栅格判据要 0.371 而半缝只有 0.33 |
⑤ 布线器本身修掉的四个真 bug(写在这里是因为它们都属于「校核过了但其实是错的」那一类)
- 搜索窗口边上没有墙。障碍裁到窗口里再栅格化,完全落在窗外的铜一格都不标 ——
贴着窗口边走的线看不见它。实测
SCL的窗口从 x=44.02 起,J31.6 的焊盘框(42.10~43.80)整个在窗外, 布线器就在 (44.10, 67.40) 打了个孔,离那焊盘只有 0.134。改法:数组往外扩 1.2 mm 标障碍, 再把外面这一圈整体标成占用。 - 钻孔间距不分网络,
viafree却只看异网铜。于是紧挨着pcb2_dp_long已有的孔又打一个 (中心距 0.510,规则要 0.605)。新增holefree距离场。 - 手写前置段没有一开始就进障碍表,排在前面的网络照样从上面碾过去。
+3V3_HUB上pcb2_dp_long画的三条会被push_sig()静默删掉(它按网络整删)。 改成从同一个事实来源取回来当前置段。 ⚠️ 由此产生一个口子:+3V3_HUB现在由pcb2_route_sig.py下发, 再单独跑pcb2_dp_long.py --push会把整个 +3V3_HUB 删掉重画。 要改差分的顺序是dp_long --push→route_sig --push,不能只跑前一半。
另外扇出规划器补了三处:板上已有的走线也当障碍(线对线分层比、过孔对线不分层)、
第三遍「并到旁边同网焊盘」加了 3.0 mm 上限并要求目标同层(原来把 C745.2 一路并到 9.78 mm 外另一层的 J64.3),
以及 dump_pads.py 的位号认领改成最近邻匹配(原来两边各自 Math.round 到 0.01,
落在 .xx5 上的 88 个焊盘认不到主人 —— J75 pin15/16 就在其中,害得「J7n 的 GND 脚整批跳过」漏掉两个)。
26. 下板 PCB1 v6(2026-09-06,两板拆分之后从头重排)
载板 PCB2 布完之后,剩下的就是下板。板上原有的东西是单板时代的产物: 391 个元件、5813 条自动布线、1208 个过孔,网络表和布局都已经过期。这一轮做的是 「导入变更 → 重建约束模型 → 重排摆位」。
事实来源:.claude/pcb1_place.py(摆位)、.claude/pcb1_env.py(环境约束)、
.claude/pcb1-env.json(生成物)、.claude/pcb1-parts.json(真实焊盘框)。
26.1 从原理图导入变更:391 → 338
| 数 | |
|---|---|
| 删 | 70 个(J2 |
| 加 | 17 个(J24 J25 排针;U33 第三片 595;Q6 D2 风扇低边 + 续流;R730 |
| 结果 | 338 个元件,位号与封装逐条对上原理图 11 页(pcb1_import.py --verify) |
⚠️ 导入对话框的变更列表会骗人。它把「将被删掉的元件」复用成「新增的元件」,
显示成一堆 修改封装 C0805 → HDR-TH_40P-...,看上去像是要把一颗 0805 电容变成 40 针排针。
实际结果是对的(位号跟着改),但列表本身读不出这一点,而且虚拟滚动逐屏抓下来还会漏行。
⇒ 判据只有一个:导入之后拿 PCB 的元件表和原理图 BOM 逐条对账(--verify)。
26.2 ⭐ 载板底面 → 下板的高度预算图(pcb1-env.json)
两板净空 13.0 mm(公头塑高 2.5 + 母座塑高 10.5,§22.3f)。 下板坐标 = 载板坐标 − (30, 5)(下板 160×125 居中在载板 220×135 下方)。
pcb1_env.py 把载板 146 个底层件 + 10 条排线车道 + 10 条穿线槽全部折算过来,
每块给一个 hmax = 13 − h(载板件) − 1(装配余量):
| 下板上的位置 | 来自 | hmax |
|---|---|---|
| (1.3 |
C801 / C811 / C821 Ø10 罐 | 1.5 |
| (38.6 |
C831 / C841 | 1.5 |
| (7.0 |
J31 / J32 排母本体 | 3.5(就是排针自己占的地方) |
| J62~J65 四个 1.25 mm EDL 座 | 8.4 | |
| 9 条排线车道 | 排线平贴载板背面 | 11.0 |
| 10 条穿线槽的投影(板边 y<1.3 / y>123.9) | 排线从这里下穿 | 3.0(本模型自己定的) |
| 其余 | 载板那边是 1206 / 0402 / 光板 | 10.3 ~ 12.0 |
⇒ 五块 12.9 × 10.8 的 1.5 mm 禁区是这一版布局最硬的约束:
电感(SPM6530T,3.0)、直插电解(12)、接线端子(10)、风扇座(9)一个都进不去。
pcb1_place.check() 里逐件核算,这一条几何检查以前完全看不见。
26.3 五路怎么分到南北两块 —— 只有一种解
VOn_P 每路 3 针,x 位置由载板几何定死(§25.10):
VO1 10.4 / VO4 46.0 / VO2 53.6 / VO5 126.7 / VO3 142.0。
母版(CH1 表)的输出端在局部 (6, 40.5),也就是左上角。所以
- 放南边(rot 0,原样):输出朝上正对排针 ⇒ 通道占
bx+2.3 ~ bx+29.5,输出 x = bx+6 - 放北边(整路 rot 180):输出转到右下正对排针 ⇒ 输出 x = bx−6
VO1 太靠左板边(rot 180 要求通道体在 x −14 起)、VO3 太靠右板边(rot 0 要求到 x 166)
⇒ CH1 只能在南、CH3 只能在北;剩下三路按互不重叠排下来只有
南 = CH1 (10.6
37.8) / CH4 (42.369.5) / CH5 (121.8149.0), 北 = CH2 (30.157.3) / CH3 (118.5~145.7),南北都是 y 18.259.2 / 66.3107.3。
⚠️ 不做 y 镜像 —— 镜像要把元件翻到底层。转 180° 是纯旋转, 母版里 §10.2 那四条手调出来的关键回路(Cin 热回路 / SW 铜箔 / FB / Kelvin)原样保留。
代价:CH2 的 POGO2_* 三根在 J25 上(x 109114),而 CH2 的体在 x 3057,
要横穿 60 mm。这是载板那边「site2 电源走 J31、信号走 J32」带来的,不是布局失误。
26.4 其余四块
| 块 | 范围 | 内容 |
|---|---|---|
| N-L | x 1 |
P1-INPUT:J1 12V 端子(左板边)→ F1 → Q1 → D1 → C2/C3 罐 → Rs6+U13 → R9;U19 辅助 3V3 组压在 x>14.3(C801 禁区) |
| N-M | x 58 |
P1B(U30 12V→5V + L3)、P6(U33 第三片 595 + Q6/D2 风扇驱动 + TACH 分压) |
| S-M | x 70 |
P3/P3B 控制块:U20 ESP32(天线端转到 −Y 朝下板边)、U6/U7 DAC、U21/U22 595、U23 PCA9555 |
| 板边 | — | J26/J27 左板边、J29/J30 右板边、J28 顶板边(4 进 1 出,§22.6);J22 调试 USB-C 转到右板边(下板边被 C841 的 1.5 mm 禁区压掉了) |
26.5 ⚠️⚠️ J24 / J25 对插针号错位 —— 必须先拍板再布线
pcb1_place.py 的对位核算(拿载板 J31/J32 的实际焊盘坐标反推)结论:
80 个焊盘全部落在载板针的正下方(误差 0.001 mm),但每一个都压在「同一行对里的另一根针」上。 下板 pin1 ↔ 载板 pin2,pin2 ↔ pin1,pin3 ↔ pin4 …… 奇偶整体互换。
也就是说照现在的原理图做出来,下板的 VO1_P 会顶在载板的 GND 上 —— 4 A 直接对地。
成因(几何,已复核):两颗封装的焊盘编号同手性(本地 pin1 都在「西南」角), 而母座装在载板底层、公头装在下板顶层。底层件在顶视图里镜像一次(skill §9w), 于是载板的奇数排跑到 y 68.77(北),下板的奇数排在 y 61.23(南)。 公头 / 母座都是无防呆的 2×20,物理上完全对称,所以「pin1 在哪一排」纯粹是封装画法约定 —— 不存在「哪个封装画错了」,只存在「两边约定不一致」。
§22.2 当时写的「换件之后两块板同一套编号,陷阱消失了」说的是符号; 同一节末尾那句「⚠️ 但 PCB 上那条风险还在」说的就是这一条,现在被实测坐标钉死了。
两条修法(等用户拍板):
| 改什么 | 好处 | 代价 | |
|---|---|---|---|
| A | 下板原理图 P5-BTB 里 J24/J25 的网络奇偶对调(p5_btb.py 只改下板那一半,c1_conn.py 用的表不动) |
不碰器件库;载板一个字都不改 | 两块板的逐针表从此不一样,§22.2 要加一张对照表 |
| B | 建一个焊盘编号奇偶互换的自制封装给 J24/J25 | 两块板逐针表保持一致,看图不用换脑子 | 要建库 + 换器件 + 重新导入 PCB |
✅ 2026-09-06 用户拍板:选 A,已实施
p5_btb.py 新增 MATE_SWAP = True 与 board_rows():两张逐针表仍按载板几何写
(c1_conn.py 生成载板 C1-CONN 时直接用原始表,一个字没动),
生成下板 P5-BTB 时把每一行的 (北, 南) 翻成 (奇数脚, 偶数脚)。
P5-BTB 重画 → verify_sch PASS / xpage 漏接 0 → PCB1 重新导入 → 摆位重推。
从此这颗排针的判据是「网络」不是「针号」:下板 pin(2r−1) 正对载板 pin(2r)。
pcb1_place.py 的 mate_map() / --verify 都改成按网络比,
锚点表 pcb1-env.json 的 anchors 里也一起存了载板侧的网络名
(pcb1_env.header_anchors() 当场从载板 PCB 读回来)。
回读复核:J24 / J25 各 40 个焊盘逐个网络对上载板。
⚠️ 以后谁再看这两页,会觉得「两块板的逐针表对不上」—— 那是对的,就是这一条。
26.6 这一轮踩到的两条
CONN-TH_KF2510-3A-1是弯针座,塑壳整个往 +Y 伸 11.7 mm。 按 ±4.5 猜的占位框让 J28 整个探出板框、J30 压住 J22,本地检查一条都不报。 API 取不到封装本体(lib_Footprint.get()只回元数据,没有图元;组件的丝印也不外露), 最后是用带标尺的放大截图 + 拿它自己的三个焊盘做标定量出来的: 本体 7.8 × 11.9,局部框(-3.90, -0.20, 3.90, 11.70)。 ⇒ 板边连接器的本体框,除了实测没有别的来源;这是本项目第三次栽在同一件事上(USB-A / Molex / 现在 KF2510)。- 低分辨率整板截图不能用来判「有没有出框」。 5.7 px/mm 下 J28 和 U20 都「看着」探出板边, 放大到 30 px/mm 再量,两个都在框内。要判出框就截带板边的局部图。
26.7 下板设计规则(2026-09-06 第十五轮,pcb1_rules.py --check 十七项全过)
单板时代那份 pcb_rules.py 已经不能用了(它建 7 对差分、给 +5V 挂 PWR12V,
拆板之后两条都不对),新写 .claude/pcb1_rules.py 取代它。做法照抄载板
pcb2_rules.py,两个 API 坑和两条陷阱一字不改(见那两份文件头)。
线宽分五档
| 规则 | 默认 | 最小 | 最大 | 挂给谁 | 依据 |
|---|---|---|---|---|---|
PWR12V |
2.0 | 0.3 | 10.0 | +12V + 8 A 输入链三段 |
§10.1:8 A 走 2.0 mm 温升 35 °C ⇒ 总干必须灌铜,2.0 只给分支 |
SWNODE |
2.0 | 0.3 | 4.0 | 五路 Buck 的 SW 节点 | §10.1 表:4 A 的 SW 铜箔 2.0 mm(ΔT 10.4 °C) |
PWR4A |
1.5 | 0.3 | 6.0 | VOn / VOn_F / VOn_P |
每路 4 A(IPC-2221 外层 1 oz,ΔT 16.7 °C) |
PWR5V |
1.2 | 0.3 | 6.0 | +5V + U30 的 SW |
§9.4 最坏 2.8 A(1.2 mm 可载 3.6 A) |
PWR1A |
0.6 | 0.15 | 3.0 | +3V3、SW3V3 |
§9.3 辅助 Buck 按 0.5 A 设计 |
SWNODE 为什么要和 PWR4A 分开、而且 max 卡在 4.0:SW 是开关节点,
铜越宽 I²R 越小、但 dV/dt 的辐射面积越大(§10.2-2「压到刚好够载流」)。
PWR4A 的 max 6.0 是留给灌铜出线的,SW 不该享受那个上限 —— 分成两条规则,
DRC 才拦得住「顺手把 SW 拉成一大片铜」。
差分对只剩 1 对 DEBUG(USB_DP/USB_DM,J22 → U20)。
五路下行 D±、UP_* 和五段 *J 在 2026-09-04 拆板时整体搬去载板,
下板上这些网络已经不存在 —— 建不上不是失败,是本来就不该有。
strokeWidthMin 保持 0.20(不像载板降到 0.10):这一对路上没有 0.35 mm 间距的连接器要钻。
⭐ 四类干路是自动命名网,按「位号 + 引脚」当场反查,不写死网名
拆板那次导入变更之后,同一个节点的自动网名从 $2N687 变成了 $2N699。
写死网名的后果是静默失效:overwriteNetRules 只改它认得的行,
认不出的名字既不报错也不留痕,DRC 照样干干净净,
而板上那条 4 A 干路的线宽规则已经悬空了。
⇒ 事实来源是 pcb1-parts.json 里每个焊盘自带的 net,resolve_auto()
拿 (位号, 引脚号) 反查,并逐条断言「是 $ 开头 / 互不重复 / 链路另一端查到同一个网」,
对不上就直接退出,一个字都不下发。本轮实际查出来的 14 个:
| 逻辑名 | 网名 | 规则 | 探针 / 校核端 |
|---|---|---|---|
SW1~SW5 |
$2N665 $8N665 $10N665 $12N844 $14N665 |
SWNODE |
Ln01.1 / Un.11 |
VO1_F~VO5_F |
$2N699 $8N699 $10N699 $12N878 $14N699 |
PWR4A |
Rsn01.2 / U(13+n).5 |
VIN_RAW / VIN_FUSED / VIN_SW |
$1N223 $1N227 $1N236 |
PWR12V |
J1.2/F1.1、F1.2/Q1.1、Rs6.1/C2.1 |
SW5V |
$16N18 |
PWR5V |
L3.1 / U30.2 |
⚠️ 顺序从此是 pcb1_import --apply → pcb1_parts_dump → pcb1_rules --push。
少跑中间那一步,反查用的就是旧网名,28 个指派里有 14 个会静默落空。
铺铜全连接(PLANE-DIRECT,connectMode = 1)挂 9 个网络
VO1_P~VO5_P、+5V、$1N223/$1N227/$1N236。理由和载板 §25.11 同一条:
不是怕十字花烧(辐条只有 0.254 mm 长、两端焊在大铜面上,8 A 下 ΔT ≈ 0.3 K,
实算见 pcb2_rules.py),而是铺完之后铜面几何要量得准 ——
十字花时铜面多边形把自己的焊盘挖空,断面测量会读到一个 0.3 mm 的假瓶颈,
真瓶颈和度量假象在数据上分不出来。
内层铺铜的全连接没有手焊代价(焊接热走的是外层),所以下板比载板放得开:
8 A 输入链的三段上挂着 J1 端子和 C2/C3 两颗直插电解 —— 那是全板电流最大的通孔焊盘。
不进来的两个不是忘了:GND 有 47 个通孔焊盘、同时贴 Inner1 与 Inner2,留十字花;
+3V3 / VOn 一个通孔焊盘都没有(全是贴片),connectMode 对它们是空操作。
顺手清掉的板框陈迹
layer 11 上原来是「1 条闭合多段线 + 4 条早年的直线」。四条直线和多段线的四条直边 完全重合(都是 0/196.85 → 6299.216/4921.26 mil 那一圈),删掉之后 layer 11 只剩 1 条闭合多段线 —— 这是自动布线器取板框的硬要求(PROGRESS「三条最贵的教训」第 1 条)。
26.8 下板 Inner2 怎么分 —— 算出来是三块,不是草案里的八块
事实来源 .claude/pcb1_pour.py(REGIONS 是唯一的定义,跑一次全部校核 + ASCII 分块图)。
上一轮 PROGRESS 写的「+12V / +5V / +3V3 / VO1~VO5 八块」是草案。逐条算下来只剩
+12V 一大块 + +3V3 南部两块,其余全部退回走线。
判据:内层 0.5 oz 和外层 1 oz 差了约 4 倍
IPC-2221 A=(I/(k·ΔT^0.44))^(1/0.725) mil²,内层 k=0.024 / t=0.685 mil,
外层 k=0.048 / t=1.37 mil —— 两个系数都翻倍,所以同样电流外层只要内层约 1/4 的宽度:
| 电流 | 内层 0.5 oz | 外层 1 oz |
|---|---|---|
| 8 A | 18.2 mm | 3.49 mm |
| 4 A | 6.99 mm | 1.34 mm |
| 2.8 A | 4.27 mm | 0.82 mm |
| 2.0 A | 2.69 mm | 0.55 mm |
| 0.5 A | 0.40 mm | 0.08 mm |
⇒ 「要不要占内层」的门槛比直觉高得多。 这块板 338 个元件全在顶层、 底层整层是空的,一条 1.2 mm 的底层线就能带 4 A —— 短距离大电流根本不该上内层。
逐个网络的结论
| 网络 | 实际跑多远 / 多大 | 结论 |
|---|---|---|
+12V |
源 Rs6.2 (9.6, 91) 在北左,负载散布南北五路 + 五个风扇,南边要 5.6 A | ✅ Inner2 主平面(3 块) |
+3V3 |
源 L2 (25.5, 104),64 个焊盘遍布全板,但只有 0.5 A | ✅ Inner2 南部 2 块 —— 要的不是载流,是「64 个焊盘各打一个孔就完事」 |
+5V |
源 L3.2 (73.3, 78),去处全是排针上那 10 个通孔针,最坏 2.8 A | ❌ 底层 1.2 mm 干线(PWR5V)。外层 0.82 mm 就够 |
VO1~VO5 |
Buck 输出 → eFuse,通道体内约 12 mm | ❌ 顶层 1.5~2.0 mm(PWR4A)。§10.2 本来就要求这段回路面积最小 |
VO1_P~VO5_P |
分流电阻 → 排针,只有约 9 mm | ❌ 底层五块小岛(排针那 3 根针是通孔,一铺就自动连上,省掉三条 4 A 走线) |
| 8 A 输入链三段 | J1→F1→Q1→C2/C3→Rs6,全长只剩 25 mm | ❌ 顶层宽铜 ≥3.5 mm(见下) |
⚠️ 8 A 输入链改走顶层 —— 和 §10.4 不一样,是有意的
§10.4 是给 v5(单板时代)写的,那时这条链被摊开到 85 mm。v6 已按 §10.2b 收进北左角
(x 328, y 6991)、全长 25 mm,于是两个新事实起了作用:
- 内层扛不动。 8 A 在 0.5 oz 内层要 18.2 mm 宽,那个角落总共才 22 mm 高,三段排不下。
- 过孔才是真瓶颈。 F1 / Q1 / D1 / C4
C6 全是贴片,下内层只能靠过孔; Ø0.3 过孔单孔 11.5 A、扇出每个焊盘给 3 个 ⇒ 一个转换点最多 3~4.5 A ≪ 8 A。
顶层是零过孔的最短路径(这条链上每个元件都在顶层),1 oz 外层 8 A 只要 3.49 mm, 而那个角落横向有 25 mm 可用。这正是 §10.1 原文三个选项里的「顶层灌铜 ≥3.5 mm 宽」。 Inner2 那一片留给 GND 底填,顺带给这条大电流回路铺了一整块贴身地平面,比原方案还好。
排针把 Inner2 劈成南北两半 —— 只有三条通道
J24 焊盘 x 6.9757.03、J25 x 102.97153.03,两排 y 61.2 / 63.8。Ø1.8 焊盘 + 0.2 净距
⇒ 同排相邻反焊盘之间只剩 0.34 mm、两排之间 0.4 mm 的铜网 —— 数值上没断,电气上当断路看。
| 通道 | x | 净宽 | 内层能带 | 用途 |
|---|---|---|---|---|
| 左 | 0.5 ~ 6.7 | 6.2 mm | 3.7 A | 不用(北端被 J1 (6,74) 和 C2.1 (4.8,82) 两个通孔掐到 2.8 mm、只剩 2.06 A) |
| 中 | 57.3 ~ 102.7 | 45.4 mm | — | +12V 中桥 (x 61.5 |
| 右 | 153.3 ~ 159.5 | 6.2 mm | 3.7 A | +12V 右通道 (x 153.5~159.5) |
南边要 5.6 A(CH1 + CH4 + CH5 各 1.6 A + 左右四个风扇各约 0.4 A)。 分法:中桥喂 CH1 + CH4 + 左风扇 = 3.6 A(实测断面 10.5 mm → 5.4 A), 右通道喂 CH5 + 右风扇 = 2.0 A(6.0 mm → 3.6 A)。
⚠️⚠️ 一条拓扑上绕不过去的结论:+3V3 南部必然被 +12V 中桥切成两半
中桥必须从北 (y≥88) 穿到南 (y≤34),也就是纵向穿过 y 41~58.5 这条带;
而 +3V3 的南部焊盘(CH1/CH4 的 INA226 与上拉、控制块、CH5 那一组)
正好横向铺满同一条带。同一层上,两个都要连通的 2-D 区域,交叉是避不开的。
⇒ 让电流小的那个换层:+3V3 只有 0.5 A,
南西块与南东块各自从北边的源单独引一条底层干线(0.6 mm 足够,底层是空的),
不在 Inner2 上强行连通。+3V3 有 2 个连通域是设计意图,不是漏接 ——
pcb1_pour.py 里那一条校核写死的就是「等于 2」。
这和载板 §25.10 取消 +5V / +3V3_HUB 两块岛是同一类判断。
落地成这样(REGIONS 的顺序 = 铺铜优先级,GND 底填必须最后)
| 层 | 网络 | 名称 | 形状 |
|---|---|---|---|
| Inner2 | +12V |
12V-N |
北带 y 88 |
| Inner2 | +12V |
12V-SW+BR |
南西块 (0.5 |
| Inner2 | +12V |
12V-SE+RC |
南东块 (116 |
| Inner2 | +3V3 |
3V3-SW |
(0.8, 41)–(58.5, 58.5) |
| Inner2 | +3V3 |
3V3-SE |
控制块 (73 |
| Inner2 | GND |
GND-FILL-L3 |
剩余全部(含北左角那一片,垫在 8 A 顶层大铜下面) |
| Bottom | VOn_P |
五块小岛 | 各约 18 × 13 mm,框住 Rs*01.1 + INA226 两脚 + R*19 + 排针 3 针 |
| Inner1 | GND |
GND-L2 |
整板,只挖 ESP32 天线区 |
⭐ 校核当场抓出来的一个错:孤岛判定是按铺铜对象算的,不是按网络
第一版按几何写成六个矩形(北带 / 中桥 / 风扇指 / 南西 / 南东 / 右通道)。
栅格连通性说「+12V 是 1 个连通域」—— 看着完全正常。但新加的孤岛规则校核报出来:
12V-RC(右通道,x 153.5159.5 / y 3488)里一个 +12V 焊盘都没有。
载板 pcb2_pour.py 文件头第 4 条那句「区域内没有本网焊盘/过孔 = 整块被当孤岛删光」,
判定粒度是每个铺铜对象各算各的 —— 哪怕它和北带紧挨着、铺出来是连续铜,
它自己那一块里没有本网焊盘/过孔,照样会被删掉(边框还在、nPoured 是 0)。
⇒ 把中桥并进南西、右通道并进南东、风扇指并进北带,凑成三个 L / ⌐ 形多边形,
每块各自含 J28.1 / J26.1 + J27.1 / J29.1 + J30.1,不依赖扇出就活得下来。
+3V3 那两块则是 0 个通孔焊盘、全靠扇出过孔活着 —— 这就是「扇出必须排在铺铜之前」的原因。
还有两条校核经验
- 只有通孔焊盘在内层挖反焊盘,贴片焊盘对内层完全透明。 按「所有焊盘都挡内层」去算, 这块板 1200 多个贴片焊盘会把 Inner2 算成一张网,结论全错。板上实测 122 个通孔焊盘。
- 区域间净距不能用包围盒估。
3V3-SE是个 L 形,它的包围盒 (73,9)-(148,86.5) 把12V-FAN(96.5,66.5)-(112,88) 整个罩进去,按包围盒算出来是 0.00 mm、像一条严重违规, 实际两块相距 0.50 mm。改成逐边线段距离才对。
明知故犯:21 个焊盘不进平面,靠布线
+12V 2 个 + +3V3 19 个,全部有名有姓地写在 pcb1_pour.py 的 ROUTED_PADS /
ROUTED_BLOCKS 里,校核时单独列出来而不算「漏掉」:
| 焊盘 | 为什么 |
|---|---|
U13.8 / U13.9(+12V)、U13.6 / C11.1(+3V3) |
Kelvin 脚。§10.4:U8~U13 的取样脚一律不进铜面,5 mΩ 分流器满量程才 20 mV |
CH2 / CH3 的 10 个 +3V3 |
在北边、各 50 mA;沿 y≈84 那条空带走顶层线到 3V3-SE 北臂 |
北左辅助 Buck 那一窝(L2.2 R2.2 C9.2 C10.2) |
U19 / L2 / C7 |
C739.1(+3V3) |
一颗去耦电容孤零零落在风扇指里,走 11 mm 顶层线到 U33.10 |
26.9 下板扇出(2026-09-06 第十六轮)—— 438 个过孔 + 441 条短线,DRC 间距 0
做的是 §26.8 定的第 3 步「扇出」。真正花时间的不是扇出本身,而是扇出把三个 早就在、但一直没被任何检查碰到的错顶了出来。三个都属于同一类: 几何检查全绿,板子是错的。
⭐⭐ 错一:控制块的去耦电容全都离本尊很远,ESP32 那对在 48 mm 外
追「U6.15 为什么扇不出去」时发现的:那个脚周围 6 mm 内没有任何同网焊盘可以并过去。
往外查了一圈,全板 20 个 IC 的 +3V3 电源脚里,只有 1 个的去耦在 3 mm 以内。
| 电容 | 是谁的 | 原来的距离 |
|---|---|---|
| C601 22 µF「ESP32 储能」 | U20.2 | 48.2 mm |
| C602 100 nF(同为 P3 页 ESP32 的) | U20.2 | 45 mm(碰巧贴在 U22 旁边) |
| C607 / C610 | U6.15 / U7.15 DAC VDD | 10.5 / 11.0 mm |
| C604 / C605 / C606 | U21.10 / U22.10 / U23.24 | 8.2 / 8.8 / 9.2 mm |
U20 的电源脚周围 12 mm 内一个元件都没有。ESP32-S3 发射时是几百 mA 的突发电流, 48 mm 外的储能电容等于没有。
根因很具体:pcb1_place.py 里控制块是
affine(['P3-CONTROL','P3B-EXPAND'], 73, 34, 42, 22) —— 把两页原理图坐标整体仿射映射
进一个矩形。它保的是「原理图上挨着的板上也挨着」,保不住「去耦贴着电源脚」;
而 U20 / J22 / RT60x 是上面手工单独摆的 —— 芯片被拎出了仿射集合,去耦却留在了原地。
⇒ 新增 DECAP 表 + place_decaps():表里的电容不参与仿射,等芯片摆完之后
绕着本尊的电源脚一圈圈往外找第一个放得下的位置。两条经验:
- 表的顺序 = 抢位置的顺序,小的高频那颗必须排在大的储能之前。 反过来实测过: C601(1206,本体 4.7 × 1.7)先占掉贴身那一圈,C602 只能落到 3.52 mm 外 —— 而两颗里真正要贴身的恰恰是 100 nF 那颗。
- 上限是每颗一个数,不是全表一个数(
DECAP第四列)。100 nF 靠的是自身低 ESL, 只有贴身才有意义;22 µF 管的是毫秒级电流坑,几毫米走线电感对它无所谓。 给储能 8 mm,它自然会让开贴身那一圈。
改完的结果:C602 → U20.2 1.46 mm,C601 → 3.31 mm,其余五颗 0.76 ~ 2.24 mm。 全板只动了 34 个元件,全部在控制块内(外加那两颗跨半块板搬过去的)。
⭐⭐ 错二:pcb1-parts.json 的包围盒漏了焊盘自身的旋转
改完摆位,本地六项检查全过,DRC 却报出 4 条间距错误 ——
C607_2 到 U6_13 只有 3.8 mil(0.096 mm),规则要 7.9 mil。
pcb1_parts_dump.py 里 w = p.pad[1]; h = p.pad[2],没有用 p.rotation。
QFN / SOIC 的侧边引脚就是同一个长条焊盘转 90° 用的:U6(WQFN-16)北排脚是
RECT 0.80 × 0.28 转 −90°,真实是 0.28 宽 × 0.80 高。不转的话
U6 的 bb 在 y 上短 0.26 mm,而摆位检查、铺铜反焊盘全都吃这个 bb。
⚠️ 这一套 API 里
getAllPinsByPrimitiveId给的 rotation 是度, 而pcb_PrimitivePad.getAll()给的是弧度(见pcb_fanout.py文件头坑 1)。
影响面实测只有 8 个元件(U1~U5 的 VQFN-14、U6/U7 的 WQFN-16、U20 的模组), 但正好都是这块板上最贵的几颗。修完 bb 各长 0.26 ~ 0.30 mm。
由错二引出的新检查:焊盘到焊盘净距(pad_clearance_errs())
原来 check() 只查「元件包围盒重不重叠」。不重叠不等于够净距 ——
C607 那次包围盒还差 0.358 mm 不碰,焊盘之间只剩 0.096 mm。
新的检查直接照着 DRC 那条规则算(0.2 mm / 7.9 mil),量的是焊盘不是包围盒,
跨元件、跨网络才查(同元件内部是封装厂商定的,同网铜可以贴在一起)。
全板 1171 个焊盘跑下来 一条不报,和布线前 DRC 间距基线 0 对得上 —— 互为交叉验证。
⭐ 错三:pcb_fanout.py 有两处还指着上一版的事实来源
两处都是静默失效:不报错、不留痕、DRC 干干净净。
TARGET还停在 §26.8 之前,里面有VO1~VO5、+5V、以及 8 A 输入链三段。 §26.8 已判定这三类都不上 Inner2 ⇒ 照原样跑会给它们打一堆接不到任何铜面的悬空过孔。 ⚠️ 第十五轮刚把 8 A 那三段的写死网名改成resolve_auto()反查,那个改动本身是对的, 只是 §26.8 随后判定它们根本不该下到 Inner2。别再把它们加回TARGET。_pour_filter()指着pcb_pour.py—— 单板时代 v5 的铜面几何。 现在改指pcb1_pour.REGIONS,并且每个网络都要过这一关,不再分 「完整覆盖 / 只盖一部分」:Inner2 是分割电源面,连+12V都只盖三块 L/⌐ 形。 实测这一条在干活:+3V3的 61 个贴片焊盘里 17 个落在铜面外, 不滤掉就是 20 多个悬空过孔。 判据是过孔中心在不在多边形里,不要求整个过孔都在 —— 铜面内缩 0.5、过孔离板边 0.6,板边那一圈 GND 过孔的铜环本来就探出去 0.3。
扇出规划器这一轮补的四条(都是被真实焊盘逼出来的)
FANOUT_WHY=U6.15调试开关:把这个焊盘所有候选孔位卡在哪一道校核上按次数打出来。 「周围太挤」四个字查不出任何东西,而每次卡住的原因都不一样。- 第三类并线锚点:这一轮已经扇出成功、身上已经有过孔的同网焊盘。 原来只认「通孔 / 散热盘」。0.5 mm 间距 QFN 的中间脚一旦被邻脚的过孔堵住正北那条 唯一出路就只能报失败 —— 哪怕 0.8 mm 外就趴着一颗自己的去耦电容。
- 起止两个焊盘自己的孔不算障碍。 并线的终点本来就落在锚点上,而锚点常常正是一个 自带钻孔的焊盘(QFN 散热盘里那个 Ø1.02 热过孔)。把它当障碍 = 「这条线不许接到它要接的那个焊盘上」。U6.14 唯一的出路就是被 U6.17 自己的孔挡掉的。
PREFER_LINK:宁可并线也不要自己那个过孔。 U6 北排四个脚里 pin14 是 GND、pin15 是 +3V3。GND 那一遍先跑,pin14 顺利在正北打了个孔, 那个孔的铜箔正好卡在 pin15 唯一的出线走廊上 —— 于是 pin15 既打不了孔也并不过去。 而 pin14 南边 0.25 mm 就是自己的散热盘(自带热过孔,本来就通全层),并过去 0.45 mm 完事, 比它自己占一个过孔还短。这是「谁更没得选谁先占」,不是特例补丁。- 并线也能退到窄线宽(0.3 → 0.2 → 0.15)。 U6.15 并到 C607.1 时,线心到 C607.2 有 0.346 mm,0.3 的线要 0.35 —— 差 0.004 mm 整个脚就断在那里。 并线走的是 mA 级的地 / 3V3,规则里最小线宽 0.102。
结果
| 网络 | 目标层 | 贴片焊盘 | 过孔 | 并线 |
|---|---|---|---|---|
GND |
Inner1 (15) | 250 | 256(含 6 个散热盘的盘内阵列共 14 个) | 2 |
+12V |
Inner2 (16) | 56(跳过 U13 两个 Kelvin 脚) | 98 | — |
+3V3 |
Inner2 (16) | 44 在铜面内 / 17 靠走线 | 44 | 2 |
VO1_P~VO5_P |
Bottom (2) | 各 4 | 各 8 | — |
板上 438 个过孔 + 441 条短线,全部网络失败 0 个。 DRC:间距错误 0 / 连接性 1336(还没铺铜,预期之内)。
⚠️ 扇出之后连接性数字会先涨再跌:布线前基线是 1145,扇出完是 1336 —— 过孔本身是新对象,在铺铜之前每一个都是自己网络里的孤岛。铺完 Inner1/Inner2 才会掉下去。
26.10 下板铺铜下发(2026-09-06 第十六轮,pcb1_pour.py --push / --verify)
§26.8 定的第 4 步。--push 整套流程照抄载板 pcb2_pour.py(那边跑通过两轮),
三条硬约定原样保留,不重复写了:顺序即优先级 / create() 成功了也会抛 /
点列末尾要把首点再写一遍(见 pcb1_pour.py 的「下发」段注释与 skill §9j、§9k)。
⭐ 这一轮真正新加的是「下发后按实测铜再校核一遍」,而且和下发前共用同一段代码
grid_checks(G_, pads, chk) —— 连通域 / 断面 / 焊盘覆盖三条。
下发前的 G_ 由 REGIONS 栅格化而来,下发后的 G_ 由
getState_PourFills() 回读的真实多边形栅格化而来,跑的是同一个函数。
分成两套写,「预测过了、实测也过了」就只证明两套代码各自自洽, 证明不了板上那块铜真的是计划里那块铜。
回读那一段的两个坑:
- 环是
x1 y1 'L' x2 y2 ... 'ARC' 角度 ex ey ...——'ARC'后面第一个数是角度不是坐标, 按奇偶分 x/y 会整体错位(载板那边把包围盒算成过 −22.9 ~ 219.4)。 这块板实测有 1485 段圆弧(反焊盘),这里按弦处理,反焊盘会算大一丁点 —— 偏保守。 - 不能逐格做 point-in-polygon。一整层地平面二百多个环 × 32 万格,Python 里要跑几分钟。 改成扫描线 + 奇偶规则(环套环就是洞),秒级完成。
⭐⭐ 新校核:每一块碎片都要有本网的过孔 / 通孔落脚,否则是浮铜
铺铜自己的孤岛判定只在「重建」那一刻生效,而且它认的是铺铜对象; 一个对象铺出好几块的时候(Inner2 的 GND 底填被三块电源面切成 3 段), 单独某一段有没有落脚点它是不管的。 浮铜在 DRC 里只会变成几条连接性错误,混在几百条「还没布线」里根本挑不出来。
实测:9 组 (网络, 层) 的全部 12 块碎片都有本网过孔/通孔落脚。
实测结果(--verify,24 项全 OK)
| 层 | 网络 | 铺出来的面积 | 连通域 | 计划 |
|---|---|---|---|---|
| Inner1 | GND |
19610 mm² | 1 | 1 ✅ |
| Inner2 | +12V |
9778 mm² | 1 | 1 ✅ |
| Inner2 | +3V3 |
4286 mm² | 2 | 2(南西/南东,§26.8 拓扑上避不开)✅ |
| Inner2 | GND 底填 |
5290 + 2191 + 94 mm² | 3 | 被三块电源面切开,预期之内 |
| Bottom | VO1_P~VO5_P |
194~307 mm² | 各 1 | 各 1 ✅ |
13 条断面全部达标,而且实测普遍比计划宽(如「北大块 @Rs6 东出」计划 28.75 mm、
实测 36.50 mm)—— 计划里的反焊盘按 焊盘半宽 + 0.2 一刀切,比真实反焊盘保守。
方向是对的:实测 ≥ 计划。
+12V 61 / 63、+3V3 45 / 64 个焊盘落在自己的平面上,其余 21 个是
§26.8 那张「明知故犯」表里有名有姓的,一个不多一个不少。
DRC
| 阶段 | 间距错误 | 连接性错误 |
|---|---|---|
| 布线前基线(板上一根铜都没有) | 0 | 1145 |
| 扇出下发之后 | 0 | 1336 |
| 铺铜下发之后 | 0 | 733 |
⚠️ 扇出之后连接性会先涨(1145 → 1336):过孔本身是新对象,铺铜之前每一个都是 自己网络里的孤岛。铺完 Inner1 / Inner2 才一次性掉到 733。 只看扇出完那一步会以为扇出把事情弄坏了。
26.11 8 A 输入链的顶层宽铜(2026-09-06 第十七轮,已下发并回读复核)
做的是 §26.8 定的第 5 步,也是全板唯一一条 8 A 的路。三段一律顶层灌铜,
定义在 .claude/pcb1_pour.py 的 REGIONS 里,和 Inner2 / Inner1 / Bottom 那 12 块
走同一套 --push / --verify。
| 铺铜 | 网络(当场反查) | 面积(实测) | 覆盖 |
|---|---|---|---|
VINRAW-TOP |
$1N223 |
46 mm² | J1.2(端子) → F1.1 |
VINFUSED-TOP |
$1N227 |
19 mm² | F1.2 → Q1.1~3(SOP-8 源极三脚) |
VINSW-TOP |
$1N236 |
284 mm² | Q1.5~8(漏极) → D1 → C4/C5/C6 → C2/C3 → Rs6.1 |
实测断面(顶层 1 oz,ΔT=20 °C,都是回读实测铜量的,不是按计划算的):
| 位置 | 连续铜宽 | 能带 | 要 |
|---|---|---|---|
| RAW J1→F1(x=10) | 5.00 mm | 10.4 A | 8 A |
| FUSED F1→Q1(x=17) | 5.00 mm | 10.4 A | 8 A |
| SW Q1 漏极西出(x=21) | 12.00 mm | 19.6 A | 8 A |
| SW C4 旁缩腰(x=24) | 8.75 mm | 15.6 A | 8 A |
| SW 干道(x=12) | 4.75 mm | 10.0 A | 8 A |
| SW 干道拐北(y=79) | 21.50 mm | 29.9 A | 8 A |
| SW 北柱 @C2 上方(y=86) | 7.00 mm | 13.2 A | 8 A |
| SW 北柱 @Rs6.1(y=92) | 5.00 mm | 10.4 A | 8 A |
最窄的两处是 4.75 / 5.00 mm,8 A 下 ΔT 分别约 12 / 11 °C。
走法:一条 ⌐ 形干道,全程零过孔
y 93 ┌──┐ Rs6.1(分流器西脚),北柱到此为止
│北│ —— 再往北是 U13 的 Kelvin 脚,不铺
y 86 │柱│ ┌─┐ 右边那条竖的是 C4/C5/C6 去耦指
y 83 ├──┤C3│ │
y 81 │ └┬─┘ │ C2/C3 两颗体电容各开一个口袋
y 76 └───┴────┴──────────────┐ ← 8 A 干道 y 76~80.95(净 4.95 mm)
y 70 Q1 漏极 + D1 │
y 68.6 └
x1.5 x12 x19.6 x28.9
VIN_SW 是一个铺铜对象、24 个点的直角多边形,不是几块拼的 —— 理由见下面第 3 条。
⭐ 三件这一轮才想清楚的事
1. 顶层和内层挡路的东西根本不是同一批。
| 通孔焊盘 | 贴片焊盘 | 过孔 | 走线 | |
|---|---|---|---|---|
| 内层 Inner1/2 | 挡 | 不挡(对内层完全透明) | 挡 | 挡本层的 |
| 外层 Top/Bottom | 挡 | 挡 | 挡 | 挡本层的 |
Grid 原来只会挖「异网通孔焊盘」—— 那是给内层写的。照搬到顶层,
这块角落里 D1.2 / C4.1 / C5.1 / C6.1 / R1.1 的 GND 贴片焊盘、
扇出给它们打的 9 个过孔、以及 Rs6.2 那两条 1 mm 宽的 +12V 出线,一样都不会被算进去,
铺出来的 8 A 铜会比算的窄一大截,而所有断面数字都还是绿的。
⇒ Grid.__init__ 加了 outer 分支 + obstacles()(过孔全层挡、走线只挡本层),
snapshot() 发现缓存里没有 via/line 就强制重抓。
2. ⭐⭐ 0.25 mm 的栅格漏掉了一处 0.101 mm 的侵入。
check_top_clearance() 是这一轮新加的不过格子的校核:顶层三块铜的多边形,
到每一个异网铜(焊盘框 / 过孔 / 走线,含线宽)的真实几何距离必须 ≥ 0.2 mm。
它当场抓出两处,栅格只抓到其中一处:
| 侵入 | 栅格看得见吗 | 成因 |
|---|---|---|
干道东端 ↔ C4.1 的 GND 脚,0.096 mm |
看得见(挖掉 7 格) | 边界写在 23.2,C4.1 西缘在 23.296 |
| 北柱东缘 ↔ Rs6.2 的 +12V 出线,0.101 mm | 看不见 | 那条线 1.0 mm 宽、圆头端帽往外多探 0.5 mm,实际铜到 x 6.901,而边界写在 6.8 |
第二条是这一类错的标本:线的端点不是铜的端点,端帽要按半线宽外扩;
0.101 mm 的侵入在 0.25 mm 栅格上一个格心都落不进去 ⇒ 栅格全绿。
真下发下去,EDA 自己会往回缩一点点铜 —— 板子不会有 DRC 错,
但板上那块铜和这里写的那块铜就不是同一块了,后面所有断面数字全部作废。
⇒ 边界改成 23.05 / 6.65,并顺手把北柱西缘从 2.6 挪到 1.5(离板边仍有 1.5 mm),
@Rs6.1 那道最窄断面从 4.25 涨到 5.00 mm。
3. VIN_SW 必须是一个铺铜对象,不能拆成几块靠重叠连起来。
第一版按几何拆成四块(干道 / 漏极块 / 电容指 / C3 口袋),各自都含本网焊盘、 孤岛规则也过。但同层同网两块铜重叠时,低优先级那块会被高优先级那块裁掉, 裁的时候留不留 0.2 mm 净距,API 文档没说。留了的话,干道和漏极块之间就是一条 看不见的缝 —— 而且连接性 DRC 也报不出来,因为两边各自都还连在自己的焊盘上。 ⇒ 合成一个 24 点的直角多边形。
手写 24 个点的代价是「写错一个坐标什么检查都发现不了」(断面照样够宽、
连通域照样是 1、净距照样过,错的地方正好没被任何一条断面线量到)。
⇒ 区域里多带一个 rects=[...](这 24 个点该等于的 8 个矩形),
poly_vs_rects() 用 0.05 mm 的细格逐格对照。写错一个点当场报。
不进宽铜的三个焊盘(都是有意的,写在 ROUTED_PADS 里)
| 焊盘 | 为什么 |
|---|---|
U13.10($1N236) |
Kelvin(VIN+)。Rs6 满量程才 40 mV,取样脚要单独引细线到 Rs6.1,不能从大铜面上随便找个点接。北柱顶端 y 93.0 那一小截是死头、不过电流,正好当取样点 |
DZ1.1 / C1.1($1N227) |
Q1 栅极钳位与 RC 的上端,µA 级;夹在 F1.1 与 Q1.4 之间只有 3.1 mm,走细线 |
DRC
| 阶段 | 间距错误 | 连接性错误 |
|---|---|---|
| 铺完 Inner1/Inner2/Bottom(§26.10) | 0 | 733 |
| 加上顶层 8 A 宽铜 | 0 | 719 |
⚠️ 顺带看出来的一件事:F1 的封装是 1206,但 BOM 写的是 10 A
F1 板上用的是 FUSE-SMD_L3.2-W1.6-1(1206),而 §7 的 BOM 写「保险丝 10A 慢断」。
1206 的贴片保险丝一般做到 5 A 左右就到顶了,10 A 通常要 2410 / Nano2 那一类。
铜宽本身没问题(这条链按 8 A 铺的),但器件选型和封装对不上,得单独定一次。
换更大的封装会动 J1→F1 那一段的摆位(pcb1_place)⇒ 要重推摆位 + 重扇出 + 重铺铜。
26.12 F1 换 12 A / R9 换 5 × 2Ω 2512(2026-09-06 第十八轮,用户拍板)
两件都是元件选型改动,走的是完整链路:改原理图 → 导入变更 → 重推摆位 → 重扇出 → 重铺铜 → DRC。
⚠️ 先纠一条上一轮写错的判断
§26.11 末尾写「F1 的封装是 1206 但 BOM 写 10 A,1206 做不到 10 A」——这条是错的。
F1206HC10A0TM(C310989)本来就是 1206 封装、额定 10 A(35 V,分断 150 A,I²t 15 A²s),
BOM 和封装从来没有对不上。教训很直白:「这个封装做不到那个规格」属于记忆,不是证据,
库里 lib_Device.search() 一查就有 Current Rating 字段。
不过顺着查下去发现了一条真的:
| 值 | 判据 | |
|---|---|---|
| 连续电流 / 额定 | 8 / 10 = 80% | 保险丝常规降额线是 75%,超了 |
| I²t | 15 A²s | C2/C3 两颗 470 µF 上电浪涌,误熔断风险 |
⇒ 换同族 F1206HC12A0TM(C310990,12 A / I²t 20 A²s):8/12 = 67% 落在降额线内,
而且封装还是 1206,摆位一格都不用动。
⚠️ 但封装对象换了:FUSE-SMD_L3.2-W1.6-1 → F1206。实测焊盘几乎一样
(1.191 × 1.727 @ ±1.444,原来是 ±1.52),顶层那两块宽铜的边界照旧够用 ——
这是 check_top_clearance() 复核出来的,不是看着差不多就放过的。
⭐⭐ R9:高度检查在一个错的数上放行了整整一轮
R9(10 Ω/5 W 母线泄放)用的是 5W水泥电阻 5W10RJ(C9900012720),
封装 RES-TH_L13.5-W9.5-P5.80-D0.7,而 pcb1_place.H_FP 给它填的高度是 9.5 ——
照封装名里的 W9.5 抄的。
P5.80 的脚距才是判据:本体 13.5 长、脚距只有 5.80,说明它是立式的。
同族的 C9900012721(RES-TH_L13.0-W9.5-P4.50-D1.0)3D 模型名直接写着 H52.0。
那一片 hmax 只有 12.0(载板底面压下来),所以「高度预算全过」这句话在它身上一直是假的。
⇒ 往
H_FP里加直插件的判据:脚距和本体长度对不上就是立式, 高度不是封装名里的 W,是那个对不上的方向。
卧式的 5 W 水泥电阻库里有(C9900015499,RES-TH_BD9.5-L22.0-P26.00-D0.8,高 9.5),
但脚距 26 mm、占位 28 × 11 mm,北左角塞不下 —— 可行位置只剩 x 83101 / y 8892
那块北中空地,离 Q3 (25.5, 119) 有 70 mm。
⇒ 用户选了第三条路:5 × 2 Ω 2512 串联(RHC2512FT2R00 C2570006,2 Ω/2 W)
= 10 Ω / 10 W,高 0.8 mm。功率余量还翻了一倍。
| 原 R9 | R9A~R9E | |
|---|---|---|
| 高度 | ≥ 22 mm(模型里写的 9.5 是错的) | 0.8 mm |
| 功率 | 5 W | 10 W |
| 占位 | 13.5 × 9.5 | 15.5 × 12(1+2+2 蛇形) |
摆位:可用空地是 x 14.530.0 / y 86.5101.8(西 U29 到 14.0 / 东 R220 从 30.87 /
北 L2、U19 从 102.25 / 南 C6)。一颗 2512 占 7.42 × 3.46,一行放不下五颗(要 39.4 mm),
排成 1 + 2 + 2 的蛇形,串联顺序跟着几何走 —— Q3 在正北,所以 R9A 放最上面、R9E 收在最下面接地:
y 98.5 R9A (18.0) ← $1N244 从 Q3 漏极下来
y 94.0 R9B (18.5) R9C (26.5)
y 89.5 R9E (18.5) R9D (26.5)
↑ R9E.2 = GND
四个串联节点是自动命名网($1N263$1N266),13.3 V 全压在 10 Ω 上是 1.33 A,
pcb1_rules.AUTO_TRACK 里加了 BLEED0BLEED4 五条按位号反查的指派,挂 PWR1A(0.6 mm,
外层 1 oz 可带 2.16 A)。
这一轮踩到的四条(都写进了对应脚本的防呆)
-
⭐⭐
pcb_fanout.py --net all --push不幂等,我连推了两遍。 板上变成 888 个过孔,每个都有一个同坐标同网的副本; 而短线数没变(444)—— EasyEDA 把共线重叠的新线并进了旧线(skill §9v)。 连接性 DRC 也不报,因为副本和焊盘同网,电气上「没错」。 唯一看得出来的判据是回读过孔数。⇒guard_not_pushed_twice(): 板上已有过孔就拒绝--push,并把--clean → dump_pads → --push的顺序打出来。 (--only那种「补一两个漏网的」不设闸。) -
_p1_sch_bom.json在仓库里根本没有生产者。--verify拿它当对账基准, 而它只能靠手工维护 ⇒ 改过原理图之后--verify是拿新 PCB 和旧原理图对账。 ⇒pcb1_import.py加--bom:逐页重抓。一页一个请求 ——eda.py把返回值截到 20000 字符,整本 BOM 装不下,截断之后json.load炸在中间。 -
JS_DUMP没有openDocument(skill §9l)。跟在--bom后面跑--verify, 当前文档停在原理图上,pcb_PrimitiveComponent.getAll()直接抛Cannot read properties of null (reading 'map')—— 报错信息完全指不到根因。 -
p1_add.py这类「整页重画」的脚本改完就变成地雷。 它的底稿p1-base.json停在 2026-09-04,再推一次会把 R9A~R9E 之间那 6 段新导线静默回退 (BASE 里没有它们,却有旧的 GND 引线)。⇒ 加了硬闸门,要跑必须显式带--i-know-it-is-stale。改一页就要问一遍:还有哪个脚本会重画这一页。
顺带清掉的:P1-INPUT 的文字叠了两代
截图才看出来(三道几何检查都不看文字):66 个文字图元里只有 30 条是唯一的,
多出来 36 个是同坐标同内容的副本(p1_add.py 推过好几次,它的清空没清干净);
另外还压着更早一整代的说明 —— 旧【C】压在【A】上、旧【B】压在【C】上、
旧【A2】直接印在标题栏里。判据是 p1-base.json 只有 9 条 + ADD_TEXT 5 条 = 14 条,
其余全是残留。收拾完 66 → 14,并逐条对账(多一条少一条都报)。
⚠️ p1_text_fix.py 第一版不幂等:去重跑在新增之前,第二次跑会再叠一层
(27 → 18 而不是 14,而且因为坐标在名单内,对账还报了 OK)。
⇒ 把新增块的坐标也放进删除名单,改成「先删再建」,并断言最终条数。
结果
| 值 | |
|---|---|
| 元件 | 338 → 342(R9 去 1、R9A~R9E 来 5) |
| 导入对账 | PCB 342 / 原理图 342,缺 0 / 多 0 / 封装对不上 0 |
| 扇出 | 444 过孔 + 444 短线,失败 0,重复 0 |
| 铺铜 | 15 块全部铺出,顶层三段各 1 个连通域,实测断面与 §26.11 一致 |
| DRC | 间距 0 / 连接性 725(多出来的 6 条是泄放链还没布线) |
26.13 五路功率级精调(2026-09-06 第十九轮)—— §10.2 的四条关键回路
这一轮做完 PROGRESS 里排的第 6 步。四条回路里有三条的根因是器件朝向,不是布线技巧, 所以先改摆位再布线;改摆位这一步用户拍板过(选「转三个 + 挪三颗」)。
⭐⭐ 先说一个真错误:五路 Buck 的散热盘一个过孔都没有
TPS54622 的 PowerPAD(U1~U5 的 pin 15)既是 PGND,也是这颗 4 A Buck
唯一的散热通道。§10.3 早就写了「电感和 IC 下方铺大面积铜箔并打散热过孔阵列
(0.3 mm 孔,1 mm 间距)」—— 而板上这五个盘是光的。同样漏掉的还有 U6/U7 的 EP。
根因在 pcb_fanout.one_net() 的一行:
todo = [p for p in pads if p['net'] == net_filter and not p['hole'] and ...]
not p['hole'] 想表达的是「这是贴片盘,通孔盘不用扇出」。但是——
EasyEDA 给每一个 POLYGON 焊盘都塞了一个假的
hole。 板上 11 个 POLYGON 盘(U1~U5.15、U6/U7.17、J22 的四个壳体盘) 无一例外满足hole = 0.600 x min(w, h):U1 的盘 2.032 x 4.320 -> 1.2192, U6 的 1.70 x 1.70 -> 1.02,J22 的 1.30 x 0.60 -> 0.36。 这是个派生出来的占位值,EasyEDA 自己渲染出来那几个盘是实心的。
于是这 7 个散热盘被整批滤掉。判据本来就该是层号:layer == 12 是多层(真通孔),
1 / 2 是单铜层。三处已改:
| 文件 | 改了什么 |
|---|---|
dump_pads.py |
落盘前把单铜层焊盘的 hole 一律清成 None,并断言被清掉的确实符合 0.6 倍关系;不符合的打印出来要人看 |
pcb_fanout.py |
todo 只按层号过滤;顺带加了 stale 提醒(pcb-copper.json 是旧的会报出来) |
pcb1_parts_dump.py |
POLYGON 盘的尺寸原来取自 +s[1](那是点数组,得到 NaN->0),再退回到 hole 那一位 —— U1 的散热盘因此被记成一个 0.12 mm 的点。现在按点数组算真实 AABB |
⚠️ 这一类失效是静默的:连接性 DRC 只会含糊地多出几条, 没人会把它和「footprint 里一个用不上的字段」联系起来。
盘内阵列也重写了:散热盘不是它的包围盒
U1~U5 的 EP 是个十字:中间 2.03 x 2.03 的方块,上下各伸出两根 0.24 mm 宽的
指头到 ±2.16。按包围盒(2.03 x 4.32)撒 1 mm 栅格,y 方向两头那两个孔会落到铜外面,
而净距校核和连接性 DRC 都不会响(那儿本来就没别人)。
⇒ 新增 pad_poly() / disc_in_poly():候选孔位要求整个 Ø0.7 的圆都在多边形里。
顺带把阵列改成「先按 1.0 mm 排,太小就退到 0.65 mm 再排一次,取孔多的那一版」, 并在偶数栅格中心补一个孔(散热盘最该打孔的就是正中间)。结果:
| 之前 | 现在 | |
|---|---|---|
U1~U5.15 Buck 散热盘 |
0 | 5(2x2 @1.0 + 中心) |
U6/U7.17 DAC 散热盘 |
0(走了一条 2.74 mm 的 0.2 引线到盘外) | 4(2x2 @0.65) |
U14~U18.21 eFuse 散热盘 |
2 | 6(3x2 @0.65) |
U6/U7 的 EP 是 1.70 x 1.70 = 2.89 mm²,卡在面积阈值 THERMAL_AREA=4.0 之下、
又在 U31 的 2.75 之上 —— 把阈值降到 2.8 等于拿 0.05 mm² 的余量去赌。
新增 THERMAL_PADS 点名表,两颗直接写进去。
摆位:转三个 + 挪四颗(用户拍板)
| 器件 | 改法 | 为什么 |
|---|---|---|
L*01 |
rot 180 + 东移到 (10.7, 18.0) | footprint 的 pin1(SW) 在西,rot 0 时正好背对 U 的 SW 脚,SW 要绕过整个电感 13.1 mm |
U*14 |
rot 180,北移 0.8 到 y 30.3 | rot 0 时输入脚在北、输出脚在南,而源在南、去处在北,两条 4 A 各横穿一次封装;北移是为了给输出电容腾出 4.6 mm 的空袋 |
Rs*01 |
rot 180 | rot 0 是「西 = VO_P / 东 = $2N699」,而 INA226 的 IN+ 是 p10(西)、IN− 是 p9,两条取样线必然交叉 |
C*05 |
(11.5,16.2,90) -> (12.4,13.0,0) | 原位置正卡在 SW 立管唯一能走的缝上(U.13 东缘 10.624 到它西缘 11.229 只有 0.605 mm,0.28 的线要 0.68) |
C*06/07/08 |
从 x 14~17.5 挪进 L01 与 U14 之间的空袋 | 输出电容跟着电感转过来的 VO 脚走;三颗的 VO 脚排成一列 x = 5.200,正对 U*14 转过来的输入脚 |
⚠️ 1206 的焊盘 rot 0 时是 1.49 宽 x 1.73 高(不是反过来)。按 1.49 高算的话 两颗摞起来「差 0.37 mm 能塞下」,实际差 0.37 的另一头 —— 本地检查当场报了 0.166 / 0.188。
⚠️ L*01 不能往南挪:C02 的 0805 罐压在它北边 1 mm 内,挪 1.3 mm 就重叠。 空袋是靠 U14 北移 0.8 mm 腾出来的。
母版的局部包围盒一格没变(x 2.2829.50 / y 2.7343.71),
所以五路的分区(§26.3)和 VO_X 对位一个字没动。
布线:pcb1_route_pwr.py(新)
四条关键回路不能交给栅格布线器:它优化的是长度和过孔数,
而这四条的判据都不是「连通」—— 一个完全连通的解可以四条全不满足。
⇒ 路径写在 CH1 母版的局部坐标里,按 CH_PLACE 仿射到五路(rot 180 是纯旋转),
改一处等于五路一起改。27 条母版路径 x 5 = 135 条 / 210 段。
| 回路 | 做法 | 结果 |
|---|---|---|
| ① 热回路 | C*01.1 顶层 1.0 mm 直上 U 的 PVIN;C*02/C*03 从西侧 0.8 mm 母线并过来 |
地不另画顶层线 —— Inner1 就在顶层下 0.2104 mm,回流是镜像电流,回路面积 = 走线长 x 0.21。让 +12V 下到 Inner2 再回来的话回路高度变成 L2-L3 的 1.13 mm,差 5 倍 |
| ② SW | 0.30 窄线出脚 -> 1.0 -> 1.5 立管直上电感 | 13.1 -> 9.7 mm,铜面积 11.2 mm² |
| ③ FB | U.7 往南出,贴散热盘南爪西边 0.224 下来,走 R*08 东边再往西折 |
全程在 SW 的反面,最近处 3.5 mm |
| ④ Kelvin | 两条取样线并排往北 1.7 mm 再分开;IN− 从电阻本体下面(两焊盘之间)横过去 | 不交叉,取样点在焊盘上 |
⚠️ U*8.9(IN−)不许有下到 VO*_P 小岛的过孔,已写进 pcb1_pour.ROUTED_PADS。
让它走岛的话,取样点在岛上而不是分流电阻的焊盘上,中间隔着 Rs*01 那三个扇出孔
(并联约 0.5 mΩ)。Rs 只有 5 mΩ、满载 20 mV,0.5 mΩ x 4 A = 2 mV = 10% 的读数误差,
而 DRC 和连通性检查都看不出来(IN− 和 VO*_P 本来就是同一个网,连上了就算过)。
pin 8 是 VBUS(测输出电压),照旧进岛 —— 它要的就是负载端的电位。
⭐⭐ 这一轮踩到的四条
1. 五路的扇出结果并不相同。
摆位是一模一样的(CH2/CH3 整路转 180°),但扇出规划器的候选角度是按板坐标排的,
同一个焊盘在 CH1 往东扇、在 CH2 就往西扇。于是母版里算好的走廊在 CH2/CH3 上被堵死,
校核报出来的却是「CH2 的 F-trunk 撞到一个 GND 过孔」—— 看上去像布线画错了,
错的是上游的扇出不对称。⇒ pcb_fanout._CH_FORCE_LOCAL:
把和手工走廊相关的 5 个焊盘(C*01.2 / C*02.2 / C*03.1 / U*8.1 / R*02.2)
按 CH1 的解钉死,展开到五路 25 个 FORCE_VIA。钉死之后照样走全套净距校核。
2. DRC 的「物理错误」那一支平时是空的,容易漏看。
第一版按 0.28(SW 出脚)/ 0.25(Kelvin)下发,间距错误 0、连接性还降了 125 条,
看那两支会以为全过 —— 而 物理错误·导线 里躺着 50 条
「线宽 11mil,应该在 11.8mil ~ 157.5mil」:pcb1_rules.TRACK_RULES 里
SWNODE / PWR4A 的 strokeWidthMin 都是 0.30。加宽到 0.30 之后清零。
(0.30 的线从 0.28 高的 QFN 焊盘出来,上下各留 0.21,正好还够。)
3. 回读走线不能按端点比 —— EasyEDA 会在 T 形接点上把已有的线劈成两条。
西侧那条 +12V 母线 (2.550, 8.701)->(2.550, 13.949) 下发之后,板上是两条,
因为 C*01 那条支线正好接在中间。按端点比会报「210 段里 40 段对不上」,
而板上的铜一点没少。⇒ verify() 改成覆盖判据:沿计划路径每 0.2 mm 取一个点,
要求都被某条同网同层同线宽的实测线盖住。
4. IPC-2221 不能套在短桩上。 0.5 mm 间距的 QFN 只能用 0.30 的窄线出 1 mm,套公式算出来是 49 °C; 再窄一点(0.28)直接 265 °C。那条式子假定的是长而均匀的导体, 而这种短桩两端都焊在大铜上。⇒ 短于 2 mm 的段只打印不报错。
这一轮的数
| 值 | |
|---|---|
| 元件 / 过孔 / 走线 / 铜面 | 342 / 495 / 691 / 15 |
| DRC | 间距 0 / 物理 0 / 连接性 594(这一轮开始时 725) |
| 一路功率级走线 | 74.8 mm,其中 SW 9.7 mm |
| 校核 | 本网落脚 + 组内连通 + 逐段净距 + 拐角 + 载流,下发前后同一段代码 |
还欠的(都不影响下一步)
R*01/R*02(FB 分压)离 U 的 FB 脚 7 mm,§10.2-3 的「紧贴 FB 引脚」没做到。 现在那条 FB 走线 8.6 mm,全程在 SW 的反面、最近 3.5 mm,能用; 真要做的话得把R*01/R*02/R*07/R*08/C*12整组挪到 U 的正南(局部 x 712 / y 5.59), 那是又一轮摆位 + 扇出 + 铺铜。C*08离电感的 VO 脚 4.5 mm(在袋子东头)。它是输出侧的高频去耦, 真正管环路的是C*06/C*07两颗 1206,那两颗贴着。
26.14 下板信号布线(2026-09-06 第二十轮)—— 379 条布通 284 条,⛔ 未下发
这一轮建好了下板的信号布线工具链,并把「布不通」拆成了两类: 几何上没有出路(22 个引脚)和拥挤(95 条连接)。前者换任何布线策略都无解。 板上一个对象都没动。
26.14a 三件新工具
| 文件 | 干什么 | 为什么要单独有它 |
|---|---|---|
pcb1_netlist.py |
按实测铜算每个网络还欠几条 | DRC 的「连接性错误」是按对象列的、还要 reload 才准,594 这个数说明不了「还剩几条线要拉」。这里把焊盘 / 过孔 / 走线 / 回读的铺铜当图的节点,k 个连通域就是还差 k−1 条 |
pcb1_route_sig.py |
下板信号布线器 | 载板那个是「本脚本负责的网络整网删掉重画」;下板已经有 691 条线(§26.13 的功率级 + 扇出),照抄会把它们抹掉。这一版只加不拆,任务表来自 pcb1_netlist |
pcb1_escape_audit.py |
逐焊盘算「能不能走出 4 mm」 | 「布不通」看不出根因是这一头出不来还是中间那段挤,而两者的处理办法完全不同 |
26.14b 四个真 bug(都属于「检查全绿而结果是错的」那一类)
1. POLYGON 焊盘的包围盒不是它的形状。
§26.13 抓的是它的 hole 是假的;这次是 pad[1], pad[2] 那对宽高。
TPS54622 的散热盘是带四个缺口的多边形(缺口正是让给 pin 1/7/8/14 的),
按 2.032 × 4.320 的包围盒当障碍,这四个脚整个泡在 GND 铜里,一个出线方向都找不到。
⇒ POLYGON 焊盘的任何标量属性都不能直接当几何用;只能读 pad[1] 那串点,
再按真实轮廓光栅化。板上一共 11 个这样的盘(5 个 Buck EP + U6/U7 EP + J22 的 4 个屏蔽脚)。
2. 网名里带 # 会被 netof() 拆坏。 下板有 KEY_OE# 和 IOEXP_INT#,
而引擎用 key.split('#')[0] 还原网名 ⇒ 校核时它和自己的焊盘被当成异网,
报「净距 −0.100」。分隔符改成 chr(0)。
3. 45° 切角会切进铺铜。 切角是往拐角内侧补铜(不是只拿掉铜),
而 seg_slack() 只认焊盘 / 过孔 / 走线三样。⇒ 把铺铜矩形条包装成「假焊盘」一起喂进去。
4. 「放得下」不等于「栅格上走得通」。 见下一节。
26.14c 细栅格逃逸:0.5 脚距的脚要单独走出来
U8.3(INA226 的 ALERT)西边 1.00 mm 是 GND 扇出孔,东边 1.00 mm 是邻脚的出线段:
| 线宽 | 需要的净宽 | 0.1 mm 栅格上需要(各加一个 QERR 0.0707) |
|---|---|---|
| 0.20 | 1.005 mm(差 5 µm) | 1.096 mm |
| 0.15 | 0.955 mm(放得下) | 1.096 mm(仍然过不去) |
0.025 mm 栅格的 QERR 只有 0.0177,同一条缝就通了。 ⇒ 凡是在 0.1 栅格上出不来的脚,先在 4 mm 内用 0.025 mm 栅格单独走出去, 再把这一小段当本网已有的铜交给主布线器。实测 47 个脚里救回 25 个。
⚠️ 逃逸环半径 4.0 mm,不是 2.5:INA226 两排脚之间就有 2.6 mm, 走到 2.5 还在芯片肚子里,主布线器接手照样出不去。
26.14d ⛔ 22 个引脚几何上没有出路 —— 要动板子
| 组 | 焊盘 | 卡在哪 | 缺多少 | 解 |
|---|---|---|---|---|
| A | U1.10~U5.10(Buck 的 EN) |
§10.2 的 SW-run 1.5 mm 铜,圆头端帽从 (20.05, 27.10) 往西探到 x 19.30 | 脚东边净空 0.376,一根 0.2 的线要 0.6 | EN 进 §10.2 母版;SW-run 起点东移 ~0.35 mm,或前 2 mm 收窄到 1.2(收窄反而符合 §10.2-2) |
| B | eFuse 北排 14 个脚(U14.2/3 U15.2/3/14/15 U16.2/3/14/15 U17.2/3 U18.2/3) |
上面 INA226 的焊盘边只隔 0.33 mm,下面自己的散热盘 0.25 mm | 要 ≥ 0.6,缺 ~0.7 mm | U8 + Rs101 在母版里北移 0.7~0.8 mm(唯一的余量在 Rs101 顶 57.73 到通道北界 59 之间的 1.27 mm) |
| C | U10.3(ALERT) U13.4(SDA) U13.5(SCL) |
隔壁 GND 扇出孔正对着出线走廊 | 5 µm | 在 pcb_fanout._CH_FORCE_LOCAL 里给那几个孔钉一个偏 0.1~0.2 mm 的位置 |
CH1 那一列从下往上:C106(顶 43.46) → U14(43.8547.75) → 53.92) → U8(48.08Rs101(54.2757.73),
缝一律 **0.330.39 mm**,一点余量都没有。这不是布线问题,是摆位把走线通道挤没了。
⚠️ B 组一改就作废扇出 + 铺铜 + 五路功率级布线(U*.9 → Rs*01.1 的 Kelvin 线也在母版里),
所以先拍板再动,别先下发信号布线。
26.14e 剩下 95 条是拥挤 —— 要拆线重布
失败集中在控制块(U21U23,x 75107 / y 43~58)和 J24/J25 排针周边。
现在这个布线器是一遍过、只加不拆(这是有意的:板上已有的 691 条线不能被抹掉),
于是先布的网络把后布的堵死。这正是商业布线器用 rip-up & reroute(协商式拥塞)解决的那一类。
顺带两条:POGO2_VUP / POGO2_VDN 离 SW 节点只有 0.54 / 0.64 mm(§10.3 要求「远离」,已有校核在报);
8 个 45° 切不动的拐角(转向 89~90°),都在细缝里。
26.14f USB 差分对:一整束布线,再平行偏移
U20(ESP32-S3 原生 USB)到调试口 J22 有 55 mm。布线器一次只认一根线,
两根各走各的最短路就不再是一对。做法是:按一整束的宽度 2W + S = 0.74 布一条中心线
(它占的地方和两根并排一模一样),再往两侧各偏移 (W + S)/2 = 0.23。
三条要点:
- 接哪两个脚是算出来的。 Type-C 的 A/B 两面各有一对 D±,J22 南→北是
B7(DM) 51.250 / A6(DP) 51.750 / A7(DM) 52.250 / B6(DP) 52.751。 偏移出来的两根线左右关系沿整条路不变,而U20那边 DP 在 DM 北边 ⇒ 只有 B6/B7 满足;接 A6/A7 得中途交叉一次。A↔B 两面的短接交给通用布线器。 - 两端各硬接一段水平引出线。 不然束的第一段是布线器自己挑的(实测 45° 斜着往东北), 偏移出来的两个端点在 y 上只差 0.32 而不是 0.46,扇入段一走平就压到 0.045。
- 翻层的两个过孔必须错开 ≥ 1.5 mm。 0.46 的对内间距下并排打不下 (钻孔到钻孔要中心距 ≥ 0.605,铜到铜 ≥ 0.81)。
结果:束长 58.1 mm,全程底层,对内偏斜 0.00 mm(容差 5.0 mm)。
26.15 五路母版的三处几何整改(2026-09-06 第二十一轮,用户拍板 A+B+C)
§26.14 抓出的 22 个「几何上没有出路」的引脚,在这一轮全部动手改掉。 三处都改在母版里 = 五路一起改,改完整条链重跑(摆位 → 扇出 → 铺铜 → 功率级 → 信号)。
A. SW 不再往南潜 —— 把 EN / COMP 的走廊还回来
TPS54622 东侧一列从南到北是 p9(COMP) 11.001 / p10(EN) 11.501 / p11,p12(SW) 12.001,12.501
(局部坐标,0.5 脚距)。老版本的 SW 是「先往南潜到 y 11.6,再东行,再 45° 抬回立管」,
为的是从 C%05.1(BOOT 焊盘,底 12.732) 下面绕过去 —— 那里只有 0.581 mm 的缝。
那一潜的 1.5 mm 圆头端帽在 y = 11.5 那一行往西探到 x 11.007,
而 COMP 与 EN 两条 0.2 的线要并排出来至少得到 x 11.62 ⇒ 两个脚只能活一个。
实测就是 COMP 抢到走廊、EN 五路全布不通。
解法不是继续挪那 0.1 mm(试过两次,都卡在 5~20 µm 上),而是换拓扑:
| 老版本 | 新版本 | |
|---|---|---|
C%05(自举电容) |
局部 (12.4, 13.0) | (12.4, 13.6) —— 北移 0.6 |
| SW 东行 | SW-down 潜到 y 11.6 → SW-run → 45° 抬回 |
SW-run 平着走 y 12.500,1.2 mm 宽 |
| SW 到 BOOT 电容 | 45° + 立管顺路盖住 | 立管(x 13.5,1.5 宽 ⇒ 铜跨 12.75~14.25)顺路盖住 C%05.2,不用单画 |
BOOT |
三段,末段往南扎进焊盘 | 两段,终点直接落在焊盘正中 |
| SW 节点 | 9.6 mm / 10.9 mm² | 8.9 mm / 9.4 mm²(§10.2-2 要它小,所以这是改好了) |
C%05 北移之后 BOOT 焊盘底 13.332,SW 那条 1.2 宽的线顶 13.10 ⇒ 净距 0.232。
y < 11.9 整片空出来:COMP 走 y 11.001、EN 走 y 11.501,各走自己那一行。
⚠️ 途中踩到的一条:SW-run 起点原本放 11.200,它 1.2 mm 宽的西端圆头端帽
(半径 0.6)离 U%1.13(BOOT 引脚) 焊盘只有 0.080。把 SW-p12 的短桩往东多走 0.3、
起点改 11.500 之后是 0.347。「端帽比端点往外探半个线宽」这一条本轮又踩了两次(§26.11)。
B. U%8(INA226) + Rs%01 + C%13 整体北移 0.8 mm
eFuse 北排焊盘顶 47.75 到 INA226 南排焊盘底 48.08 只隔 0.33 mm,
一根 0.2 的线要 0.6 ⇒ U14~U18 北排 14 个脚一个都出不来。
这一列从下往上是 C%06(顶 43.46) → U%14(43.8547.75) → 53.92)
→ U%8(48.08Rs%01(54.2757.73),缝一律 **0.330.39 mm**;唯一的余量是 Rs%01 顶到
J24 焊盘底(60.33)之间的 2.60 mm(CH2/CH3 那一侧是 3.10 mm)。
北移 0.8 之后 eFuse 那条缝 0.33 → 1.13 mm,Rs%01 到 J24 还剩 1.80 mm。
⚠️ 跟着一起改的三处(漏一处就是静默失效):
pcb_fanout._CH_FORCE_LOCAL[('U%__8','1')]:33.896 → 34.696pcb1_route_pwr的F-trunk北端:39.300 → 40.100pcb1_route_pwr的K-IN+/K-IN−(Kelvin 四线):整体 +0.8
C. 效果
pcb1_escape_audit.py 实测「几何上出不去」的焊盘:22 → 8。
剩下 8 个(U13.2 与 CH2/CH3/CH5 的几个 eFuse 脚)是和邻脚预留出线段抢地方,
不是硬几何 —— 单独布它们都能通,布线器换出线方向重试还有机会。
D. 顺带修好的一个校核假阳性
pcb1_route_pwr.verify() 原来要求「被同宽的实测线盖住」。
一段窄线整个落在一条宽线的圆头端帽里时,EasyEDA 会把它直接吞掉 ——
铜一点没少,回读却报 5 条对不上。判据改成「实测线不窄于计划线,且中心距 ≤ (o_w − p_w)/2」。
E. 整改之后的两处铺铜连带修改(信号布线把电源面啃窄了)
信号布线下发之后重铺,pcb1_pour.py 当场拦下两条 —— 都不是铺铜算错,是布线动了平面:
- Inner2 中桥 @南出口 y=35 被啃到 5.00 mm(要 6.04 mm / 3.6 A)。
三个异网信号过孔的反焊盘把这一行切成 1.50 / 0.75 / 5.00 三段。
⇒ 把
12V-SW+BR的南出口在 y 34~40.7 加宽到 x 54(再往上 y 41 起是3V3-SW,要留 0.2)。 实测这一行变成连续 18.25 mm。 ⚠️ 原来那个 61.5 的西边界注释写着「躲开 R706/R707 的 0402 焊盘」—— 贴片焊盘对内层是透明的,那条约束本来就不存在。 - Inner2 上一块 0.3 × 14.5 mm 的浮铜(7.3 mm²,y 65.5~80)。
它是 GND 底填卡在
12V-SW+BR(东界 72.0)和3V3-SE(西界 73.0)之间那 1.0 mm 里, 两边各让 0.2 之后剩 0.6,填出来 0.3 宽、里面一个 GND 落脚点都没有。 ⇒ 把 +12V 的东界推到 72.6,缝就没了(离 3V3-SE 还有 0.4)。
F. 又一个「包围盒当几何用」的假阳性
pcb1_pour.obstacles() 为了省事把每条走线折成轴对齐包围盒——
板上只有扇出的正交短线时无所谓,信号布线一上来有两千多条 45° 斜线,
一条长斜线的包围盒必定罩住半块顶层铜 ⇒ check_top_clearance 报
「VINRAW-TOP 侵入 0.000 mm」「VINSW-TOP 侵入 0.000 mm」,真实净距其实好几毫米,
而且它拦下了整次重铺。
⇒ 新增 poly_seg_gap(),走线一律按真实胶囊算;过孔仍用包围盒(对圆形够准)。
这已经是本项目第三次栽在「拿包围盒当几何」上(前两次:POLYGON 焊盘的 hole、POLYGON 焊盘的 w/h)。
G. 最终状态(全部已下发并按实测铜回读)
| 会话开始 | 现在 | |
|---|---|---|
| 板上 | 342 件 / 495 孔 / 691 线 / 15 铜面 | 342 件 / 942 孔 / 2951 线 / 15 铜面 |
| 还欠的连接(按实测铜自算) | 384 | 91(147 个网络全通 / 75 个还碎) |
| DRC | 间距 0 / 连接性 594 | 间距 0 / 物理 0 / 连接性 182 |
| 几何上出不去的引脚 | 22 | 11 |
| 五路 SW 节点 | 9.6 mm / 10.9 mm² | 8.9 mm / 9.4 mm² |
信号布线本轮下发 2305 段线 + 444 个过孔,总长 6617 mm; Kelvin 3 条、USB 差分对 1 对(对内偏斜 0.00 mm)。
已知偏差(写在这里,不是遗漏):
- 19 个切不动的 90° 拐角,全在 0.5 脚距的逃逸段里。
chamfer45半径试到 0.05 仍撞邻脚 —— 属于「这一处通道宽度物理上不允许」,不是没切。 POGO2_VUP/POGO2_VDN离 SW 节点 0.54 / 0.74 mm(§10.3 要「远离」)。pcb1_route_sig.sw_keepaway()会一直报,当提示不当错误。- 剩下 91 条连接是拥挤(控制块 U21~U23 与 J24/J25 排针周边),不是没路。 这个布线器一遍过、只加不拆,先布的把后布的堵死;再往前要 rip-up & reroute。
26.16 拆线重布 + 两处换件 + 控制块按几何重排(2026-09-06 第二十二轮)
这一轮做了四件事,结尾把板上的铜全清了,摆位重来一遍。
A. 信号布线器加了拆线重布(pcb1_route_sig.py --ripup)
§26.14 剩下的 91 条布不通几乎全是「拥挤」而不是「没路」—— 单独布每一条都通。
做法:一条连接在「换出线方向」和「放回队尾再等一轮」都失败之后,才去拆挡路的
本脚本自己下发过的铜,重算,再把被拆的按原端点布回去;任何一步失败整个回滚。
扇出 / 功率级 / 铺铜 / 焊盘一律不动;Kelvin 三条和 USB 差分对按几何钉死不许拆
(rip_pool():路径上有点落在 FORCE 表点名的焊盘里就不许拆 —— 光看键名不行,
从下发记录反推出来的键是 net�pN,FORCE: / usb 前缀一个都不剩)。
单网验证过:EDL_EN2 原来布不通,拆 9 条子链 + 重布之后通了,净距/钻孔/铺铜全 0。
全量那一跑没跑完就被这一轮的摆位重排作废了,代码留着,重布线时直接用。
⭐⭐ 建它的过程里抓到三条,每一条都真的把一次尝试搞砸过
1. clean() 一直只删得掉自己 59% 的铜。
它按「网络|层|两端点|线宽」精确比对认自己画的线,而 EasyEDA 会把共线相接的并成一条、
在 T 形接点上把线劈成两条(§26.13 第 4 条踩过一次)。实测 2305 段计划里只有
1351 段能在板上找到坐标完全一样的线 —— 按精确比对删,41% 的铜留在板上而记录里
已经没有它,从此没人认领。
⇒ 判据改成覆盖:板上这条线的中心线整条贴在同网同层同宽的计划线上(≤0.02 mm)。
实测 2951 条里 2277 条整条落在计划里、0 条只落一半,过孔 444 个全部对上。
clean() 同时加了 --force-clean 闸:这个布线器是增量的,一刀全删会把已布通的几百条抹掉。
2. 一条 --net EDL_EN2 的空跑,把 700 条路径的计划缓存清成了 {}。
_pcb1_sig_plan.json 是无条件写的,--net / --limit 的试水也照写不误。
⇒ 归属表改成从 _pcb1_sig_routes.json(只在 --push 时写,是板上那些铜唯一可靠的账本)
按铜的连通图反推路径:端点建图、过孔是连上下两层的一条边、度 ≠ 2 的点断开,
拆成一条条极大链,再逐条回验「重新 expand() 之后和账本一模一样」。
同时给 --net / --limit 加了闸,不许覆盖缓存。
(反推顺带踩到:账本里有 2 条 0.1 µm 长的线段,是 _snap_end 把端点拽向焊盘中心
留下的数值毛刺;1 µm 的节点栅格上它们是自环,对账时要按长度剔掉。)
3. ⭐「两个端点钉死 ⇒ 连通性不变」这条不变量是破的。
KEY_RCLK 三条链里,两条的起点 (83.70,52.30) / (84.70,61.00) 正落在第三条链
某一段的中间 —— 当初布线器就是奔着「已有的那坨铜」去的,终点落在它的铜里
而不是它的端点上。按端点重布,那两条当场挂空。
⇒ 先按搭接点把链切开(别的链的端点、同网焊盘、非本脚本的线端/过孔,投影到链上切一刀),
切完每一处搭接都是某条子链的端点。实测 409 条链切成 797 条(388 刀),铜一点没动。
另外拆完必须用 pcb1_netlist.analyze() 按实测铜重算受影响网络的碎片数,不许变多 ——
上面这个坑,栅格 / 净距 / DRC 三样都看不出来,就是靠这一步抓到的。
还有两条一起做的:共享铜要连坐(2277 条属于本脚本的线里 401 条同时落在相邻两条路径上, 只拆一条会「归属没落全 ⇒ 删不掉」,而它已经不在计划里 ⇒ 下一轮算成「不是我画的」, 永远拆不动也删不掉);一轮里同一条只拆一次(没有拥塞代价函数,反复拆会来回震荡)。
B. ⭐⭐ 本体框有第二个来源了 —— §26.6 那句话是错的
§26.6 写着「板边连接器的本体框,除了实测没有别的来源」。这条是错的,只是当时没找到路子。
lib_Device.search() 回来的 otherProperty['3D Model Transform'] 是一串逗号分隔的数:
v[0], v[1] = 3D 本体的 X / Y 尺寸(mil)
v[6], v[7] = 本体中心相对**封装原点**的偏移(mil)
拿六个当年用放大截图量过的封装交叉验证,全部对上,误差 ≤0.31 mm(就是截图标定的精度):
| 封装 | 3D 算出的 y 向框 | 当年截图实测 |
|---|---|---|
CONN-TH_KF2510-3A-1 |
−0.31 .. +11.70 | −0.20 .. +11.70 |
CONN-TH_P5.08_KF128-5.08-2P |
−5.31 .. +5.38 | −5.20 .. +5.20 |
USB-C_SMD-TYPE-C-31-M-12_1 |
−5.05 .. +2.85 | −5.20 .. +3.12 |
WIRELM-SMD_ESP32-S3-WROOM-1 |
−9.10 .. +16.40 | −9.35 .. +16.75 |
IND-SMD_L7.1-W6.5 |
−3.25 .. +3.25 | −3.35 .. +3.35 |
CAP-TH_BD8.0-P3.50-D0.6-FD |
−4.00 .. +4.00 | −4.10 .. +4.10 |
已固化成 .claude/fp_body.py(--scan <关键词> 选型 / --check 对账整张 FP_BODY)。
⚠️ 它只给 XY,Z(高度)读不出来,高度仍然只能查规格书或量实物。
⚠️ 没有 3D 模型的器件读不出来,那种还是得截图。
立式 / 弯针一眼分得出:同一个 3P 2.54 端子座,立式本体 ≈ 7.6 × 6 且偏移 ≈ 0;
弯针 ≈ 7.6 × 12 且偏移 ≈ ±5.7。名字完全不可靠 —— KF2510-3A(C2940511) 名字像直针,
数说它是弯针(+5.69);KF2510-3AW(C457341) 也是弯针,只是甩向 −Y。
C. 两处接口换件(用户拍板)
| 旧 | 新 | 立创 | 本体 | |
|---|---|---|---|---|
| J1 12V 输入 | KF128-5.08-2P 螺钉端子 |
XT30PW-M |
C53373776 | 13.30 × 13.95,框 (−6.65,−7.98,6.65,5.97) |
| J26~J30 风扇 | KF2510-3A(弯针) |
2510-3A(直针) |
C2803349 | 7.62 × 5.81,框 (−3.81,−2.88,3.81,2.93) |
⚠️ 用户原话是「3.5 mm DC 接口」,那个规格接不了这块板。 12V 输入是 8 A
(五路 4A × 4.2V ÷ 0.92 ÷ 12V ≈ 7.6 A,加风扇 0.7 A),而 DC-002 一类(外径 3.5 / 内径 1.35)
额定只有 0.5~1 A,差了近一个数量级 —— 接上去会烧插座。用户改选 XT30(主脚额定 20 A)。
选 2 脚版而不是 (2+2):多出来那两脚是 1 A 信号脚,用不上,而且库里读不出 pin 语义;
2 脚版符号的引脚名直接写着 + / −。导入后实测焊盘证实:p1/p2 是 2.5 mm 大焊盘、
针距 4.999 mm(XT30 标准 5.0),p3/p4 只有 1.8 mm,确实是机械固定脚(不接网络,
已进 .claude/p1-nets-nc.json)。
两处换件都做到了一根导线不动:J1 原位 (120,705) rot 180 时新符号 p1/p2 与旧件完全重合;
风扇座元件东移 5 到 x=1085,抵消引脚偏移(−20 vs −15),引脚绝对坐标不变。
脚本 .claude/p1p6_conn.py(试跑会自己把试建的新件删回去 —— 「先 create 后 delete」
意味着断言那一步已经把件建到页上了,不收尾就会留下一堆重叠件)。
⚠️ 立式风扇座的代价:装配顺序被锁死(2026-09-06 用户拍板接受)
弯针座是从板边水平插拔,13 mm 两板净空完全不碍事;立式插口朝上,正对载板底面。
座子 + 胶壳总高约 11.5 mm,装得下,但插拔只剩 1.5 mm 余量,手伸不进去
⇒ 装配顺序必须是「先插好五根风扇线,再合上载板」,以后换风扇线要拆载板。
换来的是每个座省 6.2 mm 进深(12.01 → 5.81)。
⚠️ H_FP 里这两个高度(XT30 11.0 / 直针座 9.0)是按同系列常规取的保守估计,
3D Model Transform 给不出 Z —— 打样前必须拿实物量(§12)。
D. 控制块从「按原理图仿射」改成「按连接几何」
affine(['P3-CONTROL','P3B-EXPAND'], 73, 34, 42, 22) 是把两页的原理图坐标线性映射到
板上一块 42 × 22 —— 保的是「原理图上挨着的板上也挨着」,和「谁连谁」没有半点关系。三条后果:
- 焊盘框总面积只有 253 mm²,却全挤在 924 mm² 里(填充率 27%),而 S-M 块可用 50 × 58 ——
y 0.5~32大片空着,而 §26.14 那 91 条布不通正好集中在 U21~U23 周边。 - U22 和 U23 放反了:U22 只服务 CH3/CH4/CH5(理想 x≈105)却待在 79.6, U23 服务五路全部(理想 x≈78)却待在 103.7。
- U21(79.61,56.00) 与 U22(79.61,47.96) 中心只隔 8.04 mm,两个 SOIC-16 的焊盘框 (7.44 高)之间只剩 0.6 mm —— 一根线都插不进去。
⇒ 新增 .claude/pcb1_ctrl_place.py:五颗芯片退火求位置,目标 HPWL,
预留框故意开得比「本尊 + 附属件」还大,多出来那一圈就是走线通道
(只按占地摆的话,退火会把它们贴在一起去换那几毫米线长)。结果钉进 pcb1_place.CTRL:
U21 (92.25, 52.37) U22 (92.84, 38.01) U23 (76.50, 49.63)
U6 (79.58, 38.01) U7 (109.57, 34.71)
最近的两颗现在隔 14.4 mm。不再 relax —— relax 只管不重叠、不管通道,会把它们重新推回一起。
⭐ 顺带抓到的真错:USB-C 的 CC 下拉电阻在 77 mm 外
22 个附属 R/C 改成逐个贴到真正的对端引脚(pcb1_place.SAT 表,每颗带上限,check() 硬校核)。
其中最要紧的一条:R602 / R603 是 Type-C 的 CC1/CC2 下拉 5.1k,按 affine 摆在
(77.2,33.2)/(76.4,36.8),而 J22 在 (154.4,52) —— 离了 77 mm
($3N203 / $3N204 那两条 77 mm 的网络就是它们)。CC 是角色检测线,下拉必须贴着座子。
现在 1.3 mm。这和 §26.16-A 那颗「ESP32 储能电容在 48 mm 外」是同一类:
不重叠、不越框、高度也够,几何检查一条都报不出来,纯粹是电学上错了。
全板 HPWL 9416 → 8935 mm。⚠️ 控制块位置本身只贡献 4% ——
U23 单颗管五路,往西省 CH1/CH4 就在 CH3/CH5 上赔回来,是零和的;
真正的收益来自这些「贴身」修正。(想再进一步得改通道分配:U6 现在管 CH1/CH2/CH3,
而 CH1 在 x 17、CH3 在 x 139,VDAC3 因此拉了 93.8 mm;按几何应该是「U6 管左边、U7 管右边」,
595 的按键位同理,估计再省 ~300 mm。这要改原理图,还没做。)
E. J1 换 XT30 之后 N-L 块重排
CONN-TH_XT30PW-M 插口在 −Y 端 ⇒ 要它朝左板边就得 rot 270,转过来往 −X 伸 7.98。
放在 x=8.5 时框 (0.52,64.85)-(14.47,78.15),原来 F1 的位置 (14.5,71.5) 正好被吃掉;
而东边的墙是硬的:北排 CH2 从 x 29.6 起,D1(SMB) 再往东就撞上去。
J1 东边只剩 15 mm 要放 F1/Q1/D1/DZ1/C1/R1 六件,一行排不下 ⇒ 改两行,
C2/C3 罐与 R9A~R9E 整列北让(J24 排针顶到 y 65.04、C2/C3 原来从 77.9 起,
中间只有 12.8 mm 而 J1 要 13.3)。
摆位已下发:342 件,本地检查全过,J24/J25 各 40 个焊盘逐个网络对上载板。
截图 PCB1-v11-place.png(只开通孔焊盘 + 丝印)。
F. 板上的铜全清了
摆位大改之后,2951 条走线 + 942 过孔 + 15 块铺铜全部按旧坐标算的,元件挪走了它们
不会跟着动 —— 已经是废铜,而 DRC 只会报「连接性错误」,看不出「这些铜已经作废」。
.claude/pcb1_wipe.py --push 清空:删 layer 1/2/15/16 四个铜层的线 + 全部过孔 + 全部铺铜,
元件/板框/丝印不动,删完核对元件数不变(342 → 342)。
⚠️ 顺带查实:板框根本不是 pcb_PrimitiveLine。 板上 2951 条线全部在 layer 1(2298) / 2(653),
layer 11 一条都没有(API 的 Line / Arc / Region 里都找不到板框)。
所以 pcb1_pour.py 里那句 if (l.layer === 11) continue; // 11 = 板框 是死代码;
pcb1_wipe.py 没沿用它,判据改成铜层白名单。
清空时把 13 个旧账本改名成 .stale(_pcb1_sig_routes.json / _pcb1_sig_plan*.json /
_pcb1_poured.json / _pcb1_todo.json / 五个 _fanout_plan_*.json …)——
留着的话下一轮的归属表会拿旧账本去认板上的新铜。
26.17 ⚠️ v11 的两行排法把 8 A 输入链卡死了(2026-09-06 第二十三轮,已修)
§26.16-E 把 J1 换成 XT30 之后,N-L 块改成了两行。摆位的本地检查(不重叠 / 不越框 /
不压定位孔 / 高度预算)六项全过,可是回到 §26.11 去重算顶层宽铜的多边形时,
第一刀就下不去 —— VIN_RAW 从 J1 出来根本没有 3.49 mm 的路。
为什么卡死:XT30 rot 270 之后 GND 在北、VIN 在南
| 焊盘 | v11 坐标 | 说明 |
|---|---|---|
J1.1 GND |
(13.5, 74.5) Ø2.5 通孔 | 北针 |
J1.2 $1N223 |
(13.5, 69.5) Ø2.5 通孔 | 南针 = 8 A 入口 |
F1.1 |
(16.06, 74.5) | F1 卧着放,和 GND 针同一行 |
D1.1/D1.2 |
(17.5, 71.86 / 67.14) | 正堵在 J1.2 与 F1.1 之间 |
于是 8 A 要从南针绕到 GND 通孔东侧再往北爬。实测通道宽度: GND 焊盘(圆心 (13.5,74.5) r 1.25)到 D1.1 西北角 (16.404, 72.884) 的距离 √(2.904² + 1.616²) = 3.324,减掉 r 1.25 = 2.074 mm,两边各让 0.2 之后 只剩 1.674 mm —— 1 oz 外层 ΔT=20 °C 下约 4.5 A,而这里要 8 A。
这一类错误几何检查一条都报不出来:元件不重叠、不越框、高度也够。 抓到它的是「照着新坐标重画 §26.11 的多边形」这个动作本身。 ⇒ 摆位改完不能只看本地检查,必须把顶层宽铜的多边形重推一遍, 推不出 3.49 mm 就是摆位错了,不是铜画错了。
三处改动(都在 pcb1_place.py 的 N-L 表里)
| # | 改动 | 拿回了什么 |
|---|---|---|
| ① | F1 卧 → 竖(rot 0 → 90),(17.5, 74.5) 不动 |
F1.1 落到 (17.5, 73.06),正对 J1.2 那一片空地;F1.2 到 (17.5, 75.95) 朝北接 Q1 |
| ② | D1 (17.5,69.5) → (31.0, 74.5) rot 270 |
通道里最后一个障碍搬走;TVS 贴到漏极铜的东缘,离 Q1 漏极 2.1 mm |
| ③ | C4/C5/C6 x 25 → 30.5,rot 0 → 180 |
让出 y 78.85~83.5 那条 4.64 mm 的西行干道;rot 180 让 $1N236 脚朝西迎着漏极铜、GND 脚朝东好打孔 |
⚠️ ①的关键在于换了个方向就不用绕了:F1 竖过来之后,VIN_RAW 从 J1.2 出来
一路向北偏东,GND 通孔只需要一个台阶就躲开,颈部净宽 3.50 mm(要 3.49)。
"挪 0.1 mm 解决不了拓扑问题"(§26.15 那一条)反过来也成立:
转 90° 常常比挪 5 mm 更有用。
⚠️ ③还有一层:v10 的干道走 y 7680.95,而 XT30 的机械固定脚 83.49**,
上边界又被 C2/C3 两颗罐的通孔(底 83.7)压住 ⇒ 净宽从 4.95 掉到 4.64 mm(能带 10.0 A)。J1.4 在 (3.5, 77.5),
Ø1.8 无网络通孔,占到 y 78.4。干道被迫整体北提 2.8 mm 到 **y 78.85
顶层三块宽铜重画后的实测断面(1 oz,ΔT=20 °C)
| 位置 | 连续铜宽 | 能带 | 要 |
|---|---|---|---|
| RAW J1→F1 颈(y=73.4) | 3.50 mm | 8.0 A | 8 A |
| RAW J1.2 东出(x=15.5) | 8.25 mm | 14.9 A | 8 A |
| FUSED F1.2→Q1 源极(x=19.5) | 5.25 mm | 10.8 A | 8 A |
| SW Q1 漏极北出(y=77.5) | 6.75 mm | 12.9 A | 8 A |
| SW 干道(x=12 / x=24) | 4.75 mm | 10.0 A | 8 A |
| SW 干道拐北(y=84) | 5.25 mm | 10.8 A | 8 A |
| SW 北柱 @Rs6.1(y=92) | 5.25 mm | 10.8 A | 8 A |
面积 59 / 30 / 263 mm²,各自 1 个连通域,check_top_clearance() 零侵入。
y 95.4 ┌───┐ 北柱到 Rs6.1 为止(再往北是 U13 的 Kelvin 脚)
│北 │
y 86.5 │柱 │ ┌─┐ 右边那条是 C4/C5/C6 去耦指(x 28.6~30.47)
y 85.5 ├───┤ ┌──┐ │ │ C3 口袋
y 83.5 │ └─┤C3│───┴─┴──┐
y 78.85└─────┴──┴────────┤ ← 8 A 西行干道 y 78.85~83.49(净 4.64 mm)
┌────┴──┐ Q1 漏极块 + D1(TVS)
y 73.45 ┌──┐ │ │
y 73.0 ┌────┤F1├───┤ │ ← FUSED 在 F1 与 Q1 源极之间
y 65.4 └────┴──┴───┘ └
x1.5 x15 x19.6 x25.6 x32.3
顺带抓到的一个静默失效:Rs6.2 一个过孔都没打
12V-N 那块 Inner2 平面为了让开 U13 的 Kelvin 脚,在西边咬了一个缺口
(0.5,93.0)-(12.5,101.5)。而 Rs6.2 的焊盘是 (8.9310.21, 91.7795.23),
中心 (9.57, 93.50) 正落在缺口里 ⇒ 扇出判定「这颗不在铜面上」,
于是全板唯一的 8 A 源不接电源平面,96 个 +12V 过孔里一个都不在它旁边。
- 失效是静默的:
--push报「放下 95 个过孔,失败 0 个」,一切正常; - 连接性 DRC 也不会响 —— +12V 平面靠别的 55 个焊盘照样连通, 只有 Rs6.2 这一端是断的,而它恰好是源。
缺口收成 (0.5,95.6)-(12.5,102.4),只罩住 U13 的十个脚(96.08~101.92)与 C11。
重跑扇出:+12V 焊盘 55 → 56、过孔 95 → 98,Rs6.2 拿到 3 个孔。
⚠️ 这三个孔的引线是 1 mm 宽、朝西甩出去的,
(8.975,94.397)-(7.401,94.397) 带圆端帽往西探到 x 6.901
(端帽 = 端点 ± w/2,§26.11 那一条第三次踩到)。
VINSW-TOP 的北柱东边界因此从 7.22 让到 6.65(净宽仍有 5.15 mm)。
C606.1 / R608.1:不是漏掉,是两块内层平面都够不着
v11 控制块退火重排之后,这两颗落到 x 71.87~72.41 ——
正好是 12V-SW+BR(东界 72.6)与 3V3-SE(西界 73.0)中间那 0.4 mm 的缝里。
贴片焊盘对内层是透明的,所以这不是错误;已写进 ROUTED_PADS:
C606.1 紧贴 U23.24(0.3 mm,去耦回路本来就该这么短),
R608.1 沿 U23 西缘走 6 mm 顶层线搭到 C606.1。
⚠️ pcb1_route_pwr.py --push --verify 是只 verify
main() 里 --verify 在 --push 之前 return。PROGRESS 上一轮写的那条命令
(--push --verify)实际上一根线都没下发,而它照样打 ✅ 全部校核通过,
只在最后一行的回读里露馅:「195 段里没被实测铜盖住的 195 条」。
要下发就只写 --push(它自己会回读)。
26.18 ⭐ 按 PCB 几何重排三组引脚(2026-09-06 第二十三轮,用户拍板)
「哪个信号落在哪个物理脚」在这块板上有三处是自由的,而这三处原来全是按 逻辑顺序排的(EFUSE_EN1→IO4、EN2→IO5……VDAC1→U6 通道 0、K1→U21 的头三位), 和它们在板上要去哪儿一点关系都没有。
| 组 | 为什么可以随便换 | 换脚要改什么 |
|---|---|---|
| ESP32-S3(U20)22 个信号 | 除 USB_DM/DP(IO19/IO20 是 USB PHY 硬连线)与两路 NTC(要 ADC1 = IO1~IO10)外,全部走 GPIO matrix —— I²C、LEDC(FAN_PWM)、PCNT(FAN_TACH)、普通 GPIO 都不挑脚。IOMUX 直连只在 >40 MHz 的 SPI/LCD 上才必须,这块板一根都没有 |
原理图上的网络标签 + 固件里的引脚号 |
| DAC63204 ×2 的 5 个通道 | 四个通道完全对等 | 标签 + 固件通道号 |
| 74HC595 ×3 的 21 个位 | 三片串成一条 24 位链,谁在哪一位只是移位的字节序 | 标签 + 固件位序 |
目标函数:绕开芯片本体的直角最短路,不是 HPWL
.claude/pinmap.py / reassign.py:代价 = 从出线点(焊盘往芯片外挪 1.7 mm)
到本网最近焊盘的绕障直角最短路,再跑匈牙利算法求最小总和。
HPWL 量不出「东边的脚要去西边」有多贵 —— 那根线得先往北爬出模块、 再横穿 17.5 mm 的封装宽度,而且同向的几根会一起挤在同一个拐角上。 实测两个指标的差别:同一批改动 HPWL 只说省 7%,绕障路长说省 15%。
A. ESP32-S3:放开 IO39~IO42,西边从 4 个坑变 8 个
原来 22 个信号正好塞满 22 个可用脚(东 9 / 北 9 / 西 4),一点腾挪余地都没有,
而 EFUSE_EN1(去 CH1, x 21)、EFUSE_EN2(x 47)、EFUSE_EN4(x 53) 三条去西半板的线
偏偏都在东边,得整条绕过模块。
瓶颈是西边只有 IO38 / IO44 / IO2 / IO1 四个脚,而 IO39~IO42 被 §8.1 留给了引脚 JTAG。 用户 2026-09-06 拍板放开:
调试口本来就走 ESP32-S3 原生 USB-Serial-JTAG(IO19/IO20 → J22),出厂 eFuse 默认选的就是它;板上没有 JTAG 排针,也没打算烧
JTAG_SEL_ENABLE/DIS_USB_JTAG把 JTAG 切到引脚上。留着这 4 个脚 = 在最缺位置的西边空放 4 个坑。⚠️ 让出去的是兜底:固件把 IO19/20 改成普通 GPIO、或跑到 USB 外设起不来的地方挂死时, 引脚 JTAG 还能进去,USB JTAG 进不去。另外永远别烧
DIS_USB_JTAG,烧了两边都没有。 IO39~IO42 在 S3 上不是 strapping(S3 的 strapping 只有 IO0/IO3/IO45/IO46), 复位期间是高阻输入,配合目的地那边的 100 kΩ 下拉,上电全关的行为一点没变。
结果:绕障路长 1195 → 1020 mm(−15%),挪 12 个脚,绕模块的线 3 根 → 0 根。
| 模块脚 | GPIO | 边 | 信号(新) | 原来是 | 路长 |
|---|---|---|---|---|---|
| 6 | IO6 | 东 | EFUSE_EN3 |
同 | 94 |
| 8 | IO15 | 东 | SCL |
同 | 1 |
| 9 | IO16 | 东 | FAN_TACH |
KEY_SER | 68→61 |
| 10 | IO17 | 东 | VBUS_EN5 |
KEY_SRCLK | 54→51 |
| 11 | IO18 | 东 | FAN_PWM |
KEY_RCLK | 66→60 |
| 12 | IO8 | 东 | EFUSE_EN5 |
同 | 48 |
| 13/14 | IO19/IO20 | 东 | USB_DM/USB_DP |
同(硬连线,动不了) | — |
| 17 | IO9 | 北 | KEY_RCLK |
VBUS_EN1 | 24→13 |
| 18 | IO10 | 北 | VBUS_EN2 |
同 | 63 |
| 19 | IO11 | 北 | VBUS_EN3 |
同 | 95 |
| 20 | IO12 | 北 | KEY_SRCLK |
VBUS_EN4 | 24→18 |
| 21 | IO13 | 北 | KEY_SER |
VBUS_EN5 | 44→29 |
| 22 | IO14 | 北 | SDA |
同 | 1 |
| 23 | IO21 | 北 | KEY_OE# |
同 | 19 |
| 24 | IO47 | 北 | UP_VBUS_DET |
FAN_PWM | 86→78 |
| 25 | IO48 | 北 | EFUSE_EN2 |
FAN_TACH | 112→81 |
| 31 | IO38 | 西 | IOEXP_INT# |
同 | 30 |
| 32 | IO39 | 西 | EFUSE_EN1 |
原 JTAG MTCK | 107→72 |
| 33 | IO40 | 西 | VBUS_EN1 |
原 JTAG MTDO | 97→83 |
| 34 | IO41 | 西 | EFUSE_EN4 |
原 JTAG MTDI | 72→40 |
| 35 | IO42 | 西 | VBUS_EN4 |
原 JTAG MTMS | 90→81 |
| 38 | IO2 | 西 | NTC2(ADC1_CH1) |
同 | 1 |
| 39 | IO1 | 西 | NTC1(ADC1_CH0) |
同 | 1 |
空出来的脚:IO4 / IO5 / IO7(脚 4/5/7,三个都带 ADC1)与 RXD0/IO44(脚 36)。 比原来的「一个不剩」宽裕多了。
⚠️ 这一版把
EFUSE_EN2放到了 IO48。WROOM-1 模组上 IO48 是普通 GPIO (板载 RGB 灯是 DevKitC 的事,模组上没有),复位高阻 + 目的地 100 kΩ 下拉,安全。
B. DAC63204:纯置换,一根线都不用新画
VDAC3 原来挂在 U6 的 OUT2(西侧脚),而 CH3 在板子的东北角 (141,105) ——
131.9 mm,是全组最长的一条。按几何重排:
| 通道 | 新 | 原 | 路长 |
|---|---|---|---|
| U6.OUT2(西侧) | VDAC1 → CH1 (15,21) |
VDAC3 | 85→78 |
| U6.OUT0(东) | VDAC2 → CH2 (53,105) |
VDAC1 | 97→96 |
| U6.OUT1(东) | VDAC4 → CH4 (47,21) |
VDAC2 | 80→53 |
| U7.OUT0(东) | VDAC3 → CH3 (141,105) |
VDAC4 | 132→98 |
| U7.OUT1(东) | VDAC5 → CH5 (126,21) |
同 | 27 |
422 → 352 mm(−17%)。 特意只在已经画好线的那 5 个通道里置换 —— 动用 U6.OUT3 / U7.OUT2 / U7.OUT3 还能再省 6 mm,但要新画 OUT/FB 两根线,不值。 ⇒ U6 = 0x4A 管 VDAC1/2/4(都去西半板),U7 = 0x4B 管 VDAC3/5(都去东半板)。
C. 74HC595:每路三键必须成束
原来 U21 管 CH1/CH2/CH3 的头 8 位、U22 管 CH3 尾 + CH4/CH5 + HUB_RST、U33 管 5 路 EDL。 问题是 U21 在 y≈50 却要去够 y 87~94 的 CH2/CH3,而 U33 就在 y≈70、正对它们。
约束加了一条:每一路的 3 个按键必须落在同一片的连续三个南脚上(QB~QH 的滑动窗口),
这样三根线出芯片就是一束,不各走各的。代价是比自由指派多 40 mm,换来的是布线可读。
| 芯片 | 位置 | 新的位分配 |
|---|---|---|
| U21(y≈50) | 中 | QA=EDL_EN4 / QB QC QD=K1 / QE 空 / QF=EDL_EN5 / QG=EDL_EN3 / QH=EDL_EN2 |
| U22(y≈35) | 南 | QA 空 / QB QC QD=K4 / QE 空 / QF QG QH=K5(VDN/VUP/PWR) |
| U33(y≈70,在 P6 那一页) | 北 | QA=EDL_EN1 / QB QC QD=K2 / QE QF QG=K3 / QH=HUB_RST |
1286 → 1141 mm(−11%)。 单条改善最大的几个:
HUB_RST 56→29、K3_VDN 76→50、K2_VUP/VDN 各 −23、K3_PWR 72→54。
U33 从「EDL 专用片」变成「北边那一片」,页面语义确实乱了一点 (CH2/CH3 的按键网络现在出现在
P6-FAN-EDL上),但三片本来就是一条链, 功能上没有区别,而几何上 U33 就是离 CH2/CH3 最近的那一片。
落地:端口只能删掉重建,不能改名
三张映射一共 44 处「修改网络」(导入对话框里逐条核对过,没有一条是增删元件)。
落地脚本 .claude/pinmap.py:
⚠️⚠️ setState_Net 对 netport 是坏的 —— 调用之后网络名变成空字符串,
标签也一起没了(和 skill §3b 的 setState_X/Y 同一个毛病,这一轮实测栽了一次)。
⇒ 端口只能 delete + createNetPort 重建。
✅ 但 skill §8b 那句「端口的 dir(IN/OUT/BI)读不回来」是错的:
getState_Component().name 就是 Netport-BI / Netport-IN / Netport-OUT。
重建前读它、原样传回去即可,不用像 p1_add.py 那样「端口只增不重建」。
改动量:P3 改名 8 / 删 4 / 新建 4;P3B 改名 14 / 删 3;P6 改名 4 / 新建 3。
三页 verify_sch --nets --nc、xpage.py(0 漏接)、port_audit.py(544 个旗/端口 0 可疑)全过。
NC 清单跟着改:p3-nets-nc.json 去掉 32~35、加上 4/5/7/36;
p3b-nets-nc.json 加 U21:[4] / U22:[4,15];p6-nets-nc.json 的 U33 只剩 [9](链尾的 Q7S)。
顺手治了一处烂了很久的东西:图面文字叠了好几代
读回来发现 P3 有 44 条 sch_PrimitiveText、P3B 64 条、P6 76 条,
其中大量是同坐标同内容的完全重复(历代脚本只 create 不 delete),
还有互相矛盾的旧说明叠在一起,渲染出来就是一坨看不清的黑块。
verify_sch / xpage / port_audit / DRC 四道验证一条都不管文字,所以它烂了很久也没人发现。
.claude/sch_text.py 整页重写:P3 44→13、P3B 64→14、P6 76→16,
顺带把换脚之后变成假话的几条改掉(IO39~IO42 留给 JTAG、IO47/IO48 备用、
U22.Q7 = HUB_RST、QA~QE = EDL_EN1~5;QF/QG/QH 备用不接、风扇座 KF2510-3A)。
判据:
sch_PrimitiveText只有图面注释,标题栏不是它(图框自己的字段,getAll()里根本不出现),所以整页删干净是安全的。
26.19 ⚠️ 8 A 的源只有 3 个过孔 —— 四道验证一条都不管(2026-09-06 第二十三轮)
第一次跑信号布线跑到 35/196 个网络时中止,原因不是布线器,是它报出来的失败 把两个上游问题照了出来。
A. Rs6.2 → +12V 平面:3 个 Ø0.3 过孔扛不住 8 A
Rs6 是输入检流电阻,Rs6.2 是全板 +12V 平面唯一的源 ——
12V 进线 8 A 全部由这一个贴片焊盘下到 Inner2。而扇出规划器按
pad_n_via() 给了它 3 个孔:Ø0.3 过孔单孔算 11.5 A ⇒ **34.5 A**,缺一半。
这一条为什么四道验证一条都抓不到:
| 验证 | 它在看什么 | 为什么漏 |
|---|---|---|
pcb1_pour 断面校核 |
平面本身的连续铜宽(北大块 @Rs6 东出 x=20 → 11.1 A) |
它量的是平面,不是焊盘怎么下到平面 |
pcb_fanout |
「孔放下了没有」 | 放下 3 个就报「失败 0 个」,它不知道要几个 |
| 连接性 DRC | 「连上没有」 | 连上了,只是细 |
pcb1_escape_audit |
「出得去吗」 | 出得去 |
⇒ pcb_fanout.py 新增 FORCE_ARRAY[(位号, 引脚号)] = [(x, y), ...]:
整片阵列钉死,逐个仍走全套净距校核。Rs6.2 钉了 12 个孔(≈12 A),
摆在焊盘正南那片空地(实测 x 5.214.0 / y 85.591.5 什么都没有)。
规矩:凡是 >4 A 的「焊盘 → 平面」转换点,过孔数必须手写,不能交给
pad_n_via()。 这块板上只有Rs6.2一处(五路的VOn_P走底层小岛、排针针脚是通孔,不经过这一步)。
B. 同一处改动顺带把 U13 的 I²C 放了出来
原来那 3 个孔里有两个被规划器甩到西边 (7.40,94.40) / (7.91,95.16),
两根 1 mm 宽的引线(圆端帽还要再往西探 0.5)正压在 U13 南排五个脚唯一的出线通道上。
pcb1_escape_audit 报 U13.2 被围死:最好的一个方向两层加起来只能走 0.47 mm²,
挡它的是 $1N236 铺铜,只差 0.379 mm —— 也就是 §26.17 刚画的 VINSW-TOP 北柱。
两边一起让:
- 12 个孔改朝南 ⇒ 西边那两根 1 mm 引线消失;
VINSW-TOP北柱在 y > 87 收窄到 x 1.5~5.3(3.8 mm,断面 8.4 A ≥ 8 A), y < 87 的 C2.1 口袋仍是 x 1.5~6.65。
U13 南边于是变成一整片 x 5.514 / y 91.696 的空地,U13.2 从「被围死」名单上消失。
C. 扇出不对称的教科书样本:C%06.2
U15.14/15、U16.14/15(CH2 / CH3 的 eFuse)报「被围死」,而 CH1 / CH4 / CH5
的同一个脚完全正常 —— 五路摆位一模一样(实测五路的局部包围盒逐件相同),
所以错的一定在上游。
把五路的过孔全部换算回母版局部坐标一比就出来了:
| 通道 | C%06.2 的 GND 孔(母版局部) |
|---|---|
| CH1 / CH4 / CH5(rot 0) | (10.02, 27.10) 往东 |
| CH2 / CH3(rot 180) | (6.75, 27.10) 往西 ⇒ 正压在 U%8 脚 14/15(局部 (6.25/6.75, 28.80))唯一的南向出线口上 |
这就是 §26.13 那一条(「扇出规划器的候选角度按板坐标排,整路转 180° 之后同一个焊盘
在 CH1 往东扇、在 CH2 就往西扇」)的又一次发作。加进 _CH_FORCE_LOCAL:
('C%06', '2'): (10.020, 27.100)。
D. 剩下 10 个「被围死」不是板上的铜
改完再审,还剩 U6.6/16、U7.16、U15.3/14/15、U16.3/14/15、U18.3 十个。
逐个查挡路物,发现报出来的 GND 过孔 (52.84,82.90) 板上根本不存在
(那一点 2 mm 内一个过孔都没有)——它是审计自己给邻脚预留的出线段。
⇒ 这十个是「和邻脚抢预留位」,不是硬几何。判据很简单:
--why 列出来的挡路物,去 pcb-copper.json 里查一遍,查不到的就是预留段。
这一类布线器的细栅格逃逸自己能救回一部分(上一轮 52 个里救回 38 个),
真救不回来的才需要动摆位。
顺带记一条:route_sig 是跑完才一次性下发
中途 TaskStop 掉,板上一根铜都不会变(回读 665/491/15 与开跑前一致)。
代价只是算力。所以「先跑着看看」是安全的,发现上游有问题随时可以停。
反过来也意味着:跑到 90% 被打断 = 全白跑,长跑要放后台并挂 monitor 盯
… k/196 个网络 那一行。
实测速率(第一次跑):前 2 个网络(SDA/SCL,各挂 14 个焊盘横跨整板)吃掉 1516 s,
之后 5 个网络只要 68 s。⇒ 别拿头几个网络外推总时长。
26.20 ⭐ I²C 干线改走 Inner2(2026-09-06 第二十四轮,用户拍板)
SDA / SCL 是全板最长的两个网络(各挂 14 个焊盘,横跨整块板),
布线器在它们身上花掉 1516 s,还把外层最好的通道占了。
用户拍板:走内层,只挪跨板长干线(器件脚下的短引出仍在外层)。
工具是新写的 .claude/pcb1_i2c_l3.py(三层迷宫布线:Top / Bottom / Inner2)。
结论:中桥那 13 mm 是唯一不能进内层的一段
Inner2 上东西两半之间只有一条隔断不能割 —— 12V-SW+BR 的中桥
(x 61.5~72.6,11.1 mm,喂南西块 3.6 A,pcb1_pour.CUTS 里三条断面都盯着它)。
横着割一刀就是南西块断电,而 I²C 要过去就必须横着割。
⇒ 中桥只能外层跳过去(现在是 x 61 ↔ 73 的底层 13 mm + 两个孔)。
巧的是上一轮 pcb1_route_sig 自己也撞出了同一个结论 —— 它给 SDA 布的就是这个跳法。
除此之外内层随便走:+3V3 两大块只有 0.5 A(内层 0.5 oz 下 0.40 mm 就够),
GND-FILL-L3 只是底填(L2 才是「不许割断」的那张完整地平面)。
+12V 三块一律硬障碍,一格都不进。
| 改之前 | 改之后 | |
|---|---|---|
| I²C 总铜长 | 596 mm,内层 0 | 609 mm |
| Inner2 | — | 302 mm |
| 顶层 / 底层 | 596 mm | 157 / 150 mm |
| 换层孔 | 18 | 35 |
| 连通性 | SCL 3 片 / SDA 4 片 | 一模一样(欠的那几条是上一轮就欠着的) |
⚠️ 教训一:PEN_3V3 这个代价决定的不是长度,是平面会不会被切出孤岛
第一版给「L3 上穿 +3V3」定的代价是 1.8,于是 SCL 沿 y=50 在 3V3-SW 里
横跑了 12.7 mm、SDA 又从东边界斜插进来 —— 两根线加平面东边界围出一块
7.2 mm² 的孤岛,里面正好有 R415.2 的 +3V3 焊盘和它的过孔。
这一条三道检查全都看不见: · 铺铜的「浮铜」检查不响 —— 那块铜有本网落脚点; · 「焊盘覆盖」检查不响 —— 焊盘确实落在本网铜上; · 连接性 DRC 不响 —— 过孔把它接到顶层去了。 只有数连通域看得见。
堵住孤岛重绕是不收敛的(实测四轮,越堵越大:7.2 → 25.4 → 26.8 → 32.5 mm²)。
真正的修法是改代价:PEN_3V3 = 4.0 之后干线改走北边的 GND 底填,
只在器件附近扎一个盲端进平面 —— 盲端不切平面,连通域数不变。
代价是 Inner2 占比从 82% 掉到 70%(多出来的都是器件脚下的短引出,本来就说好留在外层)。
⇒ 规矩:内层干线穿电源面只许扎盲端,不许从一边穿到另一边。
pcb1_i2c_l3.plane_report() 在规划阶段就数连通域(+12V 要 1 块、+3V3 要 2 块),
和 pcb1_pour.grid_checks 用同一套 PO.Grid。
⚠️ 教训二:expand() 会静默丢掉最后一点上的过孔(引擎早写着,我又踩了一遍)
路径写成「L3 上走到焊盘正上方 → 换层落下去」时,expand() 的
i + 1 < n - 1 把最后一个换层点跳过了 ⇒ 末段画在 L3 上、过孔根本没生成。
现象是净距校核全过、DRC 也不响,只有数碎片才看得出来
(实测「U8.4 还是单独一片」)。修法是引擎里现成的 E._end_via(path)。
⚠️ 教训三:own(本网铜放行)不能按「格心落在本网铜里」判
free = edt >= need | own 会让 0.2 mm 的线贴着自家焊盘的边走 ——
INA226 的焊盘只有 0.28 宽,线心压在西边缘就往外探出 0.1,离邻脚只剩 0.06;
Φ0.61 的过孔更离谱(实测 −0.145,一口气 30 条)。
· 走线:own 要按半线宽内缩之后再标(真正的判据是「本网铜完全盖住这根线」);
· 过孔:根本不吃这条放行 —— edt 里本来就不含本网铜,直接按真净距判。
顺带修掉的一块浮铜(不是这次改动造成的)
铺铜回读报「Inner2 GND 有 1 块浮铜 1312.8 mm²」。查下来是板子南沿 y 0.5~9
那一整条 GND 底填:南边是板框,北边被三块电源面封死,原本只剩
x 72.673(0.4 mm,本来就走不了)和 x 115116(1.0 mm)两条缝,
而后者被 K5_VUP(114.80,28.70) / VDAC5(116.70,29.50) / EFUSE_EN3(115.00,32.40)
三个信号布线打的过孔的反焊盘掐断了 —— 那一条里一个过孔、一个通孔焊盘都没有。
它正贴着 ESP32 天线禁铺区,160 mm 的悬空铜条不能留。
⇒ 新脚本 .claude/pcb1_gnd_stitch.py,南沿补 6 个 GND 缝合孔
(过孔是通孔,一个孔就把 Inner2 这块铜接到 Inner1 的完整地平面上)。
它同样是静默的:
pcb1_pour.py下发前的report()看不见 —— 它的栅格不含别的铺铜,算出来 GND 是一整块; 只有下发后verify()回读实测铜才量得出来。
验收(2026-09-06)
| 项 | 结果 |
|---|---|
pcb1_i2c_l3.py 净距 / 拐角 / 孔距 |
✅ 全过 |
| 平面完整性(规划阶段) | ✅ Inner2 +12V 1 块 / +3V3 2 块 |
pcb1_pour.py --push --verify |
✅ 实测铺铜和计划对得上 |
pcb1_netlist.py |
SCL 3 片 / SDA 4 片,和改动前一模一样 |
drc_read.py |
72 条间距错误里没有一条牵涉 SDA/SCL(全是上一轮 route_sig 的 VDAC/EFUSE/K*/FAN) |
26.20b 挪进内层是为了腾外层给布不通的线 —— 效果实测
用户点明了目的:I²C 挪内层不是为了 I²C 自己,是为了把外层通道让给那 87 条布不通的线。
挪完立刻跑第三遍信号布线(pcb1_route_sig.py --refresh --ripup --push)验证:
| 挪之前 | 挪之后 + 第三遍布线 | |
|---|---|---|
| 已连通网络 | 148 | 163 |
| 还欠连接 | 87 条 / 74 网络 | 68 条 / 59 网络 |
| DRC 连接性错误 | 1044 | 855 |
INA_ALERT |
5 碎片 | 3 碎片 |
| 板上铜 | 3196 线 / 1000 孔 | 3516 线 / 1084 孔 |
内层干线一段没丢:--ripup 拆了 191 线 / 46 孔,55 段 L3 走线(302 mm)、
6 个南沿缝合孔全在;I²C 过孔 35 → 39(布线器补的)。
⚠️ 26.20c 引擎的层数写死是 2 —— 板上一有内层走线就崩
pcb2_route_sig.Field.__init__ 里 occ = {L: ... for L in (L_TOP, L_BOT)},
mask_of / _mask 也是同一句。板上一出现 layer 16 的走线,障碍表里就带 16 ⇒
KeyError: 16 当场崩(实测 pcb1_route_sig.py --limit 6 就崩在 _mask)。
更阴的是「滤掉 16 层就好了」这个想法是错的:
viafree = np.minimum(edt[L_TOP], edt[L_BOT]) —— 过孔是通孔,
只看外层两层的话,新过孔会直接打在内层干线上,而净距校核一声不吭。
⇒ 改成:self.lays = 障碍表里真正出现过的层(并上 1/2),
occ / edt / mask_of / _mask 全按 self.lays 建,
viafree = np.minimum.reduce([edt[L] for L in self.lays])。
只有 1/2 层时行为和以前逐格一致。
顺带把 pcb1_route_sig._layers() 里「过孔只算 (L_TOP, L_BOT)」改成四层 ——
否则碎片分析会把「内层线 + 两端的孔」数成两片。
⚠️ 26.20d 顺带查出来的:21 处真实铜重叠(在 Buck 控制器的 GND 脚上)
DRC 报 74 条间距错误。按板上真实几何逐对算下来,21 处净距 < 0,
全部是 U1.15 ~ U5.15(五个 Buck 控制器的 GND 脚)被功率级走线压进去
0.10 ~ 0.125 mm,五路完全对称 ⇒ 是 pcb1_route_pwr.py 的几何有系统性问题,
不是布线器随机撞的。做板之前必须清掉。
为什么一路绿到现在:
pcb1_route_sig的check()只核本轮新画的铜 (mine那张表),板上早就存在的线-焊盘重叠它一次都没看过。 同理pcb1_route_pwr.py --verify核的是「195 段有没有被实测铜盖住」, 也不是「有没有压到别人的焊盘上」。
26.21 ⛔ 漏跑 pcb1_parts_dump.py = 后面两轮布线全照着过期引脚映射画(2026-09-06 第二十五轮)
§26.18 按几何重排了三组引脚(U20 / U6+U7 / U21+U22+U33,共 44 个焊盘),
改动导进 PCB 了,但 pcb1_parts_dump.py 漏跑了 ——
它的文件头就写着「从原理图导入变更之后必须跑一次」。
于是 pcb1-parts.json 停在重排之前。而本项目所有脚本的焊盘网络都来自这个缓存
(pcb1_pour.load_pads → pcb1_netlist.geom → pcb1_route_sig),
只有 EasyEDA 自己的 DRC 用的是 PCB 文档里的真实焊盘网络。
⇒ 后面两轮信号布线(共 ~1000 段)里,这 33 个网络的铜连的是错信号。 板上表现是 74 条「贴片焊盘 到 导线 距离 0 mil」 —— 走线正正好落在某个焊盘上, 因为按缓存那是它自己的焊盘,按板子那是别人的。
| 判据 | 结果 |
|---|---|
| 用旧缓存的网络算净距 | 0 对违规(所以脚本一路全绿) |
| 用板上真实网络算净距 | 44 对,头几条正是 DRC 报的那几条 |
| 刷新缓存后再算 | 53 对 < 0.20,其中 45 对真重叠 |
善后:pcb1_parts_dump.py 重抓(旧的备份成 pcb1-parts.json.before-remap-refresh)→
焊盘网络 0 处不一致 → 拆掉这 33 个网络的全部铜(530 段 / 2482 mm / 138 孔,
占全板 3512 段的 15%)→ 按正确映射重布。
I²C 不受影响(SDA / SCL / INA_ALERT 都不在重排名单里)。
规矩:
pcb1_import.py --apply之后下一条命令就是pcb1_parts_dump.py。 中间插任何别的操作,后面所有几何和布线都建在沙子上,而且六道自检一条都不会响 —— 它们全都读同一份缓存,自洽得很。
顺带记两条「怎么查才算数」
- 多边形焊盘不许按包围盒判。 QFN 的散热盘(
U1.15~U5.15,21 个点的十字形) 包围盒是 2.03 × 4.32 mm,把 1/7/8/14 脚整个套进去 ⇒ 临时写的检查会凭空报出 21 处「重叠」,全是假的(按真实轮廓算净距全 ≥ 0.20)。pcb1_route_sig.expand_pads()存在就是为了这件事,临时检查别绕过它。 - DRC 的「连接性」和「间距」新鲜度不一样。 程序化建线之后连接性那一支是陈旧的
(实测
location.reload()之后 855 → 198),但间距那一支是即时的 —— 重载前后都是 74 条、内容逐字相同 ⇒ 间距报出来的东西不能当成陈旧数据糊弄过去。