R2 底板改 4 层(D15):规则 / 几何 / 背面摆位 / 4 层布线与铺铜,已下发

- 规则:铜层 2→4,差分 0.28/0.18,间距 0.15,过孔 0.3/0.2(rules_base)
- 几何:98×98 板框 + 4×M3,槽阵居中,L1 12V 大铜 + 指头(pcb_base)
- 摆位:五插槽留 L1,其余 133 件翻到 L4;背面镜像规则实测;Hub 放走廊 2、
  东移 2.5 mm;扇出圈 / 小件间距 1.5(去耦例外)/ 9 A 过孔阵禁区(place_base)
- 叠层按用户决定改为 L1 槽面 / L2 整层 +3V3 / L3 整层 GND / L4 器件面
- 布线:D± 七对按构造布通(USB3 掉头、USB1/2 北去掉头、USB4/5 东绕、
  J23 桥),+3V3 / GND / +12V 平面网每脚一孔,0.125 网格 + PathFinder
  开关(route_base、remote_route.ps1);剩 37 个网待手工补
- 铺铜:4 层重写,入口链自南向北切段 + 断面校核(pour_base);
  已下发布线 / 缝合孔 / 铜面轮廓,填铜未成功(待查)
- 工具:plot_base / plot_routes / shot_base,board_check 通孔两层都算

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_0168Bu6SEx3cXXCJLkdnE6zB
这个提交包含在:
zhou yang
2026-09-10 21:02:10 +08:00
共同撰写人 Claude Opus 5
父节点 18d3d69856
当前提交 efcba30a0c
共修改 280 个文件,包含 92007 行新增和 15053 行删除
+63 -19
查看文件
@@ -3,7 +3,8 @@ u"""载板 C4-SITE1 ~ C4-SITE5:每台手机一页。
一页里三块:
【A】电池排线 4 焊盘直焊座 J8n(P+/P−/TEMP/ID,2026-09-06 取代 TP8n1/2)+ TEMP 10k / ID 68k + §6.3 电容组(六颗)
【B】四根侧键顶针(PWR / VUP / VDN + J604 三键公共地)
【B】四根侧键顶针(PWR / VUP / VDN + J604 三键公共地)+ 三颗按键 MOS(2N7002 + 1k 栅阻 + 100k 下拉)
—— 2026-09-06 随 74HC595 从下板 P2 搬来(§26.23),位号沿用 Q%d03~05 / R%d20~25
【C】EDL:1.25mm 2P 座 + TS5A3157 模拟开关 + 100k 下拉 + 去耦
用法: /c/Python314/python .claude/c4_site.py [--push] [--only N]
@@ -50,6 +51,8 @@ P = {
'CONN2P': '6461e6e5749d421bb997627984866425', # C225104 A1251WV-S-2P
'SW': '5acafd8eb5a641fcaf05190902930635', # C353034 TS5A3157DBVR
'R100K': 'acc294b6661948399f609b41c77ed19f', # C25741 100k 0402
'NMOS': 'f8007837564a4f1fa0e6b57b81dccb0d', # C8545 2N7002(按键 MOS,从下板搬来)
'R1K': '65abbad5fa864933b552e0f016ece0db', # C11702 1k 0402(栅极串阻)
}
# ---- 版面常量 ----
@@ -63,9 +66,14 @@ J8 = (225, 630) # 排线直焊座:符号 4 脚朝**左**(实
COL = {'1': 100, '2': 130, '3': 170, '4': 190}
R78, R79 = (170, 575), (190, 575) # TEMP / ID 电阻(竖放),下端直接落在 GND 母线上
POGO_X = [220, 320, 420, 520] # 【B】四根顶针的元件中心
Y_POGO = 380
POGO_PORT_Y = [330, 300, 270, 240]
# 【B】三个按键列(PWR / VUP / VDN),每列:顶针在上、按键 MOS 在下、K 端口从最底下进来。
# 列内相对顶针中心 x_p:MOS (x_p-25, 360) → G(x_p-45,360) S(x_p-15,340) D(x_p-15,380);
# 栅阻 R%20/22/24 (x_p-45, 330) 竖放;下拉 R%21/23/25 (x_p-75, 330) 竖放;
# K 端口 (x_p-45, 250);POGO 端口挂在漏极竖线旁的横支线末端 (x_p+5, 410)(给 PCB 网络起名)。
# 列距 120:一列占 x_p-85 ~ x_p+85(POGO 标签),最东一列的标签 515 < 【C】那根 x=530 的竖线。
KEY_X = [190, 310, 430]
GND_POGO_X = 80 # 第四根顶针(J604 公共地)
Y_POGO = 440
J6, U4 = (660, 400), (880, 400) # 【C】
R74, C76 = (975, 370), (1060, 370)
@@ -88,6 +96,9 @@ def names(n):
'j8': 'J8%d' % n, 'r78': 'R78%d' % n, 'r79': 'R79%d' % n,
'pogo': ['J%d' % (41 + (n - 1) * 4 + i) for i in range(4)],
'j6': 'J6%d' % n, 'u4': 'U4%d' % n, 'r74': 'R74%d' % n, 'c76': 'C76%d' % n,
'q': ['Q%d0%d' % (n, k) for k in (3, 4, 5)], # PWR / VUP / VDN
'rg': ['R%d2%d' % (n, k) for k in (0, 2, 4)], # 1k 栅阻
'rp': ['R%d2%d' % (n, k) for k in (1, 3, 5)], # 100k 下拉
}
@@ -102,8 +113,12 @@ def placement(n):
# 和 skill §6 那张表相反 —— 所以传 90。下面 EXPECT 会再断言一次。
rot = 90 if key == 'C2200U' else 270
out.append([d['caps'][i], P[key], CAP_X[i], Y_CAP, rot, LIB_POGO if key == 'C2200U' else LIB])
for i, x in enumerate(POGO_X):
for i, x in enumerate(KEY_X):
out.append([d['pogo'][i], P['POGO'], x, Y_POGO, 0, LIB_POGO])
out.append([d['q'][i], P['NMOS'], x - 25, 360, 0, LIB])
out.append([d['rg'][i], P['R1K'], x - 45, 330, 90, LIB])
out.append([d['rp'][i], P['R100K'], x - 75, 330, 90, LIB])
out.append([d['pogo'][3], P['POGO'], GND_POGO_X, Y_POGO, 0, LIB_POGO])
out += [[d['j6'], P['CONN2P'], J6[0], J6[1], 0, LIB],
[d['u4'], P['SW'], U4[0], U4[1], 0, LIB],
[d['r74'], P['R100K'], R74[0], R74[1], 270, LIB],
@@ -153,16 +168,41 @@ def wiring(n, pins):
w(top[0], top[1], top[0], Y_VO)
w(bot[0], bot[1], bot[0], Y_GND)
# ---------- 【B】侧键顶针 ----------
labels = ['POGO%d_PWR' % n, 'POGO%d_VUP' % n, 'POGO%d_VDN' % n, None]
for i in range(4):
# ---------- 【B】侧键顶针 + 按键 MOS ----------
for i, key in enumerate(('PWR', 'VUP', 'VDN')):
px, py = pins[d['pogo'][i]]['1']
yy = POGO_PORT_Y[i]
w(px, py, px, yy)
if labels[i]:
PT.append(['BI', labels[i], px, yy, 180])
else:
F.append(['Ground', 'GND', px, yy, 0])
q = pins[d['q'][i]]
g, sr, dr = q['1'], q['2'], q['3'] # 2N7002:1=G 2=S 3=D(下面 build_page 里断言过)
assert px == dr[0] == sr[0] and dr[1] < py, (d['q'][i], q, px, py)
# 漏极 -> 顶针一根直线;POGO 端口挂在旁边一根 20 长的横支线末端(给 PCB 网络起名)。
# ⚠️ 不能把端口放在直线的中点:两段共线导线会被 EasyEDA 合并成一段,端口就落在中段 =
# 真断线(skill §8a-2,2026-09-06 第一版就是这么被 port_audit 抓到 15 处的)。
mid = dr[1] + 30
w(dr[0], dr[1], px, py)
w(dr[0], mid, dr[0] + 20, mid)
PT.append(['BI', 'POGO%d_%s' % (n, key), dr[0] + 20, mid, 0])
# 源极 -> 地
w(sr[0], sr[1], sr[0], 300)
F.append(['Ground', 'GND', sr[0], 300, 0])
# 栅极 <- 1k <- K 端口(从底下进来)
rg = pins[d['rg'][i]]
gt = max(rg.values(), key=lambda v: v[1])
gb = min(rg.values(), key=lambda v: v[1])
assert gt[0] == g[0] and gt[1] < g[1], (d['rg'][i], rg, g)
w(g[0], g[1], gt[0], gt[1])
w(gb[0], gb[1], gb[0], 250)
PT.append(['IN', 'K%d_%s' % (n, key), gb[0], 250, 180])
# 栅极 100k 下拉(复位期间 / 排针没插时不误按)
rp = pins[d['rp'][i]]
pt = max(rp.values(), key=lambda v: v[1])
pb = min(rp.values(), key=lambda v: v[1])
assert pt[0] < g[0] and pt[1] < g[1], (d['rp'][i], rp, g)
w(g[0], g[1], pt[0], g[1], pt[0], pt[1])
w(pb[0], pb[1], pb[0], 300)
F.append(['Ground', 'GND', pb[0], 300, 0])
px, py = pins[d['pogo'][3]]['1'] # J604 三键公共地
w(px, py, px, 400)
F.append(['Ground', 'GND', px, 400, 0])
# ---------- 【C】EDL ----------
j, u = pins[d['j6']], pins[d['u4']]
@@ -205,11 +245,11 @@ def wiring(n, pins):
% names(n)['j8'], 10),
(45, 772, u' %s 10k 代替保护板上的 NTC(模拟 25 °C),%s 68k 照抄保护板上的 ID 电阻,都对 P−。'
% (names(n)['r78'], names(n)['r79']), 10),
(45, 470, u'【B】四根顶针顶主板反面的 J601~J604(§13.3)。J604 是三键公共地,', 10),
(45, 454, u' 直接接本路的电源返回地。驱动 MOS 在下板,这里只有顶针。', 10),
(45, 438, u'顶针 = YTC1P-2510-01(立创 C5221288):自由高 3.5 / 行程 0.8 / 压到底 2.7 mm。', 10),
(45, 422, u' 配 3.0mm 立柱 → 压缩 0.5mm(62% 行程,约 62g),屏蔽罩净空 1.6mm。', 10),
(45, 406, u' 冠径只有 Ø0.9 球头,±1mm 落点公差靠首件实测校正(§22.3c / §22.3e)。', 10),
(45, 522, u'【B】四根顶针顶主板反面的 J601~J604(§13.3),J604 是三键公共地,直接接本路的电源返回地。按键 = MOS 把触点对地短接(主板上已串 1k)。', 10),
(45, 508, u' %s 2N7002 由 C6-KEYS 的 74HC595 驱动(K%d_PWR/VUP/VDN),栅极 1k 串阻 + 100k 下拉:复位期间 / 排针没插时不会误按(2026-09-06 从下板搬来,§26.23)。'
% ('/'.join(names(n)['q']), n), 10),
(45, 494, u' 顶针 YTC1P-2510-01(C5221288):自由高 3.5 / 行程 0.8 / 压到底 2.7 mm;配 3.0mm 立柱压缩 0.5mm(62% 行程,约 62g),屏蔽罩净空 1.6mm。', 10),
(45, 480, u' 冠径只有 Ø0.9 球头,±1mm 落点公差靠首件实测校正(§22.3c / §22.3e)。', 10),
(45, 205, u'【C】%s 是 1.25mm 2P 座,两根线焊到主板正面的 TP1204 / TP1205(§22.4)。'
% names(n)['j6'], 10),
(45, 189, u' %s 导通即短接两点 → 手机进 9008。串了 1.8k,短路电流只有 1mA。'
@@ -332,6 +372,10 @@ return k;
for k, v in want.items():
if got.get(k, '').upper().replace('VCC', 'V+') != v:
bad.append(u'%s.%s 引脚名期望 %s 实测 %s' % (d['u4'], k, v, got.get(k)))
for qd in d['q']:
q = pins[qd]
if not (sorted(q) == ['1', '2', '3'] and q['1'][0] < q['2'][0] == q['3'][0] and q['2'][1] < q['1'][1] < q['3'][1]):
bad.append(u'%s 2N7002 引脚应是 1=G(左) 2=S(右下) 3=D(右上),实测 %s' % (qd, q))
if bad:
raise SystemExit(pname + u' 引脚核对失败:\n ' + '\n '.join(bad))