文件
phonerail/.claude/p6_place.py
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

130 行
4.9 KiB
Python

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
# -*- coding: utf-8 -*-
u"""新建 P6-FAN-EDL 页并放置元件,读回真实引脚坐标存 .claude/p6-pins.json。
用法: /c/Python314/python .claude/p6_place.py [--push]
"""
import json
import os
import sys
HERE = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, HERE)
from eda import run
SCH = 'c63aa0a04d951314'
LIB = '0819f05c4eef4c71ace90d822a990e87'
P = {
'HC595': '94fc47f3127c49c1b8e18e741938eebc', # C5947 74HC595D
'AO3400': '2b6cc05daeb34c16b9e00706a375fc9f', # C20917 AO3400A
'R100K': 'acc294b6661948399f609b41c77ed19f', # C25741
'R10K': 'c3b9baa5ef2e4070a4c0f9e9cd04fe6e', # C25744
'R1K': '65abbad5fa864933b552e0f016ece0db', # C11702
'C100N': '87bb635d0b2f489a9f60e7cd225beb3c', # C1525
'C22U': '0de9d28bbcd34ca3bf2a4d78faaa50bb', # C12891 22uF/25V 1206
}
# 这一轮新增的料(还没进 eda-parts.json)
NEW = {'R3K3': 'C25890', 'SS34': 'C8678', 'KF2510': 'C2940511'}
# (位号, 器件键, x, y, rotation)
PLACE = [
# --- 【A】EDL 驱动:第三片 74HC595 ---
('U33', 'HC595', 250, 600, 0),
('C739', 'C100N', 120, 690, 270),
('R735', 'R100K', 430, 660, 270),
('R736', 'R100K', 490, 660, 270),
('R737', 'R100K', 550, 660, 270),
('R738', 'R100K', 610, 660, 270),
('R739', 'R100K', 670, 660, 270),
# --- 【B】风扇驱动 ---
('Q6', 'AO3400', 700, 330, 0),
('R733', 'R1K', 600, 330, 0),
('R734', 'R100K', 660, 270, 270),
('D2', 'SS34', 790, 430, 270),
('C738', 'C22U', 880, 620, 270),
('R730', 'R10K', 950, 300, 270),
('R731', 'R10K', 870, 240, 0),
('R732', 'R3K3', 950, 200, 270),
('J26', 'KF2510', 1080, 700, 0),
('J27', 'KF2510', 1080, 620, 0),
('J28', 'KF2510', 1080, 540, 0),
('J29', 'KF2510', 1080, 460, 0),
('J30', 'KF2510', 1080, 380, 0),
]
def call(js, timeout=180):
r = run(js, timeout=timeout)
if not r.get('success'):
raise RuntimeError(json.dumps(r, ensure_ascii=False)[:800])
return r['result']
def main():
if '--push' not in sys.argv:
print(u'元件 %d 个;加 --push 执行' % len(PLACE))
return
ids = call("return await eda.lib_Device.getByLcscIds(%s);"
% json.dumps(list(NEW.values())))
uu = {d['supplierId']: d['uuid'] for d in ids}
for k, lcsc in NEW.items():
assert lcsc in uu, u'找不到 %s (%s)' % (k, lcsc)
P[k] = uu[lcsc]
print(u'新料 uuid: %s' % json.dumps({k: P[k] for k in NEW}, ensure_ascii=False))
page = call("""
const info = await eda.dmt_Schematic.getSchematicInfo('%s');
for (const p of (info.page||[])) if (p.name==='p6-fan-edl') return p.uuid;
const u = await eda.dmt_Schematic.createSchematicPage('%s');
await eda.dmt_Schematic.modifySchematicPageName(u,'P6-FAN-EDL');
return u;
""" % (SCH, SCH))
print(u'页面 %s' % page)
call("""
await eda.dmt_EditorControl.openDocument('%s'); await new Promise(r=>setTimeout(r,900));
const n=(await eda.dmt_Schematic.getCurrentSchematicPageInfo()).name;
if (n!=='P6-FAN-EDL') throw new Error('page='+n);
for (const c of await eda.sch_PrimitiveComponent.getAll()){
if (c.getState_ComponentType()==='sheet') continue;
await eda.sch_PrimitiveComponent.delete(c.getState_PrimitiveId());
}
for (const w of await eda.sch_PrimitiveWire.getAll()) await eda.sch_PrimitiveWire.delete(w.getState_PrimitiveId());
for (const t of await eda.sch_PrimitiveText.getAll()) await eda.sch_PrimitiveText.delete(t.getState_PrimitiveId());
return 1;
""" % page)
for i in range(0, len(PLACE), 6):
chunk = [[d, P[k], x, y, r] for d, k, x, y, r in PLACE[i:i + 6]]
call("""
for (const [d,uuid,x,y,rot] of %s){
await eda.sch_PrimitiveComponent.create({libraryUuid:'%s', uuid}, x, y, undefined, rot, false, true, true);
for (const c of await eda.sch_PrimitiveComponent.getAll()){
if (c.getState_ComponentType()!=='part') continue;
if (Math.round(c.getState_X())!==x || Math.round(c.getState_Y())!==y) continue;
await c.toAsync().setState_Designator(d).done();
}
}
return 1;
""" % (json.dumps(chunk), LIB))
print(u'已放置 %d 个元件' % len(PLACE))
pins = call("""
const out={};
for (const c of await eda.sch_PrimitiveComponent.getAll()){
if (c.getState_ComponentType()!=='part') continue;
const d=c.getState_Designator();
const ps=await c.getAllPins();
out[d]=ps.map(p=>[p.getState_PinNumber(),Math.round(p.getState_X()),Math.round(p.getState_Y())]);
}
return out;
""")
pins['_page'] = page
json.dump(pins, open(os.path.join(HERE, 'p6-pins.json'), 'w', encoding='utf-8'),
ensure_ascii=False, indent=1)
for d in sorted(k for k in pins if not k.startswith('_')):
print(u'%-6s %s' % (d, ' '.join('%s@%d,%d' % tuple(p) for p in pins[d])))
main()