R2 焊接:丝印临时换成器件值 + 摆放优化 + 1:1 器件值打印稿

2026-09-25 为焊接底板与旧版刀片(BLADE-PCB 3b9c4e39c8d164db):

- silk_value.py:隐藏位号、在原位建自由丝印写器件值(Value,没有就用型号),
  --restore 按 _silk_value_restore.json 删字并恢复位号。⚠ 再出 Gerber / 下单前必须先 --restore。
- silk_value_plan.py:器件值摆放优化(不压焊盘 / 不重叠 / 不出框 / 避开开槽与金手指区;
  软代价:压过孔、压他件本体、离本件远、缩字号)。EDA 默认字体实测字宽 ≈0.78×字高。
- print_value.py:两块板背面镜像 1:1 画在同一张 A4,红框标 1 脚;
  print/print_1to1.ps1 按 210×297 mm 直送打印机(不经 PDF 阅读器缩放)。
- 数据:_silk_value_geom/_extra(板上读回几何)、_dump/_plan(排位结果)。

Co-Authored-By: Claude Opus 5.5 <[email protected]>
这个提交包含在:
zhou yang
2026-09-27 10:27:20 +08:00
共同撰写人 Claude Opus 5.5
父节点 dc0395fde0
当前提交 cae567dfd8
共修改 10 个文件,包含 1840 行新增和 0 行删除
+116
查看文件
@@ -0,0 +1,116 @@
# -*- coding: utf-8 -*-
u"""焊接用:把底板 / 旧版刀片的丝印从「位号」临时换成「器件值」,焊完再换回来。
/c/Python314/python .claude/r2/silk_value.py --push # 隐藏位号 + 在原位建器件值文字,存还原表
/c/Python314/python .claude/r2/silk_value.py --restore # 删掉建的文字 + 位号恢复可见
- 器件值 = 元件 `Value` 属性(阻容感);没有就用 `Device`(型号)去掉 `_Cxxxx` 后缀,个别手工缩写(LABEL_FIX)。
- 位号没有「换成别的属性显示」的接口(PCB 属性不能新建),所以做法是:
位号 `valueVisible=false` + 同层同位置同字号建一条**自由丝印** `pcb_PrimitiveString`。
- 还原表 `_silk_value_restore.json`:建出来的文字 id + 原本可见的位号 id。⚠ 再下单打板前必须 --restore。
"""
import io
import json
import os
import re
import sys
sys.stdout.reconfigure(encoding='utf-8')
HERE = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, os.path.dirname(HERE))
from eda import run # noqa: E402
BOARDS = {'BASE': '7b9524b6aaf6f235', 'BLADE': '3b9c4e39c8d164db'} # 刀片用旧版 BLADE-PCB
RESTORE = os.path.join(HERE, '_silk_value_restore.json')
LABEL_FIX = {
'6.3TPV2200M10X10.5 SMD': '2200uF 6.3V',
'BM24-50DS/2-0.35V(51) HRS-PIN': 'BM24-50DS',
'PCA9555PW,112': 'PCA9555PW',
'NCP18XH103F03RB': 'NTC 10k',
'MI8-KEY-PAD D1.5': 'KEY',
'2.54mm 1*5P 直排针': '1x5P 2.54',
}
def label(value, device):
if value:
return value.replace(u'kΩ', 'k').replace(u'MΩ', 'M')
d = device or ''
if d in LABEL_FIX:
return LABEL_FIX[d]
return re.sub(r'_C\d+$', '', d)
READ = u"""
await eda.dmt_EditorControl.openDocument('%s');
await new Promise(r=>setTimeout(r,3000));
const C = await eda.pcb_PrimitiveComponent.getAll()||[];
const cv = {}; C.forEach(c=>{const o=c.otherProperty||{}; cv[c.primitiveId]=[o.Value||null, o.Device||null];});
const A = (await eda.pcb_PrimitiveAttribute.getAll()||[]).filter(a=>a.key==='Designator').map(a=>({id:a.primitiveId, pid:a.parentPrimitiveId, ref:a.value, layer:a.layer, x:a.x, y:a.y, rot:a.rotation, fs:a.fontSize, lw:a.lineWidth, align:a.alignMode, vis:a.valueVisible, mirror:a.mirror, font:a.fontFamily, reverse:a.reverse, expansion:a.expansion}));
return {cv, attrs:A};
"""
PUSH = u"""
await eda.dmt_EditorControl.openDocument('%s');
await new Promise(r=>setTimeout(r,3000));
const J = %s;
const made = [], hid = [], err = [];
for (const t of J) {
try {
const s = await eda.pcb_PrimitiveString.create(t.layer, t.x, t.y, t.text, t.font, t.fs, t.lw, t.align, t.rot, t.reverse, t.expansion, t.mirror, false);
if (s) made.push([t.ref, s.primitiveId]); else err.push(['create', t.ref]);
await eda.pcb_PrimitiveAttribute.modify(t.id, {valueVisible: false});
hid.push(t.id);
} catch (e) { err.push([t.ref, String(e)]); }
}
await eda.pcb_Document.save();
return {made, hid, err};
"""
UNDO = u"""
await eda.dmt_EditorControl.openDocument('%s');
await new Promise(r=>setTimeout(r,3000));
const R = %s;
const ok = await eda.pcb_PrimitiveString.delete(R.made.map(m=>m[1]));
let n = 0; for (const id of R.hid) { try { await eda.pcb_PrimitiveAttribute.modify(id, {valueVisible: true}); n++; } catch (e) {} }
await eda.pcb_Document.save();
return {deleted: ok, shown: n};
"""
def push():
if os.path.exists(RESTORE):
sys.exit(u'已有还原表 %s —— 先 --restore 再重推' % RESTORE)
rec = {}
for name, u in BOARDS.items():
d = run(READ % u, timeout=300)['result']
todo = []
for a in d['attrs']:
if not a['vis']:
continue # 原本就隐藏的位号不动
v, dev = d['cv'].get(a['pid'], [None, None])
a['text'] = label(v, dev)
todo.append(a)
r = run(PUSH % (u, json.dumps(todo, ensure_ascii=False)), timeout=900)
res = r.get('result')
assert res, json.dumps(r, ensure_ascii=False)[:600]
rec[name] = {'pcb': u, 'made': res['made'], 'hid': res['hid']}
io.open(RESTORE, 'w', encoding='utf-8').write(json.dumps(rec, ensure_ascii=False, indent=1))
print(u'%s:建 %d 条器件值、藏 %d 个位号,错误 %s' % (name, len(res['made']), len(res['hid']), res['err']))
def restore():
rec = json.load(io.open(RESTORE, encoding='utf-8'))
for name, R in rec.items():
r = run(UNDO % (R['pcb'], json.dumps(R, ensure_ascii=False)), timeout=900)
print(name, r.get('result') or r)
os.rename(RESTORE, RESTORE + '.done')
if __name__ == '__main__':
if '--push' in sys.argv:
push()
elif '--restore' in sys.argv:
restore()
else:
print(__doc__)