日期:2026-06-16
涉及文件:Calib/CalibrationEngine.cs(主要)、Serial/HouseMotor.cs(参考,不改)
AutoFocusTool 自动标定单 well 时,偶发"找不到圆孔"。经排查确认现象为: 水平扫描的 7 个位置从头到尾都检不出圆,且标定窗口实时画面里始终看不到完整圆孔—— 即 well 没有充分转进相机画面。
根因:当前水平找圆以 well 的 EEPROM 位置为中心做 ±4000 脉冲、7 步扫描
(CalibrationEngine.cs:30-31)。当某 well 的 EEPROM 水平位置偏差大于该窗口时,
well 圆始终落在画面外,整段扫描都检不出。
同理 Z 对焦:粗对焦以 EEPROM Z 零点为中心 ±1500(ZHalf=1500)扫描,
若真实焦面离零点超过 1500 脉冲也会扫不到峰。
| 项 | 决策值 |
|---|---|
| 水平方案 | 全行程粗扫定位 + 局部密扫 |
| 水平行程上限 | 可配置,默认 70000(来源:旧工程自检 HouseBin.cs:468) |
| 水平粗扫步距 | 默认 2000,命中完整圆即停,不必扫完全程 |
| Z 粗对焦中心 | 固定 90000(所有 well 统一;用户实测焦面均落在 60000~120000) |
| Z 粗对焦区间 | 60000~120000(中心 90000,±30000) |
| Z 粗对焦步距 | 2000 → 约 31 层 |
| Z 精对焦半幅 | 6000(围绕粗峰 ±6000) |
| Z 精对焦步距 | 500 → 约 24 层(B 方案:精度优先) |
| 限位 | 水平 [0,HMax]、垂直 [0,ZMax],所有移动前钳位 |
CalibrationEngine 字段)// ── 行程限位(所有电机移动前钳到该区间)──
public int HMin = 0, HMax = 70000; // 水平行程上下限
public int ZMin = 0, ZMaxPulse = 125000; // 垂直行程上下限(旧工程软上限)
// ── 水平全行程粗扫定位 ──
public int HCoarseStart = 0; // 粗扫起点
public int HCoarseEnd = 70000; // 粗扫终点(= HMax)
public int HCoarseStep = 2000; // 粗扫步距(够小不跨过 well)
// 命中完整圆即停:扫到 Found && Complete 立即转入局部密扫
// ── Z 全范围粗对焦(固定中心窗口)──
public int ZCoarseCenter = 90000; // 粗对焦中心(固定,所有 well 统一)
public int ZCoarseHalf = 30000; // 粗对焦半幅 → 区间 60000~120000
public int ZCoarseStep = 2000; // 粗对焦步距 → 约 31 层
// ── Z 精对焦(围绕粗峰)──
// 复用现有精对焦逻辑,半幅与步距改为:
public int FineZHalf = 6000; // 精对焦半幅(原 fineZHalf=500)
public int FineZStep = 500; // 精对焦步距 → 约 24 层
保留现有 HScanRange/HScanSteps/FineScanSteps 用于水平局部密扫阶段
(命中后在最佳点附近精调 Y 居中),无需删除。
新增两个私有方法,所有 _motor.HorizontalMoveTo / _motor.VerticalMoveTo
调用前先过钳位,避免越界指令发给下位机:
int ClampH(int p) => Math.Max(HMin, Math.Min(HMax, p));
int ClampZ(int p) => Math.Max(ZMin, Math.Min(ZMaxPulse, p));
钳位发生时写一条 Log(便于发现 EEPROM 异常值或参数配置过界)。
新增方法 HCoarseLocate,替换 CalibrateWell 中"②旋转居中"
对 ScanForCenter(eepromHPos, HScanRange, ...) 的首次调用:
HCoarseStart 到 HCoarseEnd,步距 HCoarseStep,
每个位置 Grab + WellDetector.Detect。Found && Complete,记录该粗扫位置 hpHit,立即停止粗扫。hpHit 为中心,调用现有 ScanForCenter(well, hpHit, fineRange, FineScanSteps)
做 Y 居中精调(fineRange 取 HCoarseStep 量级,约 ±2000)。Found && Complete,
退化为"取扫描中 |Y偏移| 最小且 Found 的位置";仍无则记 Note="水平全程未检出圆",
该 well 标定失败(沿用现有失败返回风格)。粗扫阶段沿用 CenterScanExposure 固定中低曝光(well 是暗背景中灰盘)。
修改 CoarseFocus:扫描中心由"传入的 EEPROM 零点"改为固定 ZCoarseCenter=90000,
半幅 ZCoarseHalf=30000,步距 ZCoarseStep=2000:
for z in [ZCoarseCenter-ZCoarseHalf .. ZCoarseCenter+ZCoarseHalf] step ZCoarseStep:
move ClampZ(z); discard frame; grab; score = Sharpness(中央40% ROI)
取最高分 z 作为 coarseZ
约 31 层。CalibrateWell 中调用处随之调整(不再传 eepromZ 作中心)。
现有精对焦围绕 coarseZ ± fineZHalf 密扫。将半幅改用 FineZHalf=6000、
步距 FineZStep=500(约 24 层)。半幅 6000 足以覆盖粗扫 ±2000 的峰值定位误差并留余量。
保留现有 3 点平滑 + 抛物线插值峰顶逻辑不变。
读 EEPROM(水平位置仅作参考/不再作扫描中心) → 开灯
① Z 粗对焦:固定 90000±30000 步距2000 (31层) → coarseZ
② 水平全行程粗扫 0~70000 步距2000 命中完整圆即停 → hpHit
→ 局部密扫 ScanForCenter(hpHit, ±~2000) → 最居中水平位置
③ 曝光二分(well 内 ROI,逻辑不变)
④ Z 精对焦:coarseZ±6000 步距500 (24层) + 平滑插值 → focusZ
存图 + 写 calibration.json
注:相比原流程,①②顺序保持"先对焦后居中" (对焦与居中耦合,焦准画面才检得出圆),但①改为固定大窗口、②改为全行程粗扫。
ScanDelayMs350ms+抓帧) ≈ 单 well 15~20 秒。ClampH/ClampZ 钳位,越界写 Log 但不崩溃。Grab() 重试 3 次机制。PeakRatio<1.2)沿用现有"弱峰/可能空well"告警。SelfTest/SmokeTest 子工程验证编译与基本调用不被破坏。ClampH/ClampZ 边界)。Protocol.cs、不改 HouseMotor 的移动接口(限位放在 CalibrationEngine)。GetSourceBuffer 段错误)——另行处理。