原理图/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
130 行
4.9 KiB
Python
130 行
4.9 KiB
Python
# -*- 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()
|