diff --git a/app.db b/app.db index 28b8d32..d3971fa 100644 Binary files a/app.db and b/app.db differ diff --git a/src/main/java/a8k/AppControlerExceptionProcesser.java b/src/main/java/a8k/AppControlerExceptionProcesser.java index be723db..ed9d4a1 100644 --- a/src/main/java/a8k/AppControlerExceptionProcesser.java +++ b/src/main/java/a8k/AppControlerExceptionProcesser.java @@ -14,7 +14,7 @@ public class AppControlerExceptionProcesser { @ResponseBody @ExceptionHandler(value = Exception.class) - public AppRet controllerExceptionHandler(Exception e) { + public AppRet controllerExceptionHandler(Exception e) { logger.info("捕获到异常 : ", e); return AppRet.fail(e); } diff --git a/src/main/java/a8k/constant/OptConstant.java b/src/main/java/a8k/constant/OptConstant.java new file mode 100644 index 0000000..b66e283 --- /dev/null +++ b/src/main/java/a8k/constant/OptConstant.java @@ -0,0 +1,6 @@ +package a8k.constant; + +public class OptConstant { + static public final Integer FOPT_LASTER_GAIN = 100; + static public final Integer TOPT_LASTER_GAIN = 100; +} diff --git a/src/main/java/a8k/extapi_controler/ExtApiControler.java b/src/main/java/a8k/extapi_controler/ExtApiControler.java index 6c86bad..117ffd2 100644 --- a/src/main/java/a8k/extapi_controler/ExtApiControler.java +++ b/src/main/java/a8k/extapi_controler/ExtApiControler.java @@ -23,7 +23,7 @@ import java.util.Map; public class ExtApiControler { @PostMapping("/api/service-config/service-list") @ResponseBody - public AppRet services() { + public AppRet services() { List> services = new ArrayList<>(); var classes = SpringBootBeanUtil.getBeans(); for (var clazz : classes) { @@ -43,7 +43,7 @@ public class ExtApiControler { @PostMapping("/api/service-config/service-params-list") @ResponseBody - public AppRet serviceParams(@RequestBody Map params) + public AppRet serviceParams(@RequestBody Map params) throws InvocationTargetException, IllegalAccessException { String serviceKey = (String) params.get("serviceKey"); var paramService = this.getServiceParamHandlerByServiceKey(serviceKey); @@ -77,7 +77,7 @@ public class ExtApiControler { @PostMapping("/api/service-config/service-params-update") @ResponseBody - public AppRet serviceParamsUpdate(@RequestBody Map params) throws Exception { + public AppRet serviceParamsUpdate(@RequestBody Map params) throws Exception { String serviceKey = (String) params.get("serviceKey"); Map newParams = (Map) params.get("params"); @@ -119,7 +119,7 @@ public class ExtApiControler { @PostMapping("/api/service-config/service-params-reset") @ResponseBody - public AppRet serviceParamsReset(@RequestBody Map params) throws Exception { + public AppRet serviceParamsReset(@RequestBody Map params) throws Exception { // String serviceKey = (String) params.get("serviceKey"); // HardwareServiceSetting.deleteAllByServiceName(serviceKey); return AppRet.success(); @@ -127,7 +127,7 @@ public class ExtApiControler { @PostMapping("/api/service-config/service-status-list") @ResponseBody - public AppRet serviceStatus(@RequestBody Map params) throws InvocationTargetException, IllegalAccessException { + public AppRet serviceStatus(@RequestBody Map params) throws InvocationTargetException, IllegalAccessException { String serviceKey = (String) params.get("serviceKey"); Class serviceClass = null; var classes = SpringBootBeanUtil.getBeans(); @@ -166,7 +166,7 @@ public class ExtApiControler { @PostMapping("/api/service-config/service-action-list") @ResponseBody - public AppRet serviceActionList(@RequestBody Map params) throws Exception { + public AppRet serviceActionList(@RequestBody Map params) throws Exception { String serviceKey = (String) params.get("serviceKey"); Class serviceClass = null; var classes = SpringBootBeanUtil.getBeans(); @@ -244,7 +244,7 @@ public class ExtApiControler { @PostMapping("/api/service-config/service-action-exec") @ResponseBody - public AppRet serviceActionExecute(@RequestBody Map params) throws Throwable { + public AppRet serviceActionExecute(@RequestBody Map params) throws Throwable { String serviceKey = (String) params.get("serviceKey"); var service = this.getServiceInstanceByServiceKey(serviceKey); Assert.isTrue(service != null, "service not found"); @@ -277,7 +277,7 @@ public class ExtApiControler { @PostMapping("/api/service-config/service-action-exec-by-map") @ResponseBody - public AppRet serviceActionExecuteByMap(@RequestBody Map params) throws Throwable { + public AppRet serviceActionExecuteByMap(@RequestBody Map params) throws Throwable { String serviceKey = (String) params.get("serviceKey"); var service = this.getServiceInstanceByServiceKey(serviceKey); Assert.isTrue(service != null, "service not found"); @@ -322,7 +322,7 @@ public class ExtApiControler { @PostMapping("/api/service-config/class-struct-info-get") @ResponseBody - public AppRet classStructInfoGet(@RequestBody Map params) throws Exception { + public AppRet classStructInfoGet(@RequestBody Map params) throws Exception { String className = (String) params.get("class"); Class clazz = Class.forName(className); List> struct = new ArrayList<>(); @@ -331,7 +331,7 @@ public class ExtApiControler { } // execute service action and get response - private AppRet executeServiceActionAndGetResponse(Object service, Method method, List actionParams) throws Throwable { + private AppRet executeServiceActionAndGetResponse(Object service, Method method, List actionParams) throws Throwable { Object actionResult = null; try { var actionParamList = actionParams.toArray(); @@ -353,7 +353,7 @@ public class ExtApiControler { } if (actionResult instanceof AppRet) { - return (AppRet) actionResult; + return (AppRet) actionResult; } return AppRet.success(actionResult); } diff --git a/src/main/java/a8k/extapi_controler/pagecontrol/ExtApiTabConfig.java b/src/main/java/a8k/extapi_controler/pagecontrol/ExtApiTabConfig.java index 878ea3f..04bea71 100644 --- a/src/main/java/a8k/extapi_controler/pagecontrol/ExtApiTabConfig.java +++ b/src/main/java/a8k/extapi_controler/pagecontrol/ExtApiTabConfig.java @@ -27,6 +27,7 @@ public enum ExtApiTabConfig { HbotProbeSubstancePosCalibration("校准.探测物质位置校准", true), PipetteGunLLDParamCalibration("校准.移液枪LLD参数校准", true), PipetteGunLLFParamCalibration("校准.移液枪LLF参数校准", true), + OptModuleParamCalibration("校准.光学模块参数校准", true), VirtualDeviceSimulationTest("测试.虚拟设备测试", true), @@ -35,6 +36,7 @@ public enum ExtApiTabConfig { A8kPipetteCtrlModule("硬件驱动测试.移液枪测试", true), + ActionReactorService("底层调试.单步调试", false),//OK ReactionPlatesTransmitCtrl("ReactionPlatesTransmitCtrl", false), HbotControlService("HbotControlService", false), diff --git a/src/main/java/a8k/hardware/A8kCanBusService.java b/src/main/java/a8k/hardware/A8kCanBusService.java index ab1baa1..706a4f9 100644 --- a/src/main/java/a8k/hardware/A8kCanBusService.java +++ b/src/main/java/a8k/hardware/A8kCanBusService.java @@ -168,37 +168,7 @@ public class A8kCanBusService { } - public void optTStartScan(MId id, OptScanDirection scanDirection, Integer lasterGain, Integer scanGain) throws AppException { - callcmd(id.toInt(), CmdId.a8k_opt_v2_t_start_scan.toInt(), scanDirection.getInteger(), lasterGain, scanGain); - } - - public void optTStartScanBlock(MId id, OptScanDirection scanDirection, Integer lasterGain, Integer scanGain, Integer actionOvertime) throws AppException { - optTStartScan(id, scanDirection, lasterGain, scanGain); - waitForMod(id, actionOvertime); - } - - public void optFStartScan(MId id, OptScanDirection scanDirection, Integer lasterGain, Integer scanGain) throws AppException { - callcmd(id.toInt(), CmdId.a8k_opt_v2_f_start_scan.toInt(), scanDirection.getInteger(), lasterGain, scanGain); - } - public void optFStartScanBlock(MId id, OptScanDirection scanDirection, Integer lasterGain, Integer scanGain, Integer actionOvertime) throws AppException { - optFStartScan(id, scanDirection, lasterGain, scanGain); - waitForMod(id, actionOvertime); - } - - public List optReadRaw(MId id) throws AppException { - int i = 0; - List result = new ArrayList<>(); - while (true) { - var rxPacket = callcmd(id.toInt(), CmdId.a8k_opt_v2_read_raw.toInt(), i++); - if (rxPacket.getCmdContent().length == 0) { - break; - } - var rawdata = ByteArray.readU16bitArray(rxPacket.getCmdContent()); - result.addAll(Arrays.asList(rawdata)); - } - return result; - } public void plateCodeScanerPushCardAndScan(MId id, Integer finalStopPos) throws AppException { diff --git a/src/main/java/a8k/optalgo/OptAlgo.java b/src/main/java/a8k/optalgo/A8kOptAlgo.java similarity index 99% rename from src/main/java/a8k/optalgo/OptAlgo.java rename to src/main/java/a8k/optalgo/A8kOptAlgo.java index 0bcc5f8..f736d5b 100644 --- a/src/main/java/a8k/optalgo/OptAlgo.java +++ b/src/main/java/a8k/optalgo/A8kOptAlgo.java @@ -12,7 +12,7 @@ import java.util.ArrayList; import java.util.List; @Slf4j -public class OptAlgo { +public class A8kOptAlgo { public static OptAlgoResult processOptData(Integer expectPeakNum, Integer searchStart, double[] data) { LineProcessContext cxt = new LineProcessContext(); diff --git a/src/main/java/a8k/optalgo/A8kOptAlgoUtils.java b/src/main/java/a8k/optalgo/A8kOptAlgoUtils.java new file mode 100644 index 0000000..c3bfd41 --- /dev/null +++ b/src/main/java/a8k/optalgo/A8kOptAlgoUtils.java @@ -0,0 +1,36 @@ +package a8k.optalgo; + +import a8k.optalgo.utils.Filter; +import a8k.optalgo.utils.SubSampling; +import a8k.optalgo.utils.SupperSampling; + +public class A8kOptAlgoUtils { + + static public Integer[] supperSamplingAndSubSampling(Integer[] data) { + double[] indata = new double[data.length]; + for (int i = 0; i < data.length; i++) { + indata[i] = data[i]; + } + + var result = supperSamplingAndSubSampling(indata); + Integer[] outdata = new Integer[result.length]; + for (int i = 0; i < result.length; i++) { + outdata[i] = (int) result[i]; + } + return outdata; + } + + static public double[] supperSamplingAndSubSampling(double[] data) { + //过采样 + var afSupperVal = SupperSampling.process(data, 5); + //中值滤波 + var afSupperMedianVal = Filter.medianFiltering(afSupperVal, 25); + + //下采样到1000个点 + var raw1000 = SubSampling.process(afSupperMedianVal, 6); + //生成1000个的平滑曲线 + var avg1000 = Filter.smooth(raw1000, 13); + + return SubSampling.process(avg1000, 4); + } +} diff --git a/src/main/java/a8k/optalgo/OptAlgoUtils.java b/src/main/java/a8k/optalgo/OptAlgoUtils.java deleted file mode 100644 index 665459b..0000000 --- a/src/main/java/a8k/optalgo/OptAlgoUtils.java +++ /dev/null @@ -1,106 +0,0 @@ -package a8k.optalgo; - -import a8k.optalgo.type.LinearResult; -import a8k.optalgo.type.OptAlgoResult; -import org.springframework.util.Assert; - -public class OptAlgoUtils { - - OptAlgoResult processOptData(Integer expectPeakNum, Float[] data) { - return null; - } - - Boolean feq(double a, double b, double epsilon) { - double dv = a - b; - if (dv < 0) - dv = -dv; - return dv <= epsilon; - } - - - - - - - Float[] differentiate(Float[] inputRaw) { - /** - * @brief - * 巴迪泰源码,对原始数据添加了一些微小的值,原因未知 - */ - for (int i = 0; i <= inputRaw.length - 8; i += 8) { - inputRaw[i + 1] = inputRaw[i + 1] + 0.001f; - inputRaw[i + 2] = inputRaw[i + 2] + 0.002f; - inputRaw[i + 3] = inputRaw[i + 3] + 0.003f; - inputRaw[i + 4] = inputRaw[i + 4] + 0.004f; - inputRaw[i + 5] = inputRaw[i + 5] + 0.005f; - inputRaw[i + 6] = inputRaw[i + 6] + 0.004f; - inputRaw[i + 7] = inputRaw[i + 7] + 0.003f; - inputRaw[i + 8] = inputRaw[i + 8] + 0.002f; - } - - /** - * @brief - * @Warning: 此处求导和巴迪泰的存在差异, - * 巴迪泰的是当前数值减去下一个数值, - * 而此处是当前数值减去上一个数值 - */ - - Float[] differentiateRaw = new Float[inputRaw.length]; - for (int i = 1; i < differentiateRaw.length; i++) { - differentiateRaw[i] = inputRaw[i] - inputRaw[i - 1]; - } - differentiateRaw[0] = differentiateRaw[1]; - return differentiateRaw; - } - - Float[] least_square_method_differentiate(Float[] inputRaw, int windows_size) { - Assert.isTrue((windows_size > 0), "windows_size > 0"); - Assert.isTrue((windows_size % 2 == 1), "windows_size % 2 == 1"); - - Float[] differentiateRaw = new Float[inputRaw.length]; - Float[] windowsRaw = new Float[windows_size]; - - int windows_size_half = (windows_size - 1) / 2; - - for (int index = windows_size_half; index < inputRaw.length - windows_size_half; index++) { - // windowsRaw = getwindowspoint(inputRaw, index, windows_size); - float intercept = 0; - // linear_least_squares(windowsRaw, windows_size, differentiateRaw[index], - // intercept); - } - - for (int i = 0; i < windows_size_half; i++) { - differentiateRaw[i] = differentiateRaw[windows_size_half]; - } - - for (int i = inputRaw.length - windows_size_half; i < inputRaw.length; i++) { - differentiateRaw[i] = differentiateRaw[inputRaw.length - windows_size_half - 1]; - } - return differentiateRaw; - } - - float get_avg_in_windows(double[] src, int off, int windows) { - float sum = 0; - Assert.isTrue((windows % 2 == 1),"(windows % 2 == 1)"); - for (int i = off - windows / 2; i <= off + windows / 2; i++) { - sum += (float) src[i]; - } - return sum / windows; - } - - void sort_vector(Float[] src) { - // 实现冒泡排序 - for (int i = 0; i < src.length; i++) { - for (int j = 0; j < src.length - i - 1; j++) { - if (src[j] > src[j + 1]) { - float temp = src[j]; - src[j] = src[j + 1]; - src[j + 1] = temp; - } - } - } - } - - - -} diff --git a/src/main/java/a8k/service/app/appctrl/mainflowctrl/action/PLATE_OPT_SCAN.java b/src/main/java/a8k/service/app/appctrl/mainflowctrl/action/PLATE_OPT_SCAN.java index d1f8a8a..743dd7b 100644 --- a/src/main/java/a8k/service/app/appctrl/mainflowctrl/action/PLATE_OPT_SCAN.java +++ b/src/main/java/a8k/service/app/appctrl/mainflowctrl/action/PLATE_OPT_SCAN.java @@ -82,6 +82,14 @@ public class PLATE_OPT_SCAN extends A8kStepAction { return reactionResults; } + // + // 判断T光学是否需要扫描,T光学扫描方向,扫描范围 + // 判断F光学是否需要扫描,F光学扫描方向,扫描范围 + // 获取扫描起始位置,峰的数量,接收放大倍数,扫描放大倍数,是否自动调整放大倍数 + // 根据峰计算最终结果 + // + + //TODO 扫描反应板 //丢板 optScanModuleCtrlService.dropPlate(); diff --git a/src/main/java/a8k/service/app/devicectrl/ctrlservice/OptScanModuleCtrlService.java b/src/main/java/a8k/service/app/devicectrl/ctrlservice/OptScanModuleCtrlService.java index 67e3ea4..339551d 100644 --- a/src/main/java/a8k/service/app/devicectrl/ctrlservice/OptScanModuleCtrlService.java +++ b/src/main/java/a8k/service/app/devicectrl/ctrlservice/OptScanModuleCtrlService.java @@ -1,12 +1,17 @@ package a8k.service.app.devicectrl.ctrlservice; +import a8k.constant.OptConstant; import a8k.extapi_controler.pagecontrol.ExtApiTabConfig; import a8k.extapi_controler.utils.ExtApiTab; +import a8k.service.app.devicectrl.driver.OptModuleDriver; import a8k.service.app.devicectrl.driver.StepMotorCtrlDriver; +import a8k.service.app.devicectrl.driver.type.OptModuleRegIndex; import a8k.service.app.devicectrl.driver.type.StepMotorMId; import a8k.service.app.devicectrl.param.param_mgr.OptModuleParamsMgr; import a8k.service.bases.ActionReactorService; +import a8k.service.db.type.a8kidcard.zenum.A8kOptType; import a8k.type.IncubatorPos; +import a8k.type.OptScanDirection; import a8k.type.exception.AppException; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; @@ -23,6 +28,8 @@ public class OptScanModuleCtrlService { StepMotorCtrlDriver stepMotorCtrlDriver; @Resource ActionReactorService actionReactor; + @Resource + OptModuleDriver optModuleDriver; @Resource OptModuleParamsMgr optModuleParamsMgr; @@ -43,4 +50,29 @@ public class OptScanModuleCtrlService { stepMotorCtrlDriver.stepMotorEasyMoveToBlock(StepMotorMId.OptModScannerM, optModuleParamsMgr.getOptScanerScandbyPos(), overtime); } + + public Integer[] startOptScan(A8kOptType optType, OptScanDirection direction, Integer lasterGain, Integer scanGain) throws AppException { + Integer forwardScanPos = optModuleParamsMgr.getOptScanStartPos(optType); + switch (optType) { + case TOPT -> { + optModuleDriver.setReg(OptModuleRegIndex.kreg_a8k_opt_t_pos_offset, forwardScanPos); + optModuleDriver.setReg(OptModuleRegIndex.kreg_a8k_opt_t_reverse_scan_pos_offset, forwardScanPos - 1200); + optModuleDriver.setReg(OptModuleRegIndex.kreg_a8k_opt_scan_pointnum, 1200); + } + case FOPT -> { + optModuleDriver.setReg(OptModuleRegIndex.kreg_a8k_opt_f_pos_offset, forwardScanPos); + optModuleDriver.setReg(OptModuleRegIndex.kreg_a8k_opt_f_reverse_scan_pos_offset, forwardScanPos - 1200); + optModuleDriver.setReg(OptModuleRegIndex.kreg_a8k_opt_scan_pointnum, 1200); + } + } + + switch (optType) { + case TOPT -> optModuleDriver.optTStartScan(direction, lasterGain, scanGain); + case FOPT -> optModuleDriver.optFStartScan(direction, lasterGain, scanGain); + } + + return optModuleDriver.optReadRaw(); + } + + } diff --git a/src/main/java/a8k/service/app/devicectrl/driver/OptModuleDriver.java b/src/main/java/a8k/service/app/devicectrl/driver/OptModuleDriver.java new file mode 100644 index 0000000..f81e6b3 --- /dev/null +++ b/src/main/java/a8k/service/app/devicectrl/driver/OptModuleDriver.java @@ -0,0 +1,59 @@ +package a8k.service.app.devicectrl.driver; + +import a8k.hardware.A8kCanBusService; +import a8k.hardware.type.a8kcanprotocol.CmdId; +import a8k.hardware.type.a8kcanprotocol.MId; +import a8k.service.app.devicectrl.driver.type.OptModuleRegIndex; +import a8k.type.OptScanDirection; +import a8k.type.exception.AppException; +import a8k.utils.ByteArray; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +@Component +@Slf4j +public class OptModuleDriver { + + static Integer actionOvertime = 10000; + + @Resource + A8kCanBusService canBus; + + public void optTStartScan(OptScanDirection scanDirection, Integer lasterGain, Integer scanGain) throws AppException { + canBus.callcmd(MId.OptMod, CmdId.a8k_opt_v2_t_start_scan, scanDirection.getInteger(), lasterGain, scanGain); + canBus.waitForMod(MId.OptMod, actionOvertime); + } + + public void optFStartScan(OptScanDirection scanDirection, Integer lasterGain, Integer scanGain) throws AppException { + canBus.callcmd(MId.OptMod, CmdId.a8k_opt_v2_f_start_scan, scanDirection.getInteger(), lasterGain, scanGain); + canBus.waitForMod(MId.OptMod, actionOvertime); + } + + public Integer[] optReadRaw() throws AppException { + int i = 0; + List result = new ArrayList<>(); + while (true) { + var rxPacket = canBus.callcmd(MId.OptMod, CmdId.a8k_opt_v2_read_raw, i++); + if (rxPacket.getCmdContent().length == 0) { + break; + } + var rawdata = ByteArray.readU16bitArray(rxPacket.getCmdContent()); + result.addAll(Arrays.asList(rawdata)); + } + return result.toArray(new Integer[0]); + } + + public Integer readReg(OptModuleRegIndex regIndex) throws AppException { + return canBus.moduleGetReg(MId.OptMod, regIndex.regIndex); + } + + public void setReg(OptModuleRegIndex regIndex, Integer value) throws AppException { + canBus.moduleSetReg(MId.OptMod, regIndex.regIndex, value); + } + +} diff --git a/src/main/java/a8k/service/app/devicectrl/driver/type/OptModuleRegIndex.java b/src/main/java/a8k/service/app/devicectrl/driver/type/OptModuleRegIndex.java new file mode 100644 index 0000000..4f496e0 --- /dev/null +++ b/src/main/java/a8k/service/app/devicectrl/driver/type/OptModuleRegIndex.java @@ -0,0 +1,18 @@ +package a8k.service.app.devicectrl.driver.type; + +import a8k.hardware.type.regindex.RegIndex; + +public enum OptModuleRegIndex { + kreg_a8k_opt_t_pos_offset(RegIndex.kreg_a8k_opt_t_pos_offset), + kreg_a8k_opt_f_pos_offset(RegIndex.kreg_a8k_opt_f_pos_offset), + kreg_a8k_opt_t_reverse_scan_pos_offset(RegIndex.kreg_a8k_opt_t_reverse_scan_pos_offset), + kreg_a8k_opt_f_reverse_scan_pos_offset(RegIndex.kreg_a8k_opt_f_reverse_scan_pos_offset), + kreg_a8k_opt_scan_step_interval(RegIndex.kreg_a8k_opt_scan_step_interval), + kreg_a8k_opt_scan_pointnum(RegIndex.kreg_a8k_opt_scan_pointnum), + ; + + public final RegIndex regIndex; + OptModuleRegIndex(RegIndex regIndex) { + this.regIndex = regIndex; + } +} diff --git a/src/main/java/a8k/service/app/devicectrl/exdriver/TubeTransportExDriver.java b/src/main/java/a8k/service/app/devicectrl/exdriver/TubeTransportExDriver.java index 6e1be44..2d6ba2a 100644 --- a/src/main/java/a8k/service/app/devicectrl/exdriver/TubeTransportExDriver.java +++ b/src/main/java/a8k/service/app/devicectrl/exdriver/TubeTransportExDriver.java @@ -28,8 +28,6 @@ public class TubeTransportExDriver { @Resource MiniServoDriver miniServoDriver; - @Resource - TubeFeedingModuleParamMgr tubeScanPosMgr; @Resource StepMotorCtrlDriver stepMotorCtrlDriver; @@ -71,7 +69,6 @@ public class TubeTransportExDriver { } - @ExtApiFn(name = "扫描夹紧机构夹紧", group = "基础方法", order = 1) public void scanClampModClamp() throws AppException { logger.info("扫描夹紧机构夹紧"); miniServoDriver.miniServoEnable(MiniServoMId.ShakeModTubeScanerClampingSV, 1); @@ -81,7 +78,6 @@ public class TubeTransportExDriver { // canBus.waitForMod(MId.ShakeModTubeScanerClampingSV, overtime); } - @ExtApiFn(name = "扫描夹紧机构复位", group = "基础方法", order = 2) public void scanClampModRelease() throws AppException { logger.info("扫描夹紧机构复位"); miniServoDriver.miniServoEnable(MiniServoMId.ShakeModTubeScanerClampingSV, 1); diff --git a/src/main/java/a8k/service/app/devicectrl/param/calibration/OptModuleParamCalibration.java b/src/main/java/a8k/service/app/devicectrl/param/calibration/OptModuleParamCalibration.java new file mode 100644 index 0000000..a8f892a --- /dev/null +++ b/src/main/java/a8k/service/app/devicectrl/param/calibration/OptModuleParamCalibration.java @@ -0,0 +1,165 @@ +package a8k.service.app.devicectrl.param.calibration; + +import a8k.extapi_controler.pagecontrol.ExtApiTabConfig; +import a8k.extapi_controler.utils.ExtApiFn; +import a8k.extapi_controler.utils.ExtApiTab; +import a8k.optalgo.A8kOptAlgoUtils; +import a8k.service.app.devicectrl.ctrlservice.OptScanModuleCtrlService; +import a8k.service.app.devicectrl.ctrlservice.PlateBoxCtrlService; +import a8k.service.app.devicectrl.driver.OptModuleDriver; +import a8k.service.app.devicectrl.driver.StepMotorCtrlDriver; +import a8k.service.app.devicectrl.driver.type.StepMotorMId; +import a8k.service.app.devicectrl.exdriver.MotorEnableExDriver; +import a8k.service.app.devicectrl.param.param_mgr.OptModuleParamsMgr; +import a8k.service.db.type.Parameter; +import a8k.service.db.type.a8kidcard.zenum.A8kOptType; +import a8k.type.*; +import a8k.type.exception.AppException; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; + + +/** + * + * + * 1.下面三个位置在ReactionPlatesTransmitControlerCalibration进行标定 + * PullerTargetPos("拉板目标位置"), + * OptScanerDropPos("丢板坐标"), + * OptScanerScandbyPos("扫描待机位"), + * + * 2. 该模块只用来标定 + * TOptScanStartPos (T光学扫描起始位置) + * FOptScanStartPos (F光学扫描起始位置) + */ +@ExtApiTab(cfg = ExtApiTabConfig.OptModuleParamCalibration) +@Component +public class OptModuleParamCalibration { + + Integer actionOvertime = 5000; + + @Resource + OptModuleParamsMgr optModuleParamsMgr; + + @Resource + MotorEnableExDriver motorEnableExDriver; + @Resource + StepMotorCtrlDriver stepMotorCtrlDriver; + @Resource + PlateBoxCtrlService plateBoxCtrlService; + @Resource + OptScanModuleCtrlService optScanModuleCtrlService; + @Resource + OptModuleDriver optModuleDriver; + + + @ExtApiFn(name = "获得参数", group = "基础", order = 1) + public List getParams() throws AppException { + return optModuleParamsMgr.getParams(); + } + + @ExtApiFn(name = "归零", group = "测试工具", order = 11) + public void deviceReset() throws AppException { + enableModule(); + //板夹仓初始化 + stepMotorCtrlDriver.stepMotorEasyMoveToZeroBlock(StepMotorMId.PlatesBoxYM, actionOvertime); + stepMotorCtrlDriver.stepMotorEasyMoveToZeroBlock(StepMotorMId.PlatesBoxPusherM, actionOvertime); + //光学模组初始化 + stepMotorCtrlDriver.stepMotorEasyMoveToZeroBlock(StepMotorMId.OptModPullM, actionOvertime); + stepMotorCtrlDriver.stepMotorEasyMoveToZeroBlock(StepMotorMId.OptModScannerM, actionOvertime); + //转盘归零 + stepMotorCtrlDriver.stepMotorEasyMoveToZeroBlock(StepMotorMId.IncubatorRotateCtrlM, actionOvertime); + } + + @ExtApiFn(name = "使能相关模块", group = "测试工具", order = 12) + public void enableModule() throws AppException { + motorEnableExDriver.enableAllMotor(); + } + + @ExtApiFn(name = "失能相关模块", group = "测试工具", order = 13) + public void disableModule() throws AppException { + motorEnableExDriver.forceDisableAllMotor(); + } + + // + // 辅助方法 + // + + /** + * From: 0号仓 + * TrunablePos:0号仓到 + */ + @ExtApiFn(name = "推板到光学模组", group = "测试工具", order = 100) + public void pushOnePlateToOptModule() throws AppException { + //先清空当前通道 + optScanModuleCtrlService.dropPlate(); + optScanModuleCtrlService.pullPlate(IncubatorPos.SPACE01); + optScanModuleCtrlService.dropPlate(); + + //推板到光学模组 + plateBoxCtrlService.pushPlateQuick(ConsumableGroup.GROUP0, IncubatorPos.SPACE01); + optScanModuleCtrlService.pullPlate(IncubatorPos.SPACE01); + } + + @ExtApiFn(name = "拉板到光学模组", group = "测试工具", order = 101) + public void dropPlate() throws AppException { + optScanModuleCtrlService.dropPlate(); + } + + // @ExtApiFn(name = "曲线显示测试", group = "测试工具", order = 102) + // public A8kScanCurve testCurveDisplay() { + // A8kScanCurve result = new A8kScanCurve(); + // result.refCurve = List.of(40, 80, 120, 160, 200); + // result.scanDataCurve = new ArrayList<>(); + // for (int i = 0; i < 250; i++) { + // result.scanDataCurve.add(i * 10); + // } + // return result; + // } + + A8kScanCurve createScanCurve1200Point(Integer[] optScanResult) { + // Integer[] optScanResult250 = A8kOptAlgoUtils.supperSamplingAndSubSampling(optScanResult); + List refCurve = new ArrayList<>(); + for (int i = 1; i < 6; i++) { + refCurve.add((int) (40 * 4.8 * i)); + } + + var result = new A8kScanCurve(); + result.refCurve = refCurve; + result.scanDataCurve = List.of(optScanResult); + return result; + } + + @ExtApiFn(name = "设置光学扫描参考点", group = "设置", order = 200) + public void setCurrentAsScanRefPos() throws AppException { + stepMotorCtrlDriver.stepMotorEnable(StepMotorMId.OptModScannerM, 1); + Integer pos = stepMotorCtrlDriver.stepMotorReadPosByMoveToZeroBlock(StepMotorMId.OptModScannerM, 10000); + optModuleParamsMgr.setOptScanRefPos(pos); + } + + @ExtApiFn(name = "设置F光学扫描偏移", group = "设置", order = 201) + public void setFOptScanShift(Integer shift) { + optModuleParamsMgr.setFOptScanShift(shift); + } + + @ExtApiFn(name = "设置T光学扫描偏移", group = "设置", order = 202) + public void setTOptScanShift(Integer shift) { + optModuleParamsMgr.setTOptScanShift(shift); + } + + + @ExtApiFn(name = "F光学扫描", group = "扫描", order = 102) + public A8kScanCurve FOptScan(Integer lasterGain, Integer scanGain) throws AppException { + var result = optScanModuleCtrlService.startOptScan(A8kOptType.FOPT, OptScanDirection.FORWARD, lasterGain, scanGain); + return createScanCurve1200Point(result); + } + + @ExtApiFn(name = "T光学扫描", group = "扫描", order = 102) + public A8kScanCurve TOptScan(Integer lasterGain, Integer scanGain) throws AppException { + var result = optScanModuleCtrlService.startOptScan(A8kOptType.TOPT, OptScanDirection.FORWARD, lasterGain, scanGain); + return createScanCurve1200Point(optModuleDriver.optReadRaw()); + } + +} diff --git a/src/main/java/a8k/service/app/devicectrl/param/param_mgr/OptModuleParamsMgr.java b/src/main/java/a8k/service/app/devicectrl/param/param_mgr/OptModuleParamsMgr.java index 6f8a128..d456a14 100644 --- a/src/main/java/a8k/service/app/devicectrl/param/param_mgr/OptModuleParamsMgr.java +++ b/src/main/java/a8k/service/app/devicectrl/param/param_mgr/OptModuleParamsMgr.java @@ -2,6 +2,8 @@ package a8k.service.app.devicectrl.param.param_mgr; import a8k.service.app.devicectrl.param.param_mgr.base.ParamMgr; +import a8k.service.db.type.a8kidcard.zenum.A8kOptType; +import a8k.type.OptScanDirection; import jakarta.annotation.PostConstruct; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -11,7 +13,7 @@ import org.springframework.stereotype.Component; * HBOT二维码扫描坐标参数 */ @Component -public class OptModuleParamsMgr extends ParamMgr { +public class OptModuleParamsMgr extends ParamMgr { static final Logger logger = LoggerFactory.getLogger(OptModuleParamsMgr.class); @@ -19,8 +21,9 @@ public class OptModuleParamsMgr extends ParamMgr { PullerTargetPos("拉板目标位置"), OptScanerDropPos("丢板坐标"), OptScanerScandbyPos("扫描待机位"), - TOptScanStartPos("T光学扫描起始坐标"), - FOptScanStartPos("F光学扫描起始坐标"), + OptScanRefPos("光学扫描参考坐标"), + TOptScanShift("T光学扫描偏移"), + FOptScanShift("F光学扫描偏移"), ; public final String chName; @@ -42,8 +45,9 @@ public class OptModuleParamsMgr extends ParamMgr { setParam(POS.PullerTargetPos, 1147); setParam(POS.OptScanerDropPos, -349); setParam(POS.OptScanerScandbyPos, 305); - setParam(POS.TOptScanStartPos, 3723); - setParam(POS.FOptScanStartPos, 2559); + setParam(POS.OptScanerScandbyPos, 4000); + setParam(POS.TOptScanShift, 277); + setParam(POS.FOptScanShift, 1441); } public Integer getPullerTargetPos() { @@ -58,13 +62,6 @@ public class OptModuleParamsMgr extends ParamMgr { return getParam(POS.OptScanerScandbyPos, Integer.class); } - public Integer getTOptScanStartPos() { - return getParam(POS.TOptScanStartPos, Integer.class); - } - - public Integer getFOptScanStartPos() { - return getParam(POS.FOptScanStartPos, Integer.class); - } public void setPullerTargetPos(Integer pos) { setParam(POS.PullerTargetPos, pos); @@ -78,12 +75,32 @@ public class OptModuleParamsMgr extends ParamMgr { setParam(POS.OptScanerScandbyPos, pos); } - public void setTOptScanStartPos(Integer pos) { - setParam(POS.TOptScanStartPos, pos); + + public void setOptScanRefPos(Integer pos) { + setParam(POS.OptScanRefPos, pos); } - public void setFOptScanStartPos(Integer pos) { - setParam(POS.FOptScanStartPos, pos); + public void setTOptScanShift(Integer pos) { + setParam(POS.TOptScanShift, pos); } + + public void setFOptScanShift(Integer pos) { + setParam(POS.FOptScanShift, pos); + } + + + public Integer getOptScanStartPos(A8kOptType type) { + Integer shift = switch (type) { + case TOPT -> getParam(POS.TOptScanShift, Integer.class); + case FOPT -> getParam(POS.FOptScanShift, Integer.class); + }; + + Integer scanStartPos = getParam(POS.OptScanRefPos, Integer.class); + scanStartPos = scanStartPos + shift; + + return scanStartPos; + } + + } diff --git a/src/main/java/a8k/service/db/type/a8kidcard/zenum/A8kOptType.java b/src/main/java/a8k/service/db/type/a8kidcard/zenum/A8kOptType.java index ede830d..5a944dd 100644 --- a/src/main/java/a8k/service/db/type/a8kidcard/zenum/A8kOptType.java +++ b/src/main/java/a8k/service/db/type/a8kidcard/zenum/A8kOptType.java @@ -1,6 +1,6 @@ package a8k.service.db.type.a8kidcard.zenum; public enum A8kOptType { - F, - T, + FOPT, + TOPT, } diff --git a/src/main/java/a8k/service/test/fakeproj/FakeProjInfo.java b/src/main/java/a8k/service/test/fakeproj/FakeProjInfo.java index 8815cdf..4d7130c 100644 --- a/src/main/java/a8k/service/test/fakeproj/FakeProjInfo.java +++ b/src/main/java/a8k/service/test/fakeproj/FakeProjInfo.java @@ -88,7 +88,7 @@ public class FakeProjInfo { /*光学配置*/ projOptConfig.subProjName = String.format("%s_%d", projName, subIndex); projOptConfig.subProjShortName = String.format("%s_%d", projShortName, subIndex); - projOptConfig.subProjOptType = A8kOptType.F; + projOptConfig.subProjOptType = A8kOptType.FOPT; projOptConfig.subProjScanRange = 200; projOptConfig.subProjScanDirection = OptScanDirection.Forward; projOptConfig.subProjPeakNum = 3; diff --git a/src/main/java/a8k/type/A8kScanCurve.java b/src/main/java/a8k/type/A8kScanCurve.java index be140fe..06a2df8 100644 --- a/src/main/java/a8k/type/A8kScanCurve.java +++ b/src/main/java/a8k/type/A8kScanCurve.java @@ -1,17 +1,14 @@ package a8k.type; +import java.util.ArrayList; import java.util.List; public class A8kScanCurve { - public List scanDataCurve; - public List refCurve; - public List refLine; + public List scanDataCurve = new ArrayList<>(); + public List refCurve = new ArrayList<>(); + public List refLine = new ArrayList<>(); public A8kScanCurve() { } - public A8kScanCurve(List scanDataCurve, List refLine) { - this.scanDataCurve = scanDataCurve; - this.refLine = refLine; - } } diff --git a/src/main/java/a8k/type/OptScanDirection.java b/src/main/java/a8k/type/OptScanDirection.java index 9e60e18..b243796 100644 --- a/src/main/java/a8k/type/OptScanDirection.java +++ b/src/main/java/a8k/type/OptScanDirection.java @@ -1,9 +1,10 @@ package a8k.type; public enum OptScanDirection { - POSITIVE, NEGATIVE; + FORWARD, //从左向右扫描 + BACKWARD; public Integer getInteger() { - return this == POSITIVE ? 1 : -1; + return this == FORWARD ? 1 : -1; } } diff --git a/src/main/java/a8k/type/appret/AppRet.java b/src/main/java/a8k/type/appret/AppRet.java index 9625af9..9b6c8d1 100644 --- a/src/main/java/a8k/type/appret/AppRet.java +++ b/src/main/java/a8k/type/appret/AppRet.java @@ -5,7 +5,7 @@ import a8k.hardware.type.a8kcanprotocol.A8kEcode; import a8k.type.exception.AppException; import lombok.Getter; -public class AppRet { +public class AppRet { public AppRetType appRetType = AppRetType.SUCCESS; // 错误信息 public AppError ecode = null; @@ -15,7 +15,7 @@ public class AppRet { public String traceInfo = null; // 携带的对象 public String dataType; - public T data; + public Object data; // 接口请求时间 @Getter @@ -29,32 +29,33 @@ public class AppRet { return !AppRetType.FAILURE.equals(appRetType); } - public static AppRet success(T data) { - AppRet r = new AppRet<>(); + public static AppRet success(T data) { + AppRet r = new AppRet(); r.appRetType = AppRetType.SUCCESS; r.data = data; + r.dataType = data.getClass().getSimpleName(); return r; } - public static AppRet success() { - AppRet r = new AppRet<>(); + public static AppRet success() { + AppRet r = new AppRet(); r.appRetType = AppRetType.SUCCESS; return r; } - public static AppRet fail(Exception e) { + public static AppRet fail(Exception e) { StringBuilder traceSb = new StringBuilder(); for (var trace : e.getStackTrace()) { traceSb.append(trace.toString()).append("\n"); } String trace = traceSb.toString(); - AppRet r = new AppRet<>(); + AppRet r = new AppRet(); r.appRetType = AppRetType.FAILURE; if (e instanceof AppException hexcep) { - r.ecode = hexcep.error; + r.ecode = hexcep.error; } else { - r.ecode = new AppError(A8kEcode.CODEERROR); + r.ecode = new AppError(A8kEcode.CODEERROR); } r.traceInfo = trace; r.message = e.getMessage();