文件

116 行
4.7 KiB
Python

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
# -*- coding: utf-8 -*-
u"""FAN-R2 落到下板 PCB1:**只动风扇那一块**的 24 个元件,别的 277 个和已有铜一律不碰。
/c/Python314/python .claude/pcb1_fan.py # 干跑
/c/Python314/python .claude/pcb1_fan.py --push # 摆件 + 拆废铜 + 存盘
为什么不直接 `pcb1_place.py --push`:那会重摆全部 301 个元件,
把已经布好的 3116 段铜全部作废。整板重布是 PROGRESS 里单列的下一步,不该由这一轮顺手引爆。
拆铜的判据只有一条:**这个网络在板上已经一个焊盘都没有了**(旧风扇拓扑留下的孤儿),
外加 FAN_PWM —— 它的两个焊盘都还在,但 R733 从 (98,80.5) 挪到了 (108,74),旧铜接不上了。
"""
import io
import json
import os
import sys
HERE = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, HERE)
from eda import run
import pcb1_place as PL
PCB = '7e9415a16a909c51'
MIL = 39.3701
FAN = ['Q6', 'Q7', 'Q8', 'Q9', 'Q10', 'DZ3', 'D2', 'C738',
'R733', 'R734', 'R746', 'R747', 'R748', 'R749', 'R750', 'R751',
'R752', 'R753', 'R754', 'R755', 'R756', 'R757', 'J26', 'J27']
# 死网络(板上已无焊盘)+ FAN_PWM(焊盘在、但 R733 挪了位,旧铜作废)
RIP = ['$17N148', '$17N151', '$17N154', 'FAN_TACH', 'FAN_PWM']
def call(js, timeout=300):
r = run(js, timeout=timeout)
if not r.get('success'):
raise RuntimeError(json.dumps(r, ensure_ascii=False)[:900])
return r['result']
def main():
push = '--push' in sys.argv
plan = [[d, round(PL.POS[d][0] * MIL, 2), round(PL.POS[d][1] * MIL, 2), PL.POS[d][2]] for d in FAN]
print(u'风扇块 %d 个元件;拆废铜网络 %s' % (len(plan), ', '.join(RIP)))
for d, x, y, r in plan:
print(u' %-5s (%8.2f, %8.2f) rot %d' % (d, x, y, r))
if not push:
print(u'加 --push 执行')
return
call("""
await eda.dmt_EditorControl.openDocument('%s'); await new Promise(r=>setTimeout(r,2000));
return 1;""" % PCB)
n = call("""
const P = %s;
const map = {};
for (const c of await eda.pcb_PrimitiveComponent.getAll()) map[c.getState_Designator()] = c;
let n = 0;
for (const [d, x, y, rot] of P) {
const c = map[d]; if (!c) throw new Error('板上没有 ' + d);
await eda.pcb_PrimitiveComponent.modify(c.getState_PrimitiveId(), {layer: 1});
await eda.pcb_PrimitiveComponent.modify(c.getState_PrimitiveId(), {x, y, rotation: rot});
n++;
}
return n;
""" % json.dumps(plan))
print(u'已摆 %d 个元件' % n)
# 拆铜:循环删到剩 0(skill §9x:一次 getAll 逐条 delete 删不干净)
rip = call("""
const NETS = %s;
let dl = 0, dv = 0;
for (let pass = 0; pass < 4; pass++) {
let left = 0;
for (const l of await eda.pcb_PrimitiveLine.getAll())
if (NETS.includes(l.getState_Net())) { await eda.pcb_PrimitiveLine.delete(l.getState_PrimitiveId()); dl++; }
for (const v of await eda.pcb_PrimitiveVia.getAll())
if (NETS.includes(v.getState_Net())) { await eda.pcb_PrimitiveVia.delete(v.getState_PrimitiveId()); dv++; }
for (const l of await eda.pcb_PrimitiveLine.getAll()) if (NETS.includes(l.getState_Net())) left++;
for (const v of await eda.pcb_PrimitiveVia.getAll()) if (NETS.includes(v.getState_Net())) left++;
if (!left) return {dl, dv, left: 0, pass};
}
let left = 0;
for (const l of await eda.pcb_PrimitiveLine.getAll()) if (NETS.includes(l.getState_Net())) left++;
for (const v of await eda.pcb_PrimitiveVia.getAll()) if (NETS.includes(v.getState_Net())) left++;
return {dl, dv, left};
""" % json.dumps(RIP))
print(u'拆铜:导线 %d 段 / 过孔 %d 个,剩余 %d' % (rip['dl'], rip['dv'], rip['left']))
if rip['left']:
raise SystemExit(u'废铜没删干净')
got = call("""
const P = %s;
const map = {};
for (const c of await eda.pcb_PrimitiveComponent.getAll()) map[c.getState_Designator()] = c;
const out = [];
for (const [d, x, y, rot] of P) {
const c = map[d];
out.push([d, Math.round(c.getState_X()*100)/100, Math.round(c.getState_Y()*100)/100,
c.getState_Rotation(), c.getState_Layer()]);
}
await eda.pcb_Document.save();
return out;
""" % json.dumps(plan))
bad = []
for (d, x, y, r), (gd, gx, gy, gr, gl) in zip(plan, got):
if abs(gx - x) > 0.02 or abs(gy - y) > 0.02 or gr != r or gl != 1:
bad.append(u'%s 期望 (%.2f,%.2f) rot %d L1,实测 (%.2f,%.2f) rot %s L%s' % (d, x, y, r, gx, gy, gr, gl))
if bad:
raise SystemExit(u'回读对不上:\n ' + u'\n '.join(bad))
print(u'回读 %d 个元件,位置/角度/层逐个一致;已存盘' % len(got))
main()