文件
phonerail/.claude/sch_text.py
T
zhou yang和Claude Opus 5 2bfe308b30 初始导入:PhoneRail 五路手机直供电源板
原理图/PCB 已在 EasyEDA 里做到 12 页跨页 0 漏接,固件刚完成骨架包 A1。
这次是把已有的一切一次性纳入版本控制,没有改动任何设计内容。

纳入:
- 设计与需求文档、PROGRESS.md、小米8 参考原理图 PDF 与追脚脚本
- .claude/ 下的 EasyEDA 桥接工具链与几何/网表缓存(eda-parts.json、
  pcb-parts.json、pcb-pads.json、p2-ch1.json 等,是重画各页的唯一事实来源)
- 117 张验证截图(本项目所有方向问题都是靠人眼看截图发现的,属于证据不是垃圾)
- firmware/ 的 A1 骨架与 site/ 文档站源码

.gitignore 排除:构建产物(firmware/build、host/build、sdkconfig)、
site/node_modules、__pycache__、桥接日志 _bridge.log、脚本自标的 *.stale。

.gitattributes 默认 `* -text`:现有 .py/.json 大多是 CRLF,原样存,
不让 git 重写行尾。唯一例外是 *.sh 强制 LF —— 带 \r 的 shell 脚本 bash 跑不了。

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01QYuExfgyYa6DzRRcUso8M8
2026-09-06 18:18:14 +08:00

124 行
7.3 KiB
Python
原始文件 Blame 文件历史

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
# -*- coding: utf-8 -*-
u"""P3 / P3B / P6 三页的**图面文字整页重写**。
/c/Python314/python .claude/sch_text.py # 只看现状与计划
/c/Python314/python .claude/sch_text.py --push # 删光旧文字 -> 写一套新的
## 为什么要整页重写
2026-09-06 读回来发现这三页的 `sch_PrimitiveText` **层层叠了好几代**:
P3 有 44 条、P3B 64 条、P6 76 条,其中大量是**同一坐标同一内容的完全重复**
(历代脚本只 `create` 不 `delete`),还有互相矛盾的旧说明叠在一起。
渲染出来就是那一坨看不清的黑块 —— 而且 `verify_sch` / `xpage` / DRC
**四道验证一条都不管文字**,所以它烂了很久也没人发现。
⚠️ 判据:`sch_PrimitiveText` 只有图面注释,**标题栏不是它**
(标题栏字段是图框自己的,`getAll()` 里根本不出现),所以整页删干净是安全的。
顺带把 2026-09-06 换脚之后**变成假话**的几条改掉:
`IO39~IO42 留给 JTAG`、`IO47/IO48 备用`、`U22.Q7 = HUB_RST`、
`QA~QE = EDL_EN1~5;QF/QG/QH 备用不接`、`风扇座 KF2510-3A`。
"""
import json
import os
import sys
HERE = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, HERE)
from eda import run # noqa: E402
PAGE = {'P3': '12f74666e70167e4', 'P3B': 'f42285b3728794d0', 'P6': 'fd00f13e59336392'}
TEXT = {
'P3': [
(45, 806, u'【A】ESP32-S3-WROOM-1 主控(U20)'),
(45, 795, u'3V3 由 P1 的 U19 辅助 Buck 供给;EN 端 10k + 100nF 上电复位'),
(45, 395, u'【B】USB-C 调试口 —— ESP32-S3 原生 USB-Serial-JTAG(IO19/IO20)'),
(45, 384, u'VBUS 故意不接:板子由 12V 供电,避免 USB 反灌。CC1/CC2 各 5.1k 下拉作 UFP。'),
(645, 700, u'【C】I2C 上拉 4.7k + 三路开漏上拉'),
(645, 470, u'【D】NTC 温度采样(10k B3380 + 10k 分压 + 100nF)'),
# ⚠️ 右下角标题栏的左边界约在 x=476,y<210 那一片的文字末端必须 < 470
# (宽度按 CJK 12 / ASCII 6 估;`sch_text.py --push` 前会自己核一遍)
(45, 205, u'引脚按 PCB 几何重排(2026-09-06,§26.18):'),
(45, 194, u'除 USB(IO19/IO20 硬连线)与两路 NTC(要 ADC1)'),
(45, 183, u'外,全部信号走 GPIO matrix,落哪个脚都行 ——'),
(45, 172, u'按「出线方向 = 目的地方向」重排。'),
(45, 158, u'IO39~IO42 原留给引脚 JTAG,现改作 GPIO:'),
(45, 147, u'调试走原生 USB-Serial-JTAG(出厂 eFuse 默认),'),
(45, 136, u'板上没有 JTAG 排针。别烧 DIS_USB_JTAG。'),
(45, 122, u'有意不接:IO0/IO3/IO45/IO46 是 strapping;'),
(45, 111, u'IO35~IO37 留 R8 版 PSRAM;TXD0/RXD0 引到测试点;'),
(45, 100, u'IO4/IO5/IO7 空出来备用(三个都带 ADC1)。'),
],
'P3B': [
# ⚠️ 这三行右边 x=445 起是【B】PCA9555 那一块,末端要留在 430 以内
(45, 806, u'【A】74HC595 ×3 的前两片(U21 / U22)'),
(45, 795, u'链序 U21 → U22 → U33(在 P6),整条链 24 位;'),
(45, 784, u'SRCLK/RCLK/OE# 三片共用,OE# 上拉 100k ⇒ 复位全高阻'),
(445, 790, u'【B】PCA9555 输入扩展 —— 地址 0x20(A0/A1/A2 全接地)'),
(445, 779, u'IO0_7 与 IO1_5~7 备用脚直接接地:上电默认即输入,'),
(445, 768, u'固件严禁把 Port0[7] / Port1[7:5] 配成输出。'),
(45, 205, u'【C】DAC63204 ×2 —— 5 路调压'),
(45, 194, u'U6 = 0x4A(A0→SDA),U7 = 0x4B(A0→SCL)'),
(45, 180, u'三处 datasheet 强制要求,接错也不报错:'),
(45, 169, u' 1) FBx 必须接回 OUTx(电压模式的闭环反馈)'),
(45, 158, u' 2) CAP 接 2.2uF 到 AGND(LDO 旁路 0.5~15uF)'),
(45, 147, u' 3) VREF 空置时 100nF 到地 + 10k 上拉 VDD'),
(45, 136, u'内部基准 1.212V,×2 -> 满量程 2.424V(不是 2.5V)'),
(45, 122, u'通道按几何重排(§26.18):U6 = VDAC2/4/1(去西半板),'),
(45, 111, u'U7 = VDAC3/5(去东半板)。四通道对等,只改固件通道号。'),
],
'P6': [
(45, 806, u'【A】第三片 74HC595(U33)—— CH2 / CH3 的六个侧键 + EDL_EN1 + HUB_RST'),
(45, 790, u"级联在 U22 之后:U22.QH'(9) -> U33.SER(14),网络名 SR_CAS2,整条链 24 位。"),
(45, 774, u'2026-09-06 按 PCB 几何重排(§26.18):U33 在 y≈70 mm,正对北排的 CH2 / CH3,'),
(45, 758, u'比原来从 U21(y≈50) 拉过去近 20~30 mm。Q0=EDL_EN1,Q1~Q3=K2,Q4~Q6=K3,Q7=HUB_RST。'),
(45, 742, u'EDL_EN 与按键的 100k 下拉不放这一页 —— 放在载板上紧挨模拟开关(§8.1 复位安全)。'),
(45, 520, u'【B】风扇:低边 N-MOS + PWM,5 个风扇并一路(§22.6)'),
(45, 500, u'Q6 AO3400A 切风扇回流,D2 SS34 做续流 —— 风扇是感性负载,'),
(45, 484, u'少了它 MOS 会被反峰打穿。FAN_PWM = IO18(模块脚 11),FAN_TACH = IO16(模块脚 9)。'),
(45, 468, u'5 个 TACH 并联做线或,停一个频率掉约 1/5(分不出是哪一个)。'),
(45, 444, u'TACH 必须分压:低边 PWM 关断时风扇地被抬到 12V,'),
(45, 428, u'TACH 是集电极开路,也跟着到 12V —— 直连 GPIO 会打穿 ESP32。'),
(45, 412, u'10k 上拉到 12V + 10k/3.3k 分压 -> 最高 2.98V。'),
(45, 396, u'关断期间读到稳定高电平(测不到转速),导通期间才有脉冲 ——'),
(45, 380, u'这是低边调速的固有限制,不是接线错。'),
(45, 190, u'风扇电流 4x0.10 + 1x0.30 = 0.70A @12V;'),
(45, 176, u'12V 输入预算 7.6 -> 8.3A,10A 适配器仍有余量。'),
(45, 162, u'风扇座 2510-3A 直针(C2803349):'),
(45, 148, u'pin1 = +12V,pin2 = 风扇回流(MOS 漏极),pin3 = TACH。'),
],
}
JS = u"""
await eda.dmt_EditorControl.openDocument('%s');
await new Promise(r => setTimeout(r, 1500));
const old = await eda.sch_PrimitiveText.getAll();
const ids = old.map(t => t.getState_PrimitiveId());
%s
const T = %s;
%s
await eda.sch_Document.save();
await new Promise(r => setTimeout(r, 800));
return {removed: ids.length, made: %d,
now: (await eda.sch_PrimitiveText.getAll()).length};
"""
DEL = u"if (ids.length) await eda.sch_PrimitiveText.delete(ids);"
MAKE = u"for (const t of T) await eda.sch_PrimitiveText.create(t[0], t[1], t[2], 0, null, null, 12);"
if __name__ == '__main__':
go = '--push' in sys.argv
for pg in ('P3', 'P3B', 'P6'):
rows = [[x, y, s] for x, y, s in TEXT[pg]]
print(u'%-4s 新文字 %d 条' % (pg, len(rows)))
if not go:
continue
r = run(JS % (PAGE[pg], DEL, json.dumps(rows, ensure_ascii=False), MAKE, len(rows)),
timeout=600)
assert r.get('success'), json.dumps(r, ensure_ascii=False)[:400]
q = r['result']
print(u' 删 %d / 建 %d / 现在 %d %s'
% (q['removed'], q['made'], q['now'], u'✅' if q['now'] == len(rows) else u'❌'))
if not go:
print(u'(未加 --push,没有改动)')