R2 底板:按用户布局重布风扇窗口 + L1 走廊重开 + 位号丝印重排
布线(窗口整体重布,已下发): - 拆窗口内 43 段(用户手布的那批,用户选「拆掉重来」),补 139 段 / 7 孔, GND 回流孔 10 个;fan_check 对板上真实快照逐项净距达标(含「新孔 vs 内层线」)。 - ⛔ 根因:pcb_base.PD_L1 里的 L1 走廊是按**旧摆位**开的(注释坐标全是旧的), 用户重摆后与件对不上 ⇒ 四条长途网必然布不通。重开六条走廊后未完成 4 → 2。 走廊必须盖住焊盘正上方,只盖沿途不行。断面:几何 11.80 / 铺铜后实测 9.82(要 8.0)。 - 与拆线前逐网对比:没引入任何新的连通性问题(GND 未接 58→48、+3V3 2→0、 两路 TACH 2/1→0、+12V 一字不差)。 定版:板上铜以**用户自己布好的那版**为准,不再改动。 丝印(silk_base.py,已下发并读回核对 150/150): - 压焊盘 128→4、压过孔 48→8、越框 8→3、互相重叠 34 对→0;字号不变。 - 三条坑:rotation 是度且不归一化(900=180°);别拿「本体≥5mm」当保留白名单 (会豁免掉 R9A/D3/U13 这些该重排的件);「离本体」必须设硬上限 + 降级策略。 新工具:silk_base.py(丝印重排)、l1_section.py(L1 12V 主块逐 y 断面核算)、 fan_rip.py(按窗口拆线,拆前后比对全板线/孔总数防连带删除)。 Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_0168Bu6SEx3cXXCJLkdnE6zB
这个提交包含在:
@@ -0,0 +1,71 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
u"""L1 `+12V` 主块的**逐 y 水平断面**核算(§6.4 要 ≥ 8.0 mm)。
|
||||
|
||||
/c/Python314/python .claude/r2/l1_section.py # 核 pcb_base.PD_L1 现状
|
||||
/c/Python314/python .claude/r2/l1_section.py --cfg # 核 _base_window.json 里的 pd_l1_extra
|
||||
|
||||
主块 x 0.5~27.8(宽 27.30),电流南北流 ⇒ 断面是水平线,线上被走廊占掉的 x 跨度要扣掉。
|
||||
横带(沿 x 长)很贵、竖带(沿 y 长)几乎免费 —— 旧注释「一根 0.15 的线占约 0.5」说的就是竖线。
|
||||
槽指头在 x ≥ 27.5,走廊 x 一律 ≤ 27.5 ⇒ 天然不碰任何一槽的供电路径。
|
||||
"""
|
||||
import io
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
HERE = os.path.dirname(os.path.abspath(__file__))
|
||||
sys.path.insert(0, os.path.dirname(HERE))
|
||||
sys.path.insert(0, HERE)
|
||||
import pcb_base as B # noqa: E402
|
||||
|
||||
MIN_SECTION = 8.0
|
||||
MAIN = B.l1_12v_rects()[0]
|
||||
WIDTH = MAIN[2] - MAIN[0]
|
||||
|
||||
|
||||
def check(corridors, step=0.05):
|
||||
worst = (1e9, None)
|
||||
y = MAIN[1]
|
||||
while y <= MAIN[3]:
|
||||
iv = []
|
||||
for _n, r in corridors:
|
||||
if r[1] - 1e-9 <= y <= r[3] + 1e-9:
|
||||
iv.append((max(r[0], MAIN[0]), min(r[2], MAIN[2])))
|
||||
iv.sort()
|
||||
used, spans = 0.0, []
|
||||
for a, b in iv:
|
||||
if b <= a:
|
||||
continue
|
||||
if spans and a <= spans[-1][1]:
|
||||
spans[-1] = (spans[-1][0], max(spans[-1][1], b))
|
||||
else:
|
||||
spans.append((a, b))
|
||||
for a, b in spans:
|
||||
used += b - a
|
||||
left = WIDTH - used
|
||||
if left < worst[0]:
|
||||
worst = (left, y)
|
||||
y += step
|
||||
return worst
|
||||
|
||||
|
||||
def main():
|
||||
cor = [(n, r) for n, r in B.PD_L1 if n.startswith('FAN')]
|
||||
if '--cfg' in sys.argv:
|
||||
cfg = json.load(io.open(os.path.join(HERE, '_base_window.json'), encoding='utf-8'))
|
||||
cor = [(n, tuple(r)) for n, r in (cfg.get('pd_l1_extra') or [])]
|
||||
print(u'主块 x %.2f~%.2f(宽 %.2f);走廊 %d 条' % (MAIN[0], MAIN[2], WIDTH, len(cor)))
|
||||
for n, r in cor:
|
||||
kind = u'横带' if (r[2] - r[0]) >= (r[3] - r[1]) else u'竖带'
|
||||
print(u' %-14s (%6.2f, %6.2f, %6.2f, %6.2f) %5.2f×%5.2f %s'
|
||||
% (n, r[0], r[1], r[2], r[3], r[2] - r[0], r[3] - r[1], kind))
|
||||
left, y = check(cor)
|
||||
ok = left >= MIN_SECTION
|
||||
print(u'%s 逐 y 最窄断面 %.2f mm(y=%.2f),判据 ≥ %.1f' %
|
||||
(u'[OK]' if ok else u'[X]', left, y, MIN_SECTION))
|
||||
return 0 if ok else 1
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
在新工单中引用
屏蔽一个用户