ソースを参照

feat(d2-02-t3): path B读per-well范围注入CalibrationEngine(公用ReadWellFocusRange,中心=DB清晰位/水平位,半幅曝光per-well)

huangjie 2 日 前
コミット
a4a35737df
1 ファイル変更53 行追加9 行削除
  1. 53 9
      ivf_tl_operate_2.0/control/ivf_tl_Com/HouseBin.cs

+ 53 - 9
ivf_tl_operate_2.0/control/ivf_tl_Com/HouseBin.cs

@@ -1571,20 +1571,29 @@ namespace ivf_tl_Com
                         return false;
                     }
 
-                    var engine = new CalibrationEngine(lease.Serial, lease.Camera)
-                    {
-                        Log = msg => HouseLogEvent?.Invoke(House.houseSn, DateTime.Now, $"[{House.houseSn}][{this.PortName}][本地对焦]{msg}", LogEnum.HouseInfo)
-                    };
-
                     foreach (var well in wellList.Keys)
                     {
                         if (IsStopClearest || FirstClearest) break;
                         try
                         {
-                            // EEPROM 仅作扫描中心(参考),不进配置解析链、不回写(§2.5)。
-                            int hpos = lease.Serial.ReadWellHorizontalPosWait(well);
-                            int zZero = lease.Serial.ReadWellFocusZeroWait(well);
-                            var wc = engine.CalibrateWell(well, Math.Max(0, hpos), Math.Max(0, zZero));
+                            // 自动对焦重构 Task2.2:读 per-well 运动范围(半幅)+中心(DB),逐 well 注入引擎。
+                            //   中心 = DB 该 well 的水平电机位/E方清晰位(取代原硬件 EEPROM 回读 + 引擎固定 90000);
+                            //   半幅/曝光 = well 级覆盖→设备级默认→引擎默认(由 FocusRangeResolver 就近解析)。
+                            var range = ReadWellFocusRange(well);
+                            var engine = new CalibrationEngine(lease.Serial, lease.Camera)
+                            {
+                                Log = msg => HouseLogEvent?.Invoke(House.houseSn, DateTime.Now, $"[{House.houseSn}][{this.PortName}][本地对焦]{msg}", LogEnum.HouseInfo),
+                                HFineRange = range.HHalf,        // 水平微调半幅(围绕 HCenter)
+                                ZCoarseCenter = range.VCenter,   // Z 粗扫中心=该 well 清晰位(DB eeprom_clear_position),取代引擎固定 90000
+                                ZCoarseHalf = range.VHalf,       // Z 粗扫半幅
+                                ExpLo = range.ExpLo,             // 曝光二分下限
+                                ExpHi = range.ExpHi,             // 曝光二分上限
+                            };
+                            // CalibrateWell 的两参语义(已核 CalibrationEngine):
+                            //   eepromHPos → 水平居中扫描中心(初始移位 + ScanForCenter 中心);传 DB 水平位 range.HCenter。
+                            //   eepromZ    → 引擎当前未使用(Z 粗扫中心取字段 ZCoarseCenter,已上面设为 range.VCenter);
+                            //                仍传 DB 清晰位 range.VCenter 占位,避免硬件回读且语义一致。
+                            var wc = engine.CalibrateWell(well, Math.Max(0, range.HCenter), Math.Max(0, range.VCenter));
                             if (wc == null)
                             {
                                 HouseLogEvent?.Invoke(House.houseSn, DateTime.Now, $"[{House.houseSn}][{this.PortName}][{well}号well本地对焦无结果,跳过该well]", LogEnum.HouseInfo);
@@ -1632,6 +1641,41 @@ namespace ivf_tl_Com
             return false;
         }
 
+        /// <summary>
+        /// 自动对焦重构 Task2.2:读取某 well 的对焦运动范围(半幅)+中心(全部取自 DB,不回读硬件 EEPROM)。
+        /// 就近优先解析(由 FocusRangeResolver 完成):well 级半幅 &gt; 设备级默认 &gt; 引擎硬编码默认。
+        ///   · 半幅:well 级 horizontalFocusRange/verticalFocusRange(可空) → 设备级 focusHRangeDefault/focusVRangeDefault(可空) → 引擎默认。
+        ///   · 中心:well 级 horizontalMotorPosition(水平居中中心) / eepromClearPosition(Z 粗扫中心)。
+        ///   · 曝光:设备级 focusExposureMin/focusExposureMax(可空则兜底 10/800,与引擎现值一致)。
+        /// 找不到 well 配置时:中心回退为 0(记日志),半幅走设备级/引擎默认,绝不崩。
+        /// ⚠ Phase 3 标定协作(调试页一键基准等)也复用本方法取范围——改这里要同时顾及采集对焦与标定两处,勿改一处忘另一处。
+        /// </summary>
+        private FocusRangeConfig ReadWellFocusRange(int wellSn)
+        {
+            var ws = _wellSettings != null ? _wellSettings.FirstOrDefault(x => x.wellSn == wellSn) : null;
+            if (ws == null)
+            {
+                HouseLogEvent?.Invoke(House.houseSn, DateTime.Now, $"[{House.houseSn}][{this.PortName}][本地对焦:{wellSn}号well未找到well配置,中心回退0、半幅用设备/引擎默认]", LogEnum.HouseInfo);
+            }
+
+            var raw = new FocusRangeRawConfig
+            {
+                // well 级半幅(可空 → Resolver 回退设备级/引擎默认)
+                WellHRange = ws?.horizontalFocusRange,
+                WellVRange = ws?.verticalFocusRange,
+                // 设备级半幅默认(可空)
+                DeviceHRange = TLSetting?.focusHRangeDefault,
+                DeviceVRange = TLSetting?.focusVRangeDefault,
+                // 对焦曝光二分上下限:设备级可空则兜底 10/800(与 CalibrationEngine 现值一致)
+                ExposureMin = TLSetting?.focusExposureMin ?? 10,
+                ExposureMax = TLSetting?.focusExposureMax ?? 800,
+                // 中心(全部取 DB;缺 well 配置则 0):水平居中中心 / Z 粗扫中心
+                HorizontalCenter = ws?.horizontalMotorPosition ?? 0,
+                VerticalCenter = ws?.eepromClearPosition ?? 0,
+            };
+            return FocusRangeResolver.Resolve(raw);
+        }
+
         /// <summary>
         /// 是否拍照
         /// </summary>