初始导入: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
这个提交包含在:
@@ -0,0 +1,111 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
u"""C2-HUB 补一个上游 VBUS 检测分压:VBUS_UP(5V) -> 10k/20k -> UP_VBUS_DET -> 下板 IO44。
|
||||
|
||||
用法: /c/Python314/python .claude/c2_vbusdet.py [--push]
|
||||
|
||||
为什么要分压:J23 的 VBUS 是 5V,而排针那头接的是 ESP32 的 IO44(3.3V 域)。
|
||||
10k/20k 得到 5×20/30 = 3.33V;USB 上限 5.25V 时是 3.5V,仍在 ESP32 的
|
||||
绝对最大值 3.6V 以内,而且远高于 VIH(≈2.48V)。
|
||||
主机没插时 VBUS=0 -> 读到 0,这正是这个信号要的判据。
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
HERE = os.path.dirname(os.path.abspath(__file__))
|
||||
sys.path.insert(0, HERE)
|
||||
from eda import run
|
||||
|
||||
PAGE = '472c9bdbd7180ac4' # C2-HUB
|
||||
LIB = '0819f05c4eef4c71ace90d822a990e87'
|
||||
R10K = 'c3b9baa5ef2e4070a4c0f9e9cd04fe6e' # C25744
|
||||
R20K = '3a163ef2745c43cd822f855b5ea3efa4' # C25765
|
||||
|
||||
Y = 120
|
||||
R721, R722 = (880, Y), (980, Y) # 上臂 10k / 下臂 20k
|
||||
EXPECT = {'R721': [(860, Y), (900, Y)], 'R722': [(960, Y), (1000, Y)]}
|
||||
|
||||
|
||||
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'待加:R721 10k / R722 20k + VBUS_UP 端口 + UP_VBUS_DET 端口 + 地旗(加 --push)')
|
||||
return
|
||||
|
||||
call("""
|
||||
await eda.dmt_EditorControl.openDocument('%s'); await new Promise(r=>setTimeout(r,900));
|
||||
const n=(await eda.dmt_Schematic.getCurrentSchematicPageInfo()).name;
|
||||
if (n!=='C2-HUB') throw new Error('page='+n);
|
||||
// 重跑安全:先把上一轮加的东西删掉
|
||||
for (const c of await eda.sch_PrimitiveComponent.getAll()){
|
||||
const t=c.getState_ComponentType();
|
||||
if (t==='part' && ['R721','R722'].includes(c.getState_Designator())){
|
||||
await eda.sch_PrimitiveComponent.delete(c.getState_PrimitiveId()); continue; }
|
||||
if (t!=='netflag' && t!=='netport') continue;
|
||||
let nn=''; try{nn=c.getState_Net()||''}catch(e){}
|
||||
const x=Math.round(c.getState_X()), y=Math.round(c.getState_Y());
|
||||
if (x>=700 && y<=180 && (nn==='UP_VBUS_DET' || nn==='GND' || nn==='VBUS_UP'))
|
||||
await eda.sch_PrimitiveComponent.delete(c.getState_PrimitiveId());
|
||||
}
|
||||
for (const w of await eda.sch_PrimitiveWire.getAll()){
|
||||
const a=w.getState_Line(); let hit=false;
|
||||
for (let i=0;i<a.length;i+=2) if (a[i]>=700 && a[i+1]<=180) hit=true;
|
||||
if (hit) await eda.sch_PrimitiveWire.delete(w.getState_PrimitiveId());
|
||||
}
|
||||
return 1;
|
||||
""" % PAGE)
|
||||
|
||||
call("""
|
||||
for (const [d,uuid,x,y] of %s){
|
||||
await eda.sch_PrimitiveComponent.create({libraryUuid:'%s', uuid}, x, y, undefined, 0, 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([['R721', R10K, R721[0], R721[1]],
|
||||
['R722', R20K, R722[0], R722[1]]]), LIB))
|
||||
|
||||
pins = call("""
|
||||
const out={};
|
||||
for (const c of await eda.sch_PrimitiveComponent.getAll()){
|
||||
if (c.getState_ComponentType()!=='part') continue;
|
||||
const d=c.getState_Designator();
|
||||
if (d!=='R721' && d!=='R722') continue;
|
||||
out[d]=(await c.getAllPins()).map(p=>[Math.round(p.getState_X()),Math.round(p.getState_Y())]);
|
||||
}
|
||||
return out;
|
||||
""")
|
||||
bad = [u'%s 期望 %s 实测 %s' % (d, EXPECT[d], sorted(map(tuple, pins.get(d, []))))
|
||||
for d in EXPECT if sorted(map(tuple, pins.get(d, []))) != EXPECT[d]]
|
||||
if bad:
|
||||
raise SystemExit(u'引脚坐标对不上:\n ' + '\n '.join(bad))
|
||||
print(u'引脚坐标核对通过')
|
||||
|
||||
W = [[800, Y, 860, Y], # VBUS_UP -> R721
|
||||
[900, Y, 960, Y], # R721 -> R722(中点就在这一段上)
|
||||
[930, Y, 930, 60], # 中点 -> UP_VBUS_DET
|
||||
[1000, Y, 1050, Y], [1050, Y, 1050, 90]]
|
||||
PT = [['BI', 'VBUS_UP', 800, Y, 180], ['BI', 'UP_VBUS_DET', 930, 60, 0]]
|
||||
F = [['Ground', 'GND', 1050, 90, 0]]
|
||||
TX = [(700, 175, u'上游 VBUS 检测:5V 经 10k/20k 分到 3.33V 送 IO44(§22.2)。主机没插时读 0。', 10)]
|
||||
call("for (const s of %s) await eda.sch_PrimitiveWire.create(s); return 1;" % json.dumps(W))
|
||||
call("for (const p of %s) await eda.sch_PrimitiveComponent.createNetPort(p[0],p[1],p[2],p[3],p[4],false); return 1;"
|
||||
% json.dumps(PT))
|
||||
call("for (const f of %s) await eda.sch_PrimitiveComponent.createNetFlag(f[0],f[1],f[2],f[3],f[4],false); return 1;"
|
||||
% json.dumps(F))
|
||||
call("for (const t of %s) await eda.sch_PrimitiveText.create(t[0],t[1],t[2],0,null,null,t[3],false,false,false,0); return 1;"
|
||||
% json.dumps([list(t) for t in TX], ensure_ascii=False))
|
||||
print(u'推送完成')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
在新工单中引用
屏蔽一个用户