文件
zhou yang和Claude Opus 5 2bfe308b30 初始导入: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
2026-09-06 18:18:14 +08:00

78 行
2.5 KiB
Python

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
# -*- coding: utf-8 -*-
u"""在载板中央走廊里找两个中跨 M3 孔的位置(2026-09-05 用户拍板要加)。
判据:孔中心到**任何**已有焊盘 / 电解罐体的净间距 >= CLR。
孔按 NPTH Ø3.2 **无焊盘**算 —— 有焊盘的话 Ø6 塞不进走廊(见输出)。
罐体半径来自 pcb2_place.py 的 C801_BODY_R(Ø12.5 含余量)。
"""
import json
import math
import os
import sys
sys.stdout.reconfigure(encoding='utf-8')
HERE = os.path.dirname(os.path.abspath(__file__))
MIL = 39.3700787401575
pads = json.load(open(os.path.join(HERE, '_pcb2_pads.json'), encoding='utf-8'))
def box(shape, rot, x, y):
kind = shape[0]
if kind == 'POLYGON':
pts = [v for v in shape[1] if isinstance(v, (int, float))]
xs, ys = pts[0::2], pts[1::2]
return ((min(xs) + max(xs)) / 2 / MIL, (min(ys) + max(ys)) / 2 / MIL,
(max(xs) - min(xs)) / 2 / MIL, (max(ys) - min(ys)) / 2 / MIL)
w, h = float(shape[1]) / MIL, float(shape[2]) / MIL
d = rot * 180.0 / math.pi if abs(rot) <= 2 * math.pi + 1e-6 else rot
if round(d) % 180 == 90:
w, h = h, w
return x / MIL, y / MIL, w / 2.0, h / 2.0
P = [box(s, r, x, y) for lay, x, y, r, s, net, num in pads]
# 五个 Ø10 电解罐(顶层,按 Ø12.5 留),中心从 pcb2_place.py 的 BAND['c1'] 折算
CANS = [(17.0, 74.5), (88.5, 74.5), (160.0, 74.5), (95.84, 60.66), (167.34, 60.66)]
CAN_R = 6.25
HOLE_R = 1.6 # NPTH Ø3.2
CLR = 0.5 # 到任何铜/罐体的净间距
def clearance(cx, cy):
best = 1e9
for px, py, hw, hh in P:
d = max(abs(cx - px) - hw, abs(cy - py) - hh) - HOLE_R
best = min(best, d)
for qx, qy in CANS:
best = min(best, math.hypot(cx - qx, cy - qy) - CAN_R - HOLE_R)
return best
# 走廊:两排手机本体之间(CH4/CH5 顶 49.66,CH1~3 底 85.5)
best = []
x = 20.0
while x <= 200.0:
y = 51.0
while y <= 84.0:
c = clearance(x, y)
if c >= CLR:
best.append((round(c, 2), round(x, 1), round(y, 1)))
y += 0.25
x += 0.25
print(u'走廊里净间距 >= %.1f mm 的候选点 %d 个' % (CLR, len(best)))
# 按 x 分簇,报出每一簇里最宽敞的一个
best.sort(key=lambda t: -t[0])
picked = []
for c, x, y in best:
if all(math.hypot(x - a[1], y - a[2]) > 12 for a in picked):
picked.append((c, x, y))
if len(picked) >= 12:
break
print(u'%-8s %-8s %-8s' % (u'净间距', 'x', 'y'))
for c, x, y in sorted(picked, key=lambda t: t[1]):
print(u'%8.2f %8.2f %8.2f' % (c, x, y))