From 9f28d25f8445d8fafb995b9f27c69cda9c4b8ce9 Mon Sep 17 00:00:00 2001 From: zhaohe Date: Fri, 25 Oct 2024 22:48:52 +0800 Subject: [PATCH] update --- README2.md | 17 +- app.db | Bin 225280 -> 0 bytes .../java/a8k/extapi_controler/ExtApiControler.java | 49 +--- .../pagecontrol/ExtApiTabConfig.java | 1 + .../java/a8k/extapi_controler/utils/ExtApiFn.java | 2 +- src/main/java/a8k/hardware/A8kCanBusService.java | 8 +- .../java/a8k/hardware/A8kModParamInitializer.java | 15 +- .../hardware/type/regindex/StepMotorRegIndex.java | 61 ----- .../ctrlservice/DeviceInitCtrlService.java | 2 +- .../ctrlservice/OptScanModuleCtrlService.java | 11 +- .../app/devicectrl/driver/StepMotorCtrlDriver.java | 108 ++++++--- .../devicectrl/driver/type/StepMotorRegIndex.java | 3 +- .../devicectrl/exdriver/MotorEnableExDriver.java | 7 +- .../exdriver/TubePreProcesModuleExDriver.java | 12 +- .../param/calibration/HbotTipPosCalibration.java | 117 +++++++-- .../calibration/OptModuleParamCalibration.java | 26 +- .../calibration/TubePreProcesPosCalibration.java | 264 +++++++++++++-------- .../devicectrl/param/param_mgr/HbotTipPosMgr.java | 47 +++- .../param/param_mgr/OptModuleExtParamsMgr.java | 59 +++++ .../param/param_mgr/OptModuleParamsMgr.java | 56 +---- .../param/param_mgr/TemperatureCtrlParamMgr.java | 8 +- .../param/param_mgr/TubePreProcesPosParamMgr.java | 7 +- .../devicectrl/param/type/OptModuleExtParam.java | 20 ++ .../app/devicectrl/param/type/OptModuleParam.java | 10 - .../param/type/TubePrePorcessStructConstant.java | 1 + .../param/type/TubePreProcessZAxisPos.java | 12 + src/main/java/a8k/type/TipPosConfig.java | 11 + .../java/a8k/type/TubePreProcessGripperPos.java | 2 +- src/main/java/a8k/type/TubePreProcessZAxisPos.java | 13 - src/main/java/a8k/utils/ZJsonHelper.java | 14 ++ src/main/resources/app.db | Bin 0 -> 225280 bytes src/main/resources/application-dev.yml | 16 +- src/main/resources/application-test.yml | 17 +- src/main/resources/application-zhaohe_pc.yml | 19 -- 34 files changed, 569 insertions(+), 446 deletions(-) delete mode 100644 app.db delete mode 100644 src/main/java/a8k/hardware/type/regindex/StepMotorRegIndex.java create mode 100644 src/main/java/a8k/service/app/devicectrl/param/param_mgr/OptModuleExtParamsMgr.java create mode 100644 src/main/java/a8k/service/app/devicectrl/param/type/OptModuleExtParam.java create mode 100644 src/main/java/a8k/service/app/devicectrl/param/type/TubePrePorcessStructConstant.java create mode 100644 src/main/java/a8k/service/app/devicectrl/param/type/TubePreProcessZAxisPos.java create mode 100644 src/main/java/a8k/type/TipPosConfig.java delete mode 100644 src/main/java/a8k/type/TubePreProcessZAxisPos.java create mode 100644 src/main/resources/app.db delete mode 100644 src/main/resources/application-zhaohe_pc.yml diff --git a/README2.md b/README2.md index e482ce6..899dba3 100644 --- a/README2.md +++ b/README2.md @@ -104,14 +104,19 @@ TODO: 2. 吸空检测 校准移液枪相关参数 - 10. 加热功能 - 支持通过excel导入项目信息 + 10. 加热功能 OK ``` ``` - 16. 支持急停 -6. 核对ID卡信息 -1. 记录打印功能? -3. 支持鼠标? +0. 支持通过excel导入项目信息 +1. 部署 +2. 支持急停 +3. 在插卡时,添加ID卡信息核对代码 +4. 支持标准卡测试 +5. 支持板夹出仓时扫码检查功能 +4. 记录打印功能? + +6. 支持吸空检测 (困难) +5. 支持鼠标? (困难) ``` \ No newline at end of file diff --git a/app.db b/app.db deleted file mode 100644 index f800f487ac42143690e3e3505bb4b5eabb1c2cca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 225280 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 diff --git a/src/main/java/a8k/extapi_controler/ExtApiControler.java b/src/main/java/a8k/extapi_controler/ExtApiControler.java index ce03657..e50a336 100644 --- a/src/main/java/a8k/extapi_controler/ExtApiControler.java +++ b/src/main/java/a8k/extapi_controler/ExtApiControler.java @@ -165,7 +165,7 @@ public class ExtApiControler { } return AppRet.success(statusList); } - +// @PostMapping("/api/service-config/service-action-list") @ResponseBody public AppRet serviceActionList(@RequestBody Map params) throws Exception { @@ -280,53 +280,6 @@ public class ExtApiControler { return this.executeServiceActionAndGetResponse(service, method, actionParams); } - @PostMapping("/api/service-config/service-action-exec-by-map") - @ResponseBody - 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"); - - - var actionName = (String) params.get("action"); - var actionParams = (Map) params.get("params"); - List actionParamList = new ArrayList<>(); - Method method = null; - for (var methodItem : service.getClass().getMethods()) { - if (!methodItem.getName().equals(actionName)) { - continue; - } - if (methodItem.getParameterTypes().length != actionParams.size()) { - continue; - } - if (!methodItem.isAnnotationPresent(ExtApiFn.class)) { - continue; - } - - actionParamList.clear(); - for (var paramItem : methodItem.getParameters()) { - var name = paramItem.getName(); - Object value = actionParams.get(name); - if (paramItem.getType().isEnum()) { - var methodValueOf = paramItem.getType().getMethod("valueOf", String.class); - value = methodValueOf.invoke(null, (String) value); - } else if (paramItem.getType().equals(EnginnerParamFile.class)) { - value = EnginnerParamFile.fromBase64((String) value); - } else if (paramItem.getType().equals(Double.class)) { - value = Double.valueOf(String.format("%s", value)); - } - if (!paramItem.getType().isAssignableFrom(value.getClass())) { - continue; - } - actionParamList.add(value); - } - method = methodItem; - break; - } - Assert.isTrue(method != null, "method not found"); - return this.executeServiceActionAndGetResponse(service, method, actionParamList); - } - @PostMapping("/api/service-config/class-struct-info-get") @ResponseBody public AppRet classStructInfoGet(@RequestBody Map params) throws Exception { diff --git a/src/main/java/a8k/extapi_controler/pagecontrol/ExtApiTabConfig.java b/src/main/java/a8k/extapi_controler/pagecontrol/ExtApiTabConfig.java index b6af803..7d2a3ea 100644 --- a/src/main/java/a8k/extapi_controler/pagecontrol/ExtApiTabConfig.java +++ b/src/main/java/a8k/extapi_controler/pagecontrol/ExtApiTabConfig.java @@ -36,6 +36,7 @@ public enum ExtApiTabConfig { VirtualDeviceSimulationTest("测试.虚拟设备测试", true), MainflowCtrlTestService("测试.主流程控制测试", true), A8kPipetteCtrlModule("硬件驱动测试.移液枪测试", true), + StepMotorCtrlDriver("硬件驱动测试.步进电机测试", true), ActionReactorService("底层调试.单步调试", false),//OK ReactionPlatesTransmitCtrl("ReactionPlatesTransmitCtrl", false), diff --git a/src/main/java/a8k/extapi_controler/utils/ExtApiFn.java b/src/main/java/a8k/extapi_controler/utils/ExtApiFn.java index 2033812..9ba3e12 100644 --- a/src/main/java/a8k/extapi_controler/utils/ExtApiFn.java +++ b/src/main/java/a8k/extapi_controler/utils/ExtApiFn.java @@ -7,7 +7,7 @@ import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) public @interface ExtApiFn { - String name(); + String name() default ""; String group() default ""; int groupOrder() default 0; int order() default 0; diff --git a/src/main/java/a8k/hardware/A8kCanBusService.java b/src/main/java/a8k/hardware/A8kCanBusService.java index c01a982..8a79df4 100644 --- a/src/main/java/a8k/hardware/A8kCanBusService.java +++ b/src/main/java/a8k/hardware/A8kCanBusService.java @@ -22,6 +22,7 @@ import org.java_websocket.enums.ReadyState; import org.java_websocket.handshake.ServerHandshake; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.net.URI; @@ -46,6 +47,7 @@ public class A8kCanBusService { @Resource VirtualDevice virtualDevice; + @Value("${A8kCanBusService.url:ws://127.0.0.1:19005}") public String uri; // assign by application.yml private WebSocketClient client; private A8kPacket txPacketContext; @@ -71,10 +73,8 @@ public class A8kCanBusService { logger.info("BaseHardwareService initilized"); packetIndex = 0; - if (this.uri == null) { - // this.uri = "ws://127.0.0.1:19005"; - this.uri = "ws://192.168.8.10:19005"; - } + + logger.info("+++++++++++++++++++++++++a8k canbus connect to {}", this.uri); URI uri = new URI(this.uri); client = new WebSocketClient(uri) { diff --git a/src/main/java/a8k/hardware/A8kModParamInitializer.java b/src/main/java/a8k/hardware/A8kModParamInitializer.java index 1bb7e0b..d34f3bc 100644 --- a/src/main/java/a8k/hardware/A8kModParamInitializer.java +++ b/src/main/java/a8k/hardware/A8kModParamInitializer.java @@ -1,7 +1,10 @@ package a8k.hardware; import a8k.service.app.devicectrl.driver.PipetteCtrlDriver; +import a8k.service.app.devicectrl.driver.StepMotorCtrlDriver; import a8k.service.app.devicectrl.driver.type.PipetteRegIndex; +import a8k.service.app.devicectrl.driver.type.StepMotorMId; +import a8k.service.app.devicectrl.driver.type.StepMotorRegIndex; import a8k.service.bases.AppEventBusService; import a8k.service.bases.appevent.A8kCanBusOnConnectEvent; import a8k.service.bases.appevent.AppEvent; @@ -24,9 +27,11 @@ public class A8kModParamInitializer { AppEventBusService eventBus; @Resource - A8kCanBusService canBus; + A8kCanBusService canBus; @Resource - PipetteCtrlDriver pipetteCtrlDriver; + PipetteCtrlDriver pipetteCtrlDriver; + @Resource + StepMotorCtrlDriver stepMotorCtrlDriver; @Resource @@ -107,6 +112,12 @@ public class A8kModParamInitializer { canBus.moduleSetReg(MId.HbotM, RegIndex.kreg_xyrobot_look_zero_edge_speed, 10); +// //摇匀模组降低其加速度 + stepMotorCtrlDriver.setReg(StepMotorMId.ShakeModShakeM, StepMotorRegIndex.kreg_step_motor_a1, 300); + stepMotorCtrlDriver.setReg(StepMotorMId.ShakeModShakeM, StepMotorRegIndex.kreg_step_motor_d1, 300); + stepMotorCtrlDriver.setReg(StepMotorMId.ShakeModShakeM, StepMotorRegIndex.kreg_step_motor_amax, 300); + stepMotorCtrlDriver.setReg(StepMotorMId.ShakeModShakeM, StepMotorRegIndex.kreg_step_motor_dmax, 300); + } diff --git a/src/main/java/a8k/hardware/type/regindex/StepMotorRegIndex.java b/src/main/java/a8k/hardware/type/regindex/StepMotorRegIndex.java deleted file mode 100644 index 8c11d81..0000000 --- a/src/main/java/a8k/hardware/type/regindex/StepMotorRegIndex.java +++ /dev/null @@ -1,61 +0,0 @@ -package a8k.hardware.type.regindex; - -public enum StepMotorRegIndex { - /*********************************************************************************************************************** - * step_motor * - ***********************************************************************************************************************/ - kreg_step_motor_pos(RegIndex.kreg_step_motor_pos.index), // 机器人x坐标 - kreg_step_motor_is_enable(10102), // 是否使能 - kreg_step_motor_dpos(10103), // 执行完上一条指令后的相对位移 - kreg_step_motor_shift(10150), // x偏移 - kreg_step_motor_shaft(10151), // x轴是否反转 - kreg_step_motor_one_circle_pulse(10152), // x轴一圈脉冲数 - kreg_step_motor_one_circle_pulse_denominator(10153), // 设置一圈脉冲数的分母 - kreg_step_motor_default_velocity(10154), // 默认速度 - kreg_step_motor_ihold(10158), // 步进电机电流配置 - kreg_step_motor_irun(10159), // 步进电机电流配置 - kreg_step_motor_iholddelay(10160), // 步进电机电流配置 - kreg_step_motor_iglobalscaler(10161), // 步进电机电流配置 - kreg_step_motor_run_to_zero_speed(10173), // 回零速度 - kreg_step_motor_look_zero_edge_speed(10175), // 找零边缘速度 - kreg_step_motor_max_d(10178), // 最大限制距离 - kreg_step_motor_min_d(10179), // 最小限制距离 - kreg_step_motor_in_debug_mode(10180), // 驱动器处于调试模式 - kreg_step_motor_vstart(10181), // a1起作用的速度 - kreg_step_motor_a1(10182), // - kreg_step_motor_amax(10183), // - kreg_step_motor_v1(10184), // - kreg_step_motor_dmax(10185), // - kreg_step_motor_d1(10186), // - kreg_step_motor_vstop(10187), // - kreg_step_motor_tzerowait(10188), // - kreg_step_motor_enc_resolution(10189), // 编码器分辨率 1000,1024,4000,4096,16384 - kreg_step_motor_enable_enc(10190), // - kreg_step_motor_dzero_pos(10191), // 驱动器处于调试模式 - kret_step_motor_pos_devi_tolerance(10192), // 位置偏差容忍度 - kret_step_motor_io_trigger_append_distance(10193), // 移动到io时,附加的距离 - ; - - public final int index; - public final Boolean trace; - - StepMotorRegIndex(int regIndex) { - this.index = regIndex; - this.trace = true; - } - - StepMotorRegIndex(int regIndex, Boolean trace) { - this.index = regIndex; - this.trace = trace; - } - - public static StepMotorRegIndex valueOf(int val) { - StepMotorRegIndex[] values = StepMotorRegIndex.values(); - for (StepMotorRegIndex regindex : values) { - if (regindex.index == val) { - return regindex; - } - } - return null; - } -} diff --git a/src/main/java/a8k/service/app/devicectrl/ctrlservice/DeviceInitCtrlService.java b/src/main/java/a8k/service/app/devicectrl/ctrlservice/DeviceInitCtrlService.java index c2af30b..efb4745 100644 --- a/src/main/java/a8k/service/app/devicectrl/ctrlservice/DeviceInitCtrlService.java +++ b/src/main/java/a8k/service/app/devicectrl/ctrlservice/DeviceInitCtrlService.java @@ -115,7 +115,7 @@ public class DeviceInitCtrlService { actionReactor.dosome("摇匀模组-夹紧电机回零", () -> stepMotorCtrlDriver.stepMotorEasyMoveToZeroBlock(StepMotorMId.ShakeModClampingM, actionOvertime)); actionReactor.dosome("摇匀模组-夹爪Z轴电机回零", () -> stepMotorCtrlDriver.stepMotorEasyMoveToZeroBlock(StepMotorMId.ShakeModGripperZM, actionOvertime)); actionReactor.dosome("摇匀模组-摇匀电机回零", () -> stepMotorCtrlDriver.stepMotorEasyMoveToZeroBlock(StepMotorMId.ShakeModShakeM, actionOvertime)); - actionReactor.dosome("摇匀模组-摇匀电机摆动90度", () -> stepMotorCtrlDriver.stepMotorEasyMoveTo(StepMotorMId.ShakeModShakeM, 90)); + actionReactor.dosome("摇匀模组-摇匀电机摆动90度", () -> stepMotorCtrlDriver.stepMotorEasyMoveToBlock(StepMotorMId.ShakeModShakeM, 90,actionOvertime)); //板夹仓初始化 actionReactor.dosome("板夹仓Y轴电机回零", () -> stepMotorCtrlDriver.stepMotorEasyMoveToZeroBlock(StepMotorMId.PlatesBoxYM, actionOvertime)); actionReactor.dosome("板夹仓推板电机回零", () -> stepMotorCtrlDriver.stepMotorEasyMoveToZeroBlock(StepMotorMId.PlatesBoxPusherM, actionOvertime)); 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 1d96268..d8e3734 100644 --- a/src/main/java/a8k/service/app/devicectrl/ctrlservice/OptScanModuleCtrlService.java +++ b/src/main/java/a8k/service/app/devicectrl/ctrlservice/OptScanModuleCtrlService.java @@ -14,6 +14,7 @@ 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.OptModuleExtParamsMgr; import a8k.service.app.devicectrl.param.param_mgr.OptModuleParamsMgr; import a8k.service.bases.ActionReactorService; import a8k.service.db.type.ProjOptConfig; @@ -44,6 +45,8 @@ public class OptScanModuleCtrlService { OptModuleDriver optModuleDriver; @Resource + OptModuleExtParamsMgr optModuleExtParamsMgr; + @Resource OptModuleParamsMgr optModuleParamsMgr; @Resource TurnableMoveCtrlService turnableMoveCtrlService; @@ -64,11 +67,11 @@ public class OptScanModuleCtrlService { public Integer[] startOptScan(A8kOptType optType, Integer rawScanGain) throws AppException { - Integer forwardScanPos = optModuleParamsMgr.getOptScanStartPos(optType); + Integer forwardScanPos = optModuleExtParamsMgr.getOptScanStartPos(optType); - // Double scanGain = optModuleParamsMgr.getScanGain(optType); + // Double scanGain = optModuleExtParamsMgr.getScanGain(optType); // Integer rawScanGain = OptGainConvert.scanerToRawGain(optType, scanGain); - Integer lasterGain = optModuleParamsMgr.getOptEmissionIntensity(optType); + Integer lasterGain = optModuleExtParamsMgr.getOptEmissionIntensity(optType); switch (optType) { case TOPT -> { @@ -109,7 +112,7 @@ public class OptScanModuleCtrlService { for (int i = 0; i < adjustCount; i++) { if (i == 0) { - scanRealGain = optModuleParamsMgr.getScanGain(optType); + scanRealGain = optModuleExtParamsMgr.getScanGain(optType); scanRawGain = OptGainConvert.scanerToRawGain(optType, scanRealGain); } diff --git a/src/main/java/a8k/service/app/devicectrl/driver/StepMotorCtrlDriver.java b/src/main/java/a8k/service/app/devicectrl/driver/StepMotorCtrlDriver.java index a456a57..c0176f0 100644 --- a/src/main/java/a8k/service/app/devicectrl/driver/StepMotorCtrlDriver.java +++ b/src/main/java/a8k/service/app/devicectrl/driver/StepMotorCtrlDriver.java @@ -1,67 +1,89 @@ package a8k.service.app.devicectrl.driver; +import a8k.extapi_controler.utils.ExtApiFn; +import a8k.extapi_controler.utils.ExtApiTab; import a8k.hardware.A8kCanBusService; import a8k.hardware.type.a8kcanprotocol.A8kPacket; import a8k.hardware.type.a8kcanprotocol.CmdId; import a8k.hardware.type.regindex.RegIndex; import a8k.service.app.devicectrl.driver.type.StepMotorMId; +import a8k.service.app.devicectrl.driver.type.StepMotorRegIndex; import a8k.type.exception.AppException; +import a8k.utils.ZJsonHelper; +import com.fasterxml.jackson.databind.node.ObjectNode; import jakarta.annotation.Resource; import org.slf4j.Logger; import org.springframework.stereotype.Component; @Component +@ExtApiTab(cfg = a8k.extapi_controler.pagecontrol.ExtApiTabConfig.StepMotorCtrlDriver) public class StepMotorCtrlDriver { static Logger logger = org.slf4j.LoggerFactory.getLogger(StepMotorCtrlDriver.class); @Resource A8kCanBusService canBus; + + void stepMotorEasyMoveBy(StepMotorMId id, Integer dpos) throws AppException { + canBus.callcmd(id.mid, CmdId.step_motor_easy_move_by, dpos); + } + + void stepMotorEasyMoveTo(StepMotorMId id, Integer pos) throws AppException { + canBus.callcmd(id.mid, CmdId.step_motor_easy_move_to, pos); + } + + void stepMotorEasyMoveToZero(StepMotorMId id) throws AppException { + canBus.callcmd(id.mid, CmdId.step_motor_easy_move_to_zero); + } + + void stepMotorEasyMoveToZeroPointQuick(StepMotorMId id) throws AppException { + canBus.callcmd(id.mid, CmdId.step_motor_easy_move_to_zero_point_quick); + } + + void stepMotorEasyMoveToEndPoint(StepMotorMId id) throws AppException { + canBus.callcmd(id.mid, CmdId.step_motor_easy_move_to_end_point); + } + // // stepMotor // + @ExtApiFn(name = "stepMotorEnable", order = 1) public void stepMotorEnable(StepMotorMId mid, Integer enable) throws AppException { canBus.callcmd(mid.mid, CmdId.step_motor_enable, enable); } + @ExtApiFn(name = "stepMotorReadPos", order = 2) public Integer stepMotorReadPos(StepMotorMId id) throws AppException { A8kPacket packet = canBus.callcmd(id.mid, CmdId.step_motor_read_pos); return packet.getContentI32(0); } - public void stepMotorEasyRotate(StepMotorMId id, int direction) throws AppException { + @ExtApiFn(name = "stepMotorEasyRotate", order = 3) + public void stepMotorEasyRotate(StepMotorMId id, Integer direction) throws AppException { canBus.callcmd(id.mid, CmdId.step_motor_easy_rotate, direction); } - public void stepMotorEasyMoveBy(StepMotorMId id, int dpos) throws AppException { - canBus.callcmd(id.mid, CmdId.step_motor_easy_move_by, dpos); - } - - public void stepMotorEasyMoveByBlock(StepMotorMId id, int dpos, Integer actionOvertime) throws AppException { + @ExtApiFn(name = "stepMotorEasyMoveByBlock", order = 4) + public void stepMotorEasyMoveByBlock(StepMotorMId id, Integer dpos, Integer actionOvertime) throws AppException { logger.info("stepMotorEasyMoveByBlock {} {}", id, dpos); stepMotorEasyMoveBy(id, dpos); canBus.waitForMod(id.mid, actionOvertime); } - public void stepMotorEasyMoveTo(StepMotorMId id, int pos) throws AppException { - canBus.callcmd(id.mid, CmdId.step_motor_easy_move_to, pos); - } - - public void stepMotorEasyMoveToBlock(StepMotorMId id, int pos, Integer actionOvertime) throws AppException { + @ExtApiFn(name = "stepMotorEasyMoveToBlock", order = 5) + public void stepMotorEasyMoveToBlock(StepMotorMId id, Integer pos, Integer actionOvertime) throws AppException { logger.info("stepMotorEasyMoveToBlock {} {}", id, pos); stepMotorEasyMoveTo(id, pos); canBus.waitForMod(id.mid, actionOvertime); } - public void stepMotorEasyMoveToZero(StepMotorMId id) throws AppException { - canBus.callcmd(id.mid, CmdId.step_motor_easy_move_to_zero); - } - + @ExtApiFn(name = "stepMotorEasyMoveToZeroBlock", order = 6) public void stepMotorEasyMoveToZeroBlock(StepMotorMId id, Integer actionOvertime) throws AppException { logger.info("stepMotorEasyMoveToZeroBlock {}", id); stepMotorEasyMoveToZero(id); canBus.waitForMod(id.mid, actionOvertime); } + @ExtApiFn(name = "stepMotorReadPosByMoveToZeroBlock", order = 7) public Integer stepMotorReadPosByMoveToZeroBlock(StepMotorMId id, Integer actionOvertime) throws AppException { stepMotorEnable(id, 1); stepMotorEasyMoveToZeroBlock(id, actionOvertime); @@ -71,25 +93,23 @@ public class StepMotorCtrlDriver { return measurepos; } - public void stepMotorEasySetCurrentPos(StepMotorMId id, int pos) throws AppException { - canBus.callcmd(id.mid, CmdId.step_motor_easy_set_current_pos, pos); - } - - public void stepMotorEasyMoveToIo(StepMotorMId id, int io) throws AppException { - canBus.callcmd(id.mid, CmdId.step_motor_easy_move_to_io, io); - } + // public void stepMotorEasySetCurrentPos(StepMotorMId id, Integer pos) throws AppException { + // canBus.callcmd(id.mid, CmdId.step_motor_easy_set_current_pos, pos); + // } + // + // public void stepMotorEasyMoveToIo(StepMotorMId id, Integer io) throws AppException { + // canBus.callcmd(id.mid, CmdId.step_motor_easy_move_to_io, io); + // } // step_motor_easy_move_to_zero_point_quick - public void stepMotorEasyMoveToZeroPointQuick(StepMotorMId id) throws AppException { - canBus.callcmd(id.mid, CmdId.step_motor_easy_move_to_zero_point_quick); - } - + @ExtApiFn(name = "stepMotorEasyMoveToZeroPointQuickBlock", order = 8) public void stepMotorEasyMoveToZeroPointQuickBlock(StepMotorMId id, Integer actionOvertime) throws AppException { stepMotorEasyMoveToZeroPointQuick(id); canBus.waitForMod(id.mid, actionOvertime); } + @ExtApiFn(name = "stepMotorReadIoState", order = 9) public void stepMotorStop(StepMotorMId id) throws AppException { canBus.callcmd(id.mid, CmdId.step_motor_stop, 0); } @@ -98,26 +118,50 @@ public class StepMotorCtrlDriver { canBus.callcmd(id.mid, CmdId.step_motor_active_cfg); } - public Boolean stepMotorReadIoState(StepMotorMId id, int ioindex) throws AppException { + @ExtApiFn(name = "stepMotorReadIoState", order = 10) + public Boolean stepMotorReadIoState(StepMotorMId id, Integer ioindex) throws AppException { var packet = canBus.callcmd(id.mid, CmdId.step_motor_read_io_state, ioindex); return packet.getContentI32(0) != 0; } - public void stepMotorEasyMoveToEndPoint(StepMotorMId id) throws AppException { - canBus.callcmd(id.mid, CmdId.step_motor_easy_move_to_end_point); - } + @ExtApiFn(name = "stepMotorEasyMoveToZeroPointQuickBlock", order = 12) public void stepMotorEasyMoveToEndPointBlock(StepMotorMId id, Integer actionOvertime) throws AppException { stepMotorEasyMoveToEndPoint(id); canBus.waitForMod(id.mid, actionOvertime); } - public void stepMotorEasyReciprocatingMotion(StepMotorMId id, int startpos, int endpos, int times) throws AppException { + + void stepMotorEasyReciprocatingMotion(StepMotorMId id, Integer startpos, Integer endpos, Integer times) throws AppException { canBus.callcmd(id.mid, CmdId.step_motor_easy_reciprocating_motion, startpos, endpos, times); } - public void stepMotorEasyReciprocatingMotionBlock(StepMotorMId id, int startpos, int endpos, int times, Integer actionOvertime) throws AppException { + @ExtApiFn(name = "stepMotorEasyReciprocatingMotionBlock", order = 13) + public void stepMotorEasyReciprocatingMotionBlock(StepMotorMId id, Integer startpos, Integer endpos, Integer times, Integer actionOvertime) throws AppException { stepMotorEasyReciprocatingMotion(id, startpos, endpos, times); canBus.waitForMod(id.mid, actionOvertime); } + + @ExtApiFn(name = "setReg", order = 14) + public void setReg(StepMotorMId id, StepMotorRegIndex regIndex, Integer val) throws AppException { + canBus.moduleSetReg(id.mid, regIndex.regIndex, val); + } + + @ExtApiFn(name = "getReg", order = 15) + public Integer getReg(StepMotorMId id, StepMotorRegIndex regIndex) throws AppException { + return canBus.moduleGetReg(id.mid, regIndex.regIndex); + } + + @ExtApiFn(name = "getAllReg", order = 16) + public ObjectNode getAllReg(StepMotorMId id) throws AppException { + ObjectNode node = ZJsonHelper.createObjectNode(); + for (StepMotorRegIndex regIndex : StepMotorRegIndex.values()) { + Integer regVal = getReg(id, regIndex); + logger.info("read reg {} -> {}", regIndex,regVal); + node.put(regIndex.name(), getReg(id, regIndex)); + + } + return node; + } + } diff --git a/src/main/java/a8k/service/app/devicectrl/driver/type/StepMotorRegIndex.java b/src/main/java/a8k/service/app/devicectrl/driver/type/StepMotorRegIndex.java index 21c0450..ab13468 100644 --- a/src/main/java/a8k/service/app/devicectrl/driver/type/StepMotorRegIndex.java +++ b/src/main/java/a8k/service/app/devicectrl/driver/type/StepMotorRegIndex.java @@ -7,14 +7,13 @@ public enum StepMotorRegIndex { kreg_module_type(RegIndex.kreg_module_type), // 模块类型 kreg_module_status(RegIndex.kreg_module_status), // 0idle,1busy,2error kreg_module_errorcode(RegIndex.kreg_module_errorcode), // inited_flag - kreg_extboard_resetflag(RegIndex.kreg_extboard_resetflag), /*********************************************************************************************************************** * step_motor * ***********************************************************************************************************************/ kreg_step_motor_pos(RegIndex.kreg_step_motor_pos), // 机器人x坐标 kreg_step_motor_is_enable(RegIndex.kreg_step_motor_is_enable), // 是否使能 kreg_step_motor_dpos(RegIndex.kreg_step_motor_dpos), // 执行完上一条指令后的相对位移 - kreg_step_motor_shift(RegIndex.kreg_step_motor_shift), // x偏移 +// kreg_step_motor_shift(RegIndex.kreg_step_motor_shift), // x偏移 kreg_step_motor_shaft(RegIndex.kreg_step_motor_shaft), // x轴是否反转 kreg_step_motor_one_circle_pulse(RegIndex.kreg_step_motor_one_circle_pulse), // x轴一圈脉冲数 kreg_step_motor_one_circle_pulse_denominator(RegIndex.kreg_step_motor_one_circle_pulse_denominator), // 设置一圈脉冲数的分母 diff --git a/src/main/java/a8k/service/app/devicectrl/exdriver/MotorEnableExDriver.java b/src/main/java/a8k/service/app/devicectrl/exdriver/MotorEnableExDriver.java index 360bb68..d763c36 100644 --- a/src/main/java/a8k/service/app/devicectrl/exdriver/MotorEnableExDriver.java +++ b/src/main/java/a8k/service/app/devicectrl/exdriver/MotorEnableExDriver.java @@ -33,7 +33,12 @@ public class MotorEnableExDriver { Integer val = enable ? 1 : 0; miniServoDriver.miniServoEnable(MiniServoMId.ShakeModGripperSV, val); miniServoDriver.miniServoEnable(MiniServoMId.ShakeModGripperYSV, val); - stepMotorCtrlDriver.stepMotorEnable(StepMotorMId.ShakeModClampingM, val); + if (!enable) { + //TODO: 只有第一台样机,由于无法手拧,所以永不失能 + // stepMotorCtrlDriver.stepMotorEnable(StepMotorMId.ShakeModClampingM, val); + } else { + stepMotorCtrlDriver.stepMotorEnable(StepMotorMId.ShakeModClampingM, val); + } stepMotorCtrlDriver.stepMotorEnable(StepMotorMId.ShakeModGripperZM, val); stepMotorCtrlDriver.stepMotorEnable(StepMotorMId.ShakeModShakeM, val); } diff --git a/src/main/java/a8k/service/app/devicectrl/exdriver/TubePreProcesModuleExDriver.java b/src/main/java/a8k/service/app/devicectrl/exdriver/TubePreProcesModuleExDriver.java index 83c9624..f79d8d2 100644 --- a/src/main/java/a8k/service/app/devicectrl/exdriver/TubePreProcesModuleExDriver.java +++ b/src/main/java/a8k/service/app/devicectrl/exdriver/TubePreProcesModuleExDriver.java @@ -46,15 +46,10 @@ public class TubePreProcesModuleExDriver { miniServoDriver.miniServoMoveToBlock(MiniServoMId.ShakeModGripperSV, tubePreProcesPosParamMgr.getGripperServoOpenPos()); } - public void gripperSVCClose() throws AppException { - miniServoDriver.miniServoMoveToBlock(MiniServoMId.ShakeModGripperSV, tubePreProcesPosParamMgr.getGripperServoClosePos()); - } - public void gripperSVClampTube() throws AppException { miniServoDriver.miniServoMoveToBlock(MiniServoMId.ShakeModGripperSV, tubePreProcesPosParamMgr.getGripperServoTakeCapPos()); } - public void YSVMoveToTakeTubePos() throws AppException { miniServoDriver.miniServoMoveToBlock(MiniServoMId.ShakeModGripperYSV, tubePreProcesPosParamMgr.getYServoTakeTubePos() - 100); //该动作是为了消除齿轮间隙 miniServoDriver.miniServoMoveToBlock(MiniServoMId.ShakeModGripperYSV, tubePreProcesPosParamMgr.getYServoTakeTubePos()); @@ -99,6 +94,10 @@ public class TubePreProcesModuleExDriver { stepMotorCtrlDriver.stepMotorEasyMoveToBlock(StepMotorMId.ShakeModClampingM, tubePreProcesPosParamMgr.getShakeClampMotorReleasePos(), actionOvertime); } + public void clampingMReleaseTubeInFuzzyPos() throws AppException { + stepMotorCtrlDriver.stepMotorEasyMoveToBlock(StepMotorMId.ShakeModClampingM, 90, actionOvertime); + } + public void shakeMMoveTo90() throws AppException { stepMotorCtrlDriver.stepMotorEasyMoveToBlock(StepMotorMId.ShakeModShakeM, 90, actionOvertime); } @@ -106,8 +105,7 @@ public class TubePreProcesModuleExDriver { public void shakeMShake(Integer shakeDegree, Integer times) throws AppException { var startPos = 90 - shakeDegree; var endPos = 90 + shakeDegree; - stepMotorCtrlDriver.stepMotorEasyReciprocatingMotion(StepMotorMId.ShakeModShakeM, startPos, endPos, times); - canBus.waitForMod(MId.ShakeModShakeM, actionOvertime); + stepMotorCtrlDriver.stepMotorEasyReciprocatingMotionBlock(StepMotorMId.ShakeModShakeM, startPos, endPos, times, actionOvertime); } // diff --git a/src/main/java/a8k/service/app/devicectrl/param/calibration/HbotTipPosCalibration.java b/src/main/java/a8k/service/app/devicectrl/param/calibration/HbotTipPosCalibration.java index 15882fc..ddead4f 100644 --- a/src/main/java/a8k/service/app/devicectrl/param/calibration/HbotTipPosCalibration.java +++ b/src/main/java/a8k/service/app/devicectrl/param/calibration/HbotTipPosCalibration.java @@ -6,6 +6,7 @@ import a8k.extapi_controler.pagecontrol.ExtApiTabConfig; import a8k.extapi_controler.utils.ExtApiFn; import a8k.extapi_controler.utils.ExtApiTab; import a8k.hardware.type.a8kcanprotocol.A8kEcode; +import a8k.service.app.devicectrl.param.ext_param_mgr.HbotConsumableParamMgr; import a8k.service.app.devicectrl.param.param_mgr.HbotTipPosMgr; import a8k.service.app.devicectrl.driver.HbotDriver; import a8k.service.app.devicectrl.driver.PipetteCtrlDriver; @@ -23,6 +24,7 @@ import jakarta.annotation.Resource; import org.aspectj.lang.annotation.Aspect; import org.slf4j.Logger; import org.springframework.stereotype.Component; +import org.springframework.util.Assert; import java.util.List; import java.util.Map; @@ -38,11 +40,14 @@ public class HbotTipPosCalibration { HbotDriver hbotDriver; @Resource - HbotCtrlService hbotCtrlService; + HbotCtrlService hbotCtrlService; @Resource - HbotTipPosMgr hbotTipPosMgr; + HbotTipPosMgr hbotTipPosMgr; + @Resource + HbotConsumableParamMgr hbotConsumableParamMgr; - Boolean stopFlag = false; + Boolean stopFlag = false; + TipGroup tipGroup; Boolean checkStopFlag() { if (stopFlag) { @@ -87,20 +92,24 @@ public class HbotTipPosCalibration { hbotDriver.enable(0); } + + @ExtApiFn(name = "设置上下文", group = "设置上下文", order = 20) + public void setContext(TipGroup tipGroup) throws AppException { + this.tipGroup = tipGroup; + } + // // 标定 // - TipGroup tipGroup; List tipRefPosList; Pos3d tip000; Double tipdx; Double tipdy; - - @ExtApiFn(name = "开始标定Tip坐标", group = "标定TIP坐标", order = 20) - public void startCalibrateTipPos(TipGroup tipGroup) throws AppException { - this.tipGroup = tipGroup; + @ExtApiFn(name = "开始标定Tip坐标", group = "辅助标定", order = 20) + public void startCalibrateTipPos() throws AppException { + Assert.isTrue(tipGroup != null, "请先设置上下文"); tipRefPosList = new java.util.ArrayList<>(); moveToZero(); disableModule(); @@ -109,8 +118,7 @@ public class HbotTipPosCalibration { tip000 = new Pos3d(0, 0, 0); } - - @ExtApiFn(name = "添加Tip参考点", group = "标定TIP坐标", order = 21) + @ExtApiFn(name = "添加Tip参考点", group = "辅助标定", order = 21) public Object addTipPosRefPoint(TipRowNum row, TipColumnNum columnNum) throws AppException { enableModule(); Pos2d xypos = hbotDriver.readPos(); @@ -127,7 +135,7 @@ public class HbotTipPosCalibration { return ret; } - @ExtApiFn(name = "删除上一个Tip参考点", group = "标定TIP坐标", order = 22) + @ExtApiFn(name = "删除上一个Tip参考点", group = "辅助标定", order = 22) public Object removeTipPosRefPoint() throws AppException { if (!tipRefPosList.isEmpty()) { tipRefPosList.remove(tipRefPosList.size() - 1); @@ -138,7 +146,7 @@ public class HbotTipPosCalibration { } - @ExtApiFn(name = "计算Tip坐标", group = "标定TIP坐标", order = 23) + @ExtApiFn(name = "计算Tip坐标", group = "辅助标定", order = 23) public ObjectNode computeTipGroupPos() throws AppException { TipRefPoint tip_ref_01_01 = tipRefPosList.stream().filter(tipRefPoint -> tipRefPoint.eq(TipRowNum.ROW00, TipColumnNum.Colu00)).findFirst().orElse(null); @@ -189,43 +197,104 @@ public class HbotTipPosCalibration { } - @ExtApiFn(name = "保存计算结果", group = "标定TIP坐标", order = 24) + @ExtApiFn(name = "保存计算结果", group = "辅助标定", order = 24) public void saveTipGroupPos() throws AppException { + TipPosConfig tipPosConfig = getTipPosConfig(); + if (tipdx == null || tipdx.isNaN() || tipdx.isInfinite()) { + tipdx = tipPosConfig.spaceingX; + } + + if (tipdy == null || tipdy.isNaN() || tipdy.isInfinite()) { + tipdy = tipPosConfig.spaceingY; + } + hbotTipPosMgr.setTipGroupParam(tipGroup, tip000, tipdx, tipdy); } - @ExtApiFn(name = "标定.丢Tip坐标", group = "标定.丢Tip坐标", order = 30) - public void calibrateDropTipPos() throws AppException { - enableModule(); - pipetteCtrlDriver.zMotorMeasureDistance(); - hbotTipPosMgr.setDropTipPos(new Pos3d(hbotDriver.readPos().x, hbotDriver.readPos().y, pipetteCtrlDriver.zMotorReadMeasureDistanceResult())); - disableModule(); + @ExtApiFn(name = "获取当前Tip组的配置", group = "直接设置坐标", order = 31) + public TipPosConfig getTipPosConfig() { + return hbotTipPosMgr.getTipPosCfg(tipGroup); + } + + @ExtApiFn(name = "设置Tip000坐标", group = "直接设置坐标", order = 32) + public void setTipPos000(Integer x, Integer y, Integer z) { + tip000 = new Pos3d(x, y, z); + TipPosConfig poscfg = hbotTipPosMgr.getTipPosCfg(tipGroup); + poscfg.tip000 = tip000; + hbotTipPosMgr.setTipPosCfg(tipGroup, poscfg); + } + + @ExtApiFn(name = "设置Tip间距", group = "直接设置坐标", order = 33) + public void setSpacingXAndSpacingY(Double spacingX, Double spacingY) { + TipPosConfig poscfg = hbotTipPosMgr.getTipPosCfg(tipGroup); + poscfg.spaceingX = spacingX; + poscfg.spaceingY = spacingY; + hbotTipPosMgr.setTipPosCfg(tipGroup, poscfg); } // // 校验 // - @ExtApiFn(name = "校验取Tip坐标", group = "校验", order = 300) - public void testTakeTip(TipGroup tipGroup) throws AppException { + @ExtApiFn(name = "校验取Tip坐标(全部坐标)", group = "校验", order = 300) + public void testTakeTipAll(TipGroup tipGroup) throws AppException { resetStopFlag(); enableModule(); + pipetteCtrlDriver.zMotorMoveZeroBlock(); + for (int i = 0; i < AppConstant.TIP_NUM; i++) { hbotCtrlService.testTakeTip(tipGroup, i); + Pos3d tipPos = hbotConsumableParamMgr.getTipPos(tipGroup, i); + TipRefPoint tipRefPoint = new TipRefPoint(TipRowNum.values()[i / 12], TipColumnNum.values()[i % 12], tipPos); + if (tipRefPosList != null) + tipRefPosList.add(tipRefPoint); if (checkStopFlag()) return; } } - @ExtApiFn(name = "校验丢Tip", group = "校验", order = 301) - public void testDropTipPos() throws AppException { - hbotCtrlService.dropTip(); + @ExtApiFn(name = "校验取Tip坐标(四角坐标)", group = "校验", order = 300) + public void testTakeTipAround(TipGroup tipGroup) throws AppException { + resetStopFlag(); + enableModule(); + pipetteCtrlDriver.zMotorMoveZeroBlock(); + + List testPoint = new java.util.ArrayList<>(); + testPoint.addAll(List.of(0, 1, 10, 11)); + testPoint.addAll(List.of(12, 13, 22, 23)); + testPoint.addAll(List.of(12 * 8, 12 * 8 + 1, 12 * 8 + 10, 12 * 8 + 11)); + testPoint.addAll(List.of(12 * 9, 12 * 9 + 1, 12 * 9 + 10, 12 * 9 + 11)); + + for (Integer i : testPoint) { + hbotCtrlService.testTakeTip(tipGroup, i); + Pos3d tipPos = hbotConsumableParamMgr.getTipPos(tipGroup, i); + TipRefPoint tipRefPoint = new TipRefPoint(TipRowNum.values()[i / 12], TipColumnNum.values()[i % 12], tipPos); + if (tipRefPosList != null) + tipRefPosList.add(tipRefPoint); + if (checkStopFlag()) + return; + } + } + @ExtApiFn(name = "停止校验", group = "校验", order = 304) public void stopTest() throws AppException { setStopFlag(); } + @ExtApiFn(name = "标定.丢Tip坐标", group = "标定.丢Tip坐标", order = 500) + public void calibrateDropTipPos() throws AppException { + enableModule(); + pipetteCtrlDriver.zMotorMeasureDistance(); + hbotTipPosMgr.setDropTipPos(new Pos3d(hbotDriver.readPos().x, hbotDriver.readPos().y, pipetteCtrlDriver.zMotorReadMeasureDistanceResult())); + disableModule(); + } + + @ExtApiFn(name = "校验丢Tip", group = "标定.丢Tip坐标", order = 501) + public void testDropTipPos() throws AppException { + hbotCtrlService.dropTip(); + } + } 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 index 62bc7b0..8c7b530 100644 --- a/src/main/java/a8k/service/app/devicectrl/param/calibration/OptModuleParamCalibration.java +++ b/src/main/java/a8k/service/app/devicectrl/param/calibration/OptModuleParamCalibration.java @@ -9,8 +9,8 @@ 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.app.devicectrl.param.type.OptModuleParam; +import a8k.service.app.devicectrl.param.param_mgr.OptModuleExtParamsMgr; +import a8k.service.app.devicectrl.param.type.OptModuleExtParam; import a8k.service.db.type.Parameter; import a8k.service.db.type.a8kidcard.zenum.A8kOptType; import a8k.type.*; @@ -42,7 +42,7 @@ public class OptModuleParamCalibration { Integer actionOvertime = 5000; @Resource - OptModuleParamsMgr optModuleParamsMgr; + OptModuleExtParamsMgr optModuleExtParamsMgr; @Resource MotorEnableExDriver motorEnableExDriver; @@ -58,7 +58,7 @@ public class OptModuleParamCalibration { @ExtApiFn(name = "获得参数", group = "基础", order = 1) public List getParams() throws AppException { - return optModuleParamsMgr.getParams(); + return optModuleExtParamsMgr.getParams(); } @ExtApiFn(name = "归零", group = "测试工具", order = 11) @@ -137,7 +137,7 @@ public class OptModuleParamCalibration { public void setCurrentAsScanRefPos() throws AppException { stepMotorCtrlDriver.stepMotorEnable(StepMotorMId.OptModScannerM, 1); Integer pos = stepMotorCtrlDriver.stepMotorReadPosByMoveToZeroBlock(StepMotorMId.OptModScannerM, 10000); - optModuleParamsMgr.setOptParam(OptModuleParam.OptScanRefPos, pos); + optModuleExtParamsMgr.setOptParam(OptModuleExtParam.OptScanRefPos, pos); } //FOptScanShift @@ -146,22 +146,22 @@ public class OptModuleParamCalibration { @ExtApiFn(name = "设置F光学扫描偏移", group = "F光学", order = 300) public void setFOptScanShift(Integer shift) { - optModuleParamsMgr.setOptParam(OptModuleParam.FOptScanShift, shift); + optModuleExtParamsMgr.setOptParam(OptModuleExtParam.FOptScanShift, shift); } @ExtApiFn(name = "设置F光学发射强度[1->255]", group = "F光学", order = 301) public void setFOptEmissionIntensity(Integer val) { - optModuleParamsMgr.setOptParam(OptModuleParam.FOptEmissionIntensity, val); + optModuleExtParamsMgr.setOptParam(OptModuleExtParam.FOptEmissionIntensity, val); } @ExtApiFn(name = "设置F光学接收放大倍数[1.1->47]", group = "F光学", order = 302) public void setFOptScanAmplVal(Double val) { - optModuleParamsMgr.setOptParam(OptModuleParam.FOptScanGainVal, val); + optModuleExtParamsMgr.setOptParam(OptModuleExtParam.FOptScanGainVal, val); } @ExtApiFn(name = "F光学扫描", group = "扫描", order = 303) public A8kScanCurve FOptScan() throws AppException { - Double scanGain = optModuleParamsMgr.getScanGain(A8kOptType.FOPT); + Double scanGain = optModuleExtParamsMgr.getScanGain(A8kOptType.FOPT); Integer rawScanGain = OptGainConvert.scanerToRawGain(A8kOptType.FOPT, scanGain); var result = optScanModuleCtrlService.startOptScan(A8kOptType.FOPT, rawScanGain); return createScanCurve1200Point(result); @@ -173,22 +173,22 @@ public class OptModuleParamCalibration { @ExtApiFn(name = "设置T光学扫描偏移", group = "T光学", order = 400) public void setTOptScanShift(Integer shift) { - optModuleParamsMgr.setOptParam(OptModuleParam.TOptScanShift, shift); + optModuleExtParamsMgr.setOptParam(OptModuleExtParam.TOptScanShift, shift); } @ExtApiFn(name = "设置T光学发射强度[1->255]", group = "T光学", order = 401) public void setTOptEmissionIntensity(Integer val) { - optModuleParamsMgr.setOptParam(OptModuleParam.TOptEmissionIntensity, val); + optModuleExtParamsMgr.setOptParam(OptModuleExtParam.TOptEmissionIntensity, val); } @ExtApiFn(name = "设置T光学接收放大倍数[0.5->21.7]", group = "T光学", order = 402) public void setTOptScanAmplVal(Double val) { - optModuleParamsMgr.setOptParam(OptModuleParam.TOptScanGainVal, val); + optModuleExtParamsMgr.setOptParam(OptModuleExtParam.TOptScanGainVal, val); } @ExtApiFn(name = "T光学扫描", group = "扫描", order = 403) public A8kScanCurve TOptScan() throws AppException { - Double scanGain = optModuleParamsMgr.getScanGain(A8kOptType.TOPT); + Double scanGain = optModuleExtParamsMgr.getScanGain(A8kOptType.TOPT); Integer rawScanGain = OptGainConvert.scanerToRawGain(A8kOptType.TOPT, scanGain); var result = optScanModuleCtrlService.startOptScan(A8kOptType.TOPT, rawScanGain); return createScanCurve1200Point(result); diff --git a/src/main/java/a8k/service/app/devicectrl/param/calibration/TubePreProcesPosCalibration.java b/src/main/java/a8k/service/app/devicectrl/param/calibration/TubePreProcesPosCalibration.java index 15d66a2..3ee31a2 100644 --- a/src/main/java/a8k/service/app/devicectrl/param/calibration/TubePreProcesPosCalibration.java +++ b/src/main/java/a8k/service/app/devicectrl/param/calibration/TubePreProcesPosCalibration.java @@ -15,8 +15,9 @@ import a8k.service.app.devicectrl.param.param_mgr.TubePreProcesPosParamMgr; import a8k.type.TubePreProcessGripperPos; import a8k.type.TubePreProcessTubeClamp; import a8k.type.TubePreProcessYPos; -import a8k.type.TubePreProcessZAxisPos; +import a8k.service.app.devicectrl.param.type.TubePreProcessZAxisPos; import a8k.type.exception.AppException; +import a8k.utils.ZJsonHelper; import jakarta.annotation.Resource; import org.springframework.stereotype.Component; @@ -47,6 +48,8 @@ public class TubePreProcesPosCalibration { public void deviceReset() throws AppException { enableModule(); motorMoveZeroExDriver.preProcessModuleMoveToZero(); + stepMotorCtrlDriver.stepMotorEasyMoveToBlock(StepMotorMId.ShakeModShakeM, 90, 5000); + tubePreProcesModuleExDriver.clampingMReleaseTubeInFuzzyPos(); } @ExtApiFn(name = "使能相关模块", group = "测试工具", order = 2) @@ -65,142 +68,211 @@ public class TubePreProcesPosCalibration { return posMgr.getParams(); } + @ExtApiFn(name = "测量Z轴", group = "辅助工具", order = 10) + public Integer measureZAxis() throws AppException { + enableModule(); + Integer zpos = stepMotorCtrlDriver.stepMotorReadPosByMoveToZeroBlock(StepMotorMId.ShakeModGripperZM, 10000); + disableModule(); + return zpos; + } - //TubePreProcessYPos - //TubePreProcessZAxisPos - //TubePreProcessGripperPos - //TubePreProcessTubeClamp - + @ExtApiFn(name = "<试管夹具>夹住试管", group = "辅助工具", order = 11) + public void clampTube() throws AppException { + tubePreProcesModuleExDriver.clampingMclampTube(); + } + @ExtApiFn(name = "<试管夹具>松开试管", group = "辅助工具", order = 12) + public void unclampTube() throws AppException { + tubePreProcesModuleExDriver.clampingMReleaseTube(); + } + // 设置 + // 1. 设置试管帽夹爪冗余(0.1mm) // - // 标定坐标 + // 基础标定 + // 1. 拧开试管夹具 + // 2. 标定当前位置为试管夹具松开位置 + // 3. 掰动试管帽夹爪,让试管帽夹爪处于张开位置 + // 4. 标定当前位置为试管帽夹爪松开位置 + // + // 扩展标定 + // 1. 取一个高试管放入试管架中,挪动设备到取试管的位置 + // 2. 点击标定取高试管位置 + // 3. 取一个低试管放入试管架中,挪动设备到取试管的位置 + // 4. 点击标定取低试管位置 + // 5. 取一个高试管放到摇匀试管的位置,挪动设备到摇匀试管的位置(注意试管夹爪下表面和试管帽接触) + // 6. 点击标定试管摇匀位置 + // + // 辅助测量 + // 读取当前Z轴高度 // - @ExtApiFn(name = "标定前后移动伺服坐标", group = "标定", order = 100) - public Integer calibrateTubePreProcessYPos(TubePreProcessYPos posType) throws AppException { - Integer pos = miniServoDriver.miniServoReadPos(MiniServoMId.ShakeModGripperYSV); - posMgr.setPos(posType, pos); - return pos; - } - @ExtApiFn(name = "标定Z轴坐标", group = "标定", order = 101) - public Integer calibrateTubePreProcessZAxisPos(TubePreProcessZAxisPos posType) throws AppException { + public Integer readShakeModClampingMPos() throws AppException { enableModule(); - Integer pos = stepMotorCtrlDriver.stepMotorReadPosByMoveToZeroBlock(StepMotorMId.ShakeModGripperZM, 10000); - posMgr.setPos(posType, pos); + Integer pos = stepMotorCtrlDriver.stepMotorReadPosByMoveToZeroBlock(StepMotorMId.ShakeModClampingM, 10000); disableModule(); return pos; } - @ExtApiFn(name = "标定夹爪伺服坐标", group = "标定", order = 102) - public Integer calibrateTubePreProcessGripperPos(TubePreProcessGripperPos posType) throws AppException { - enableModule(); + + @ExtApiFn(name = "设置试管帽夹爪冗余(0.1mm)", group = "设置", order = 100) + public void setTubeCapGripperRedundancy(Integer val) throws AppException { + posMgr.setPos(TubePreProcessGripperPos.GripperRedundancyHeight, val); + } + + @ExtApiFn(name = "标定<试管帽夹爪>松开位置", group = "基础标定", order = 110) + public Integer calibrateTubeCapGripperOpenPos() throws AppException { Integer pos = miniServoDriver.miniServoReadPos(MiniServoMId.ShakeModGripperSV); - posMgr.setPos(posType, pos); - disableModule(); + posMgr.setPos(TubePreProcessGripperPos.GripperServoOpenPos, pos); + return pos; + } + + @ExtApiFn(name = "标定<试管夹具>松开位置", group = "基础标定", order = 111) + public Integer calibrateTubeCapGripperClosePos() throws AppException { + Integer pos = readShakeModClampingMPos(); + posMgr.setPos(TubePreProcessTubeClamp.ShakeClampMotorReleasePos, pos); return pos; } - @ExtApiFn(name = "标定试管夹紧伺服坐标", group = "标定", order = 103) - public Integer calibrateTubePreProcessTubeClamp(TubePreProcessTubeClamp posType) throws AppException { + public Object calibrateCurPosAsTakeTubePos(Boolean isHighTube) throws AppException { enableModule(); - Integer pos = stepMotorCtrlDriver.stepMotorReadPosByMoveToZeroBlock(StepMotorMId.ShakeModClampingM, 10000); - if (posType.equals(TubePreProcessTubeClamp.ShakeClampMotorClampPos)) { - posMgr.setPos(posType, pos - 2); + //1. 读取夹爪位置 + Integer gripperPos = miniServoDriver.miniServoReadPos(MiniServoMId.ShakeModGripperSV); + //2. 读取Y轴位置 + Integer ySVPos = miniServoDriver.miniServoReadPos(MiniServoMId.ShakeModGripperYSV); + //2. 夹爪松开 + tubePreProcesModuleExDriver.gripperSVOpen(); + //3. Z轴归零,并读取当前位置 + Integer zpos = stepMotorCtrlDriver.stepMotorReadPosByMoveToZeroBlock(StepMotorMId.ShakeModGripperZM, 10000); + + posMgr.setPos(TubePreProcessGripperPos.GripperServoTakeCapPos, gripperPos); + posMgr.setPos(TubePreProcessYPos.YServoTakeTubePos, ySVPos); + if (isHighTube) { + posMgr.setPos(TubePreProcessZAxisPos.ZMotorTakeHTubePos, zpos); } else { - posMgr.setPos(posType, pos); + posMgr.setPos(TubePreProcessZAxisPos.ZMotorTakeSTubePos, zpos); } + disableModule(); - return pos; + var ObNode = ZJsonHelper.createObjectNode(); + ObNode.put("gripperSVPos", gripperPos); + ObNode.put("ySVPos", ySVPos); + ObNode.put("zMpos", zpos); + return ObNode; } - // - // 夹爪标定,校准,校验 - // - @ExtApiFn(name = "<校验>张开", group = "校验.夹爪", order = 206) - public void gripperSVOpen() throws AppException { - miniServoDriver.miniServoEnable(MiniServoMId.ShakeModGripperSV, 1); - tubePreProcesModuleExDriver.gripperSVOpen(); + + @ExtApiFn(name = "标定<取高试管>位置", group = "扩展标定", order = 200) + public Object calibrateCurPosAsTakeHTubePos() throws AppException { + return calibrateCurPosAsTakeTubePos(true); } - @ExtApiFn(name = "<校验>夹紧", group = "校验.夹爪", order = 205) - public void gripperSVCClose() throws AppException { - miniServoDriver.miniServoEnable(MiniServoMId.ShakeModGripperSV, 1); - tubePreProcesModuleExDriver.gripperSVCClose(); + @ExtApiFn(name = "标定<取低试管>位置", group = "扩展标定", order = 201) + public Object calibrateCurPosAsTakeSTubePos() throws AppException { + return calibrateCurPosAsTakeTubePos(false); } - @ExtApiFn(name = "<校验>夹住试管", group = "校验.夹爪", order = 205) - public void gripperSVClampTube() throws AppException { - miniServoDriver.miniServoEnable(MiniServoMId.ShakeModGripperSV, 1); - tubePreProcesModuleExDriver.gripperSVClampTube(); + @ExtApiFn(name = "标定<摇匀>位置", group = "扩展标定", order = 202) + public Object calibrateCurPosAsShakePos() throws AppException { + // + //1. 读取Y位置 + Integer ySVPos = miniServoDriver.miniServoReadPos(MiniServoMId.ShakeModGripperYSV); + //2. 试管夹具张开一点 + stepMotorCtrlDriver.stepMotorEasyMoveByBlock(StepMotorMId.ShakeModClampingM, 10, overtime); + //3. Z轴归零,并读取当前位置 + Integer zpos = stepMotorCtrlDriver.stepMotorReadPosByMoveToZeroBlock(StepMotorMId.ShakeModGripperZM, 10000); + //4. 夹具归零并读取位置 + Integer clampPos = readShakeModClampingMPos(); + clampPos = clampPos - 10 - 2; + + posMgr.setPos(TubePreProcessZAxisPos.ZMotorShakeTubePos, zpos); + posMgr.setPos(TubePreProcessTubeClamp.ShakeClampMotorClampPos, clampPos); + posMgr.setPos(TubePreProcessYPos.YServoShakePos, ySVPos); + + var obNode = ZJsonHelper.createObjectNode(); + obNode.put("ySVPos", ySVPos); + obNode.put("zMpos", zpos); + obNode.put("clampPos", clampPos); + return obNode; } + // - //YSV : 设置参考点,标定,验证 + // 夹爪标定,校准,校验 // - @ExtApiFn(name = "<校验>移动到摇匀位", group = "校验.YSV", order = 305) - public void YAxixServoShake() throws AppException { - miniServoDriver.miniServoEnable(MiniServoMId.ShakeModGripperYSV, 1); - tubePreProcesModuleExDriver.YSVMoveToShakePos(); - } + // @ExtApiFn(name = "<校验>张开", group = "校验.夹爪", order = 306) + // public void gripperSVOpen() throws AppException { + // miniServoDriver.miniServoEnable(MiniServoMId.ShakeModGripperSV, 1); + // tubePreProcesModuleExDriver.gripperSVOpen(); + // } + // + // @ExtApiFn(name = "<校验>夹住试管帽", group = "校验.夹爪", order = 305) + // public void gripperSVClampTube() throws AppException { + // miniServoDriver.miniServoEnable(MiniServoMId.ShakeModGripperSV, 1); + // tubePreProcesModuleExDriver.gripperSVClampTube(); + // } - @ExtApiFn(name = "<校验>移动到取试管位", group = "校验.YSV", order = 306) - public void YAxixServoTakeTube() throws AppException { - miniServoDriver.miniServoEnable(MiniServoMId.ShakeModGripperYSV, 1); - tubePreProcesModuleExDriver.YSVMoveToTakeTubePos(); - } - @ExtApiFn(name = "<校验>移动到待机位", group = "校验.YSV", order = 307) - public void YAxixServoMoveToStandyPos() throws AppException { - miniServoDriver.miniServoEnable(MiniServoMId.ShakeModGripperYSV, 1); - tubePreProcesModuleExDriver.YSVMoveToStandyPos(); - } + // + //YSV : 设置参考点,标定,验证 + // + // @ExtApiFn(name = "<校验>移动到摇匀位", group = "校验.YSV", order = 405) + // public void YAxixServoShake() throws AppException { + // miniServoDriver.miniServoEnable(MiniServoMId.ShakeModGripperYSV, 1); + // tubePreProcesModuleExDriver.YSVMoveToShakePos(); + // } + // + // @ExtApiFn(name = "<校验>移动到取试管位", group = "校验.YSV", order = 406) + // public void YAxixServoTakeTube() throws AppException { + // miniServoDriver.miniServoEnable(MiniServoMId.ShakeModGripperYSV, 1); + // tubePreProcesModuleExDriver.YSVMoveToTakeTubePos(); + // } + // + // @ExtApiFn(name = "<校验>移动到待机位", group = "校验.YSV", order = 407) + // public void YAxixServoMoveToStandyPos() throws AppException { + // miniServoDriver.miniServoEnable(MiniServoMId.ShakeModGripperYSV, 1); + // tubePreProcesModuleExDriver.YSVMoveToStandyPos(); + // } // //ZM : 标定,验证 // - @ExtApiFn(name = "<校验>取试管", group = "校验.ZM", order = 405) - public void takeTube(Boolean isHTube) throws AppException { - enableModule(); - tubePreProcesModuleExDriver.takeTubeFromTubeholder(isHTube); - } - - @ExtApiFn(name = "<校验>放试管", group = "校验.ZM", order = 406) - public void putTube(Boolean isHTube) throws AppException { - enableModule(); - tubePreProcesModuleExDriver.putTubeToTubeholder(isHTube); - } - - @ExtApiFn(name = "<校验>Z轴移动到取试管位置", group = "校验.ZM", order = 407) - public void zMotorMoveToTakeHTubePos(Boolean isHTube) throws AppException { - enableModule(); - stepMotorCtrlDriver.stepMotorEasyMoveToZeroBlock(StepMotorMId.ShakeModGripperZM, overtime); - tubePreProcesModuleExDriver.zMotorMoveToTakeHTubePos(isHTube); - } - - @ExtApiFn(name = "<校验>Z轴移动到摇匀位置", group = "校验.ZM", order = 408) - public void zMotorMoveToShakeTubePos() throws AppException { - enableModule(); - stepMotorCtrlDriver.stepMotorEasyMoveToZeroBlock(StepMotorMId.ShakeModGripperZM, overtime); - tubePreProcesModuleExDriver.zMotorMoveToShakeTubePos(); - } - - @ExtApiFn(name = "<校验>夹紧", group = "校验.夹紧", order = 503) - - public void clampTube() throws AppException { - tubePreProcesModuleExDriver.clampingMclampTube(); - } + // @ExtApiFn(name = "<校验>取试管", group = "校验.ZM", order = 505) + // public void takeTube(Boolean isHTube) throws AppException { + // enableModule(); + // tubePreProcesModuleExDriver.takeTubeFromTubeholder(isHTube); + // } + // + // @ExtApiFn(name = "<校验>放试管", group = "校验.ZM", order = 506) + // public void putTube(Boolean isHTube) throws AppException { + // enableModule(); + // tubePreProcesModuleExDriver.putTubeToTubeholder(isHTube); + // } + // + // @ExtApiFn(name = "<校验>Z轴移动到取试管位置", group = "校验.ZM", order = 507) + // public void zMotorMoveToTakeHTubePos(Boolean isHTube) throws AppException { + // enableModule(); + // stepMotorCtrlDriver.stepMotorEasyMoveToZeroBlock(StepMotorMId.ShakeModGripperZM, overtime); + // tubePreProcesModuleExDriver.zMotorMoveToTakeHTubePos(isHTube); + // } + // + // @ExtApiFn(name = "<校验>Z轴移动到摇匀位置", group = "校验.ZM", order = 508) + // public void zMotorMoveToShakeTubePos() throws AppException { + // enableModule(); + // stepMotorCtrlDriver.stepMotorEasyMoveToZeroBlock(StepMotorMId.ShakeModGripperZM, overtime); + // tubePreProcesModuleExDriver.zMotorMoveToShakeTubePos(); + // } - @ExtApiFn(name = "<校验>释放", group = "校验.夹紧", order = 504) - public void unclampTube() throws AppException { - tubePreProcesModuleExDriver.clampingMReleaseTube(); - } - @ExtApiFn(name = "<校验>全部流程", group = "校验.全部", order = 600) + @ExtApiFn(name = "<校验>全部流程", group = "校验.全部", order = 700) public void testAll(Boolean isHTube) throws AppException { + deviceReset(); controler.takeTubeFromTubeholderToShakePos(isHTube); controler.shakeTube(45, 5); controler.takeTubeCap(isHTube); controler.putbakTubeCapAndPutbakTubeToTubeHolder(isHTube); + tubePreProcesModuleExDriver.clampingMReleaseTubeInFuzzyPos(); + disableModule(); + } } diff --git a/src/main/java/a8k/service/app/devicectrl/param/param_mgr/HbotTipPosMgr.java b/src/main/java/a8k/service/app/devicectrl/param/param_mgr/HbotTipPosMgr.java index aa1b996..b6413bd 100644 --- a/src/main/java/a8k/service/app/devicectrl/param/param_mgr/HbotTipPosMgr.java +++ b/src/main/java/a8k/service/app/devicectrl/param/param_mgr/HbotTipPosMgr.java @@ -2,6 +2,7 @@ package a8k.service.app.devicectrl.param.param_mgr; import a8k.service.app.devicectrl.param.param_mgr.base.ParamMgr; import a8k.service.app.devicectrl.param.type.HbotTipPosParam; +import a8k.type.TipPosConfig; import a8k.type.cfg.Pos3d; import a8k.type.type.TipGroup; import jakarta.annotation.PostConstruct; @@ -18,7 +19,6 @@ public class HbotTipPosMgr extends ParamMgr { static final Logger logger = LoggerFactory.getLogger(HbotTipPosMgr.class); - @PostConstruct void initialize() { for (HbotTipPosParam param : HbotTipPosParam.values()) { @@ -35,6 +35,9 @@ public class HbotTipPosMgr extends ParamMgr { HbotTipPosParam tip000Pos = null; HbotTipPosParam tipDxPos = null; HbotTipPosParam tipDyPos = null; + if(tip000 == null) tip000 = new Pos3d(0, 0, 0); + if(dx == null) dx = 0.0; + if(dy == null) dy = 0.0; if (tipGroup == TipGroup.GROUP0) { tip000Pos = HbotTipPosParam.TipGroup0_000Pos; @@ -43,7 +46,7 @@ public class HbotTipPosMgr extends ParamMgr { } else if (tipGroup == TipGroup.GROUP1) { tip000Pos = HbotTipPosParam.TipGroup1_000Pos; tipDxPos = HbotTipPosParam.TipGroup1_SpaceingX; - tipDyPos = HbotTipPosParam.TipGroup2_SpaceingY; + tipDyPos = HbotTipPosParam.TipGroup1_SpaceingY; } else if (tipGroup == TipGroup.GROUP2) { tip000Pos = HbotTipPosParam.TipGroup2_000Pos; tipDxPos = HbotTipPosParam.TipGroup2_SpaceingX; @@ -57,7 +60,11 @@ public class HbotTipPosMgr extends ParamMgr { setParam(tipDyPos, dy); } - public Pos3d getTipPos(TipGroup tipGroup, Integer tipoff) { + public void setTipPosCfg(TipGroup tipGroup, TipPosConfig cfg) { + setTipGroupParam(tipGroup, cfg.tip000, cfg.spaceingX, cfg.spaceingY); + } + + public TipPosConfig getTipPosCfg(TipGroup tipGroup) { Pos3d tip000 = null; Double dx = 0.0; Double dy = 0.0; @@ -70,32 +77,48 @@ public class HbotTipPosMgr extends ParamMgr { } else if (tipGroup == TipGroup.GROUP1) { tip000 = getParam(HbotTipPosParam.TipGroup1_000Pos, Pos3d.class); dx = getParam(HbotTipPosParam.TipGroup1_SpaceingX, Double.class); - dy = getParam(HbotTipPosParam.TipGroup2_SpaceingY, Double.class); + dy = getParam(HbotTipPosParam.TipGroup1_SpaceingY, Double.class); } else if (tipGroup == TipGroup.GROUP2) { tip000 = getParam(HbotTipPosParam.TipGroup2_000Pos, Pos3d.class); dx = getParam(HbotTipPosParam.TipGroup2_SpaceingX, Double.class); dy = getParam(HbotTipPosParam.TipGroup2_SpaceingY, Double.class); } - Assert.isTrue(tip000 != null, "tip000 != null"); - Assert.isTrue(dx != null, "dx != null"); - Assert.isTrue(dy != null, "dy != null"); + + TipPosConfig cfg = new TipPosConfig(); + if (tip000 == null) { + tip000 = new Pos3d(0, 0, 0); + } + cfg.tip000 = tip000; + cfg.spaceingX = dx; + cfg.spaceingY = dy; + cfg.tipGroup = tipGroup; + return cfg; + } + + + public Pos3d getTipPos(TipGroup tipGroup, Integer tipoff) { + TipPosConfig cfg = getTipPosCfg(tipGroup); + + Assert.isTrue(cfg.tip000 != null, "tip000 != null"); + Assert.isTrue(cfg.spaceingX != null, "dx != null"); + Assert.isTrue(cfg.spaceingY != null, "dy != null"); int xoff = tipoff % 12; int yoff = tipoff / 12; - double x = tip000.x + xoff * dx; - double y = tip000.y + yoff * dy; - double z = tip000.z; + double x = cfg.tip000.x + xoff * cfg.spaceingX; + double y = cfg.tip000.y + yoff * cfg.spaceingY; + double z = cfg.tip000.z; return new Pos3d((int) x, (int) y, (int) z); } - public void setDropTipPos(Pos3d pos){ + public void setDropTipPos(Pos3d pos) { setParam(HbotTipPosParam.DropTipPos, pos); } - public Pos3d getDropTipPos(){ + public Pos3d getDropTipPos() { return getParam(HbotTipPosParam.DropTipPos, Pos3d.class); } } diff --git a/src/main/java/a8k/service/app/devicectrl/param/param_mgr/OptModuleExtParamsMgr.java b/src/main/java/a8k/service/app/devicectrl/param/param_mgr/OptModuleExtParamsMgr.java new file mode 100644 index 0000000..59d1ae3 --- /dev/null +++ b/src/main/java/a8k/service/app/devicectrl/param/param_mgr/OptModuleExtParamsMgr.java @@ -0,0 +1,59 @@ +package a8k.service.app.devicectrl.param.param_mgr; + + +import a8k.service.app.devicectrl.param.param_mgr.base.ParamMgr; +import a8k.service.app.devicectrl.param.type.OptModuleExtParam; +import a8k.service.app.devicectrl.param.type.OptModuleExtParam; +import a8k.service.db.type.a8kidcard.zenum.A8kOptType; +import jakarta.annotation.PostConstruct; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +/** + * HBOT二维码扫描坐标参数 + */ +@Component +public class OptModuleExtParamsMgr extends ParamMgr { + static final Logger logger = LoggerFactory.getLogger(OptModuleExtParamsMgr.class); + + + @PostConstruct + void initialize() { + for (OptModuleExtParam pos : OptModuleExtParam.values()) { + setParamChName(pos, pos.chName); + } + } + + public void setOptParam(OptModuleExtParam pos, Object value) { + setParam(pos, value); + } + + public Integer getOptScanStartPos(A8kOptType type) { + Integer shift = switch (type) { + case TOPT -> getParam(OptModuleExtParam.TOptScanShift, Integer.class); + case FOPT -> getParam(OptModuleExtParam.FOptScanShift, Integer.class); + }; + + Integer scanStartPos = getParam(OptModuleExtParam.OptScanRefPos, Integer.class); + scanStartPos = scanStartPos + shift; + + return scanStartPos; + } + + public Double getScanGain(A8kOptType type) { + return switch (type) { + case TOPT -> getParam(OptModuleExtParam.TOptScanGainVal, Double.class); + case FOPT -> getParam(OptModuleExtParam.FOptScanGainVal, Double.class); + }; + } + + public Integer getOptEmissionIntensity(A8kOptType type) { + return switch (type) { + case TOPT -> getParam(OptModuleExtParam.TOptEmissionIntensity, Integer.class); + case FOPT -> getParam(OptModuleExtParam.FOptEmissionIntensity, Integer.class); + }; + } + +} + 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 bbd8b68..490cfca 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 @@ -30,8 +30,7 @@ public class OptModuleParamsMgr extends ParamMgr { setParam(OptModuleParam.OptScanerDropPos, -349); setParam(OptModuleParam.OptScanerScandbyPos, 305); setParam(OptModuleParam.OptScanerScandbyPos, 4000); - setParam(OptModuleParam.TOptScanShift, 277); - setParam(OptModuleParam.FOptScanShift, 1441); + } @@ -40,59 +39,6 @@ public class OptModuleParamsMgr extends ParamMgr { } - // public void setPullerTargetPos(Integer pos) { - // setParam(OptModuleParam.PullerTargetPos, pos); - // } - // - // public void setOptScanerDropPos(Integer pos) { - // setParam(OptModuleParam.OptScanerDropPos, pos); - // } - // - // public void setOptScanerScandbyPos(Integer pos) { - // setParam(OptModuleParam.OptScanerScandbyPos, pos); - // } - // - // - // public void setOptScanRefPos(Integer pos) { - // setParam(OptModuleParam.OptScanRefPos, pos); - // } - // - // public void setTOptScanShift(Integer pos) { - // setParam(OptModuleParam.TOptScanShift, pos); - // } - // - // public void setFOptScanShift(Integer pos) { - // setParam(OptModuleParam.FOptScanShift, pos); - // } - - - public Integer getOptScanStartPos(A8kOptType type) { - Integer shift = switch (type) { - case TOPT -> getParam(OptModuleParam.TOptScanShift, Integer.class); - case FOPT -> getParam(OptModuleParam.FOptScanShift, Integer.class); - }; - - Integer scanStartPos = getParam(OptModuleParam.OptScanRefPos, Integer.class); - scanStartPos = scanStartPos + shift; - - return scanStartPos; - } - - public Double getScanGain(A8kOptType type) { - return switch (type) { - case TOPT -> getParam(OptModuleParam.TOptScanGainVal, Double.class); - case FOPT -> getParam(OptModuleParam.FOptScanGainVal, Double.class); - }; - } - - public Integer getOptEmissionIntensity(A8kOptType type) { - return switch (type) { - case TOPT -> getParam(OptModuleParam.TOptEmissionIntensity, Integer.class); - case FOPT -> getParam(OptModuleParam.FOptEmissionIntensity, Integer.class); - }; - } - - public Integer getPullerTargetPos() { return getParam(OptModuleParam.PullerTargetPos, Integer.class); } diff --git a/src/main/java/a8k/service/app/devicectrl/param/param_mgr/TemperatureCtrlParamMgr.java b/src/main/java/a8k/service/app/devicectrl/param/param_mgr/TemperatureCtrlParamMgr.java index 4e41b69..c75f8d8 100644 --- a/src/main/java/a8k/service/app/devicectrl/param/param_mgr/TemperatureCtrlParamMgr.java +++ b/src/main/java/a8k/service/app/devicectrl/param/param_mgr/TemperatureCtrlParamMgr.java @@ -26,7 +26,13 @@ public class TemperatureCtrlParamMgr extends ParamMgr { } public Double getParam(TemperatureCtrlParam pos) { - return super.getParam(pos, Double.class); + Double obj = super.getParam(pos, Double.class); + if (obj == null) { + return switch (pos) { + case IncubatorTCMTempOffset, PlatesBoxTCMTempOffset -> 0.0; + }; + } + return obj; } } diff --git a/src/main/java/a8k/service/app/devicectrl/param/param_mgr/TubePreProcesPosParamMgr.java b/src/main/java/a8k/service/app/devicectrl/param/param_mgr/TubePreProcesPosParamMgr.java index 70c41c7..bef997b 100644 --- a/src/main/java/a8k/service/app/devicectrl/param/param_mgr/TubePreProcesPosParamMgr.java +++ b/src/main/java/a8k/service/app/devicectrl/param/param_mgr/TubePreProcesPosParamMgr.java @@ -4,7 +4,7 @@ import a8k.service.app.devicectrl.param.param_mgr.base.ParamMgr; import a8k.type.TubePreProcessGripperPos; import a8k.type.TubePreProcessTubeClamp; import a8k.type.TubePreProcessYPos; -import a8k.type.TubePreProcessZAxisPos; +import a8k.service.app.devicectrl.param.type.TubePreProcessZAxisPos; import jakarta.annotation.PostConstruct; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -13,6 +13,7 @@ import org.springframework.stereotype.Component; @Component public class TubePreProcesPosParamMgr extends ParamMgr { static final Logger logger = LoggerFactory.getLogger(TubeFeedingModuleParamMgr.class); + @PostConstruct void initialize() { for (var pos : TubePreProcessGripperPos.values()) { @@ -52,8 +53,6 @@ public class TubePreProcesPosParamMgr extends ParamMgr { public Integer getGripperServoOpenPos() {return getParam(TubePreProcessGripperPos.GripperServoOpenPos);} - public Integer getGripperServoClosePos() {return getParam(TubePreProcessGripperPos.GripperServoClosePos);} - public Integer getGripperServoTakeCapPos() {return getParam(TubePreProcessGripperPos.GripperServoTakeCapPos);} public Integer getYServoTakeTubePos() {return getParam(TubePreProcessYPos.YServoTakeTubePos);} @@ -70,7 +69,7 @@ public class TubePreProcesPosParamMgr extends ParamMgr { public Integer getZMotorShakeTubePos() {return getParam(TubePreProcessZAxisPos.ZMotorShakeTubePos);} - public Integer getZMotorPutCapPos() {return getParam(TubePreProcessZAxisPos.ZMotorPutTubeCapPos);} + public Integer getZMotorPutCapPos() {return getParam(TubePreProcessZAxisPos.ZMotorShakeTubePos) + getParam(TubePreProcessGripperPos.GripperRedundancyHeight);} public Integer getShakeClampMotorClampPos() {return getParam(TubePreProcessTubeClamp.ShakeClampMotorClampPos);} diff --git a/src/main/java/a8k/service/app/devicectrl/param/type/OptModuleExtParam.java b/src/main/java/a8k/service/app/devicectrl/param/type/OptModuleExtParam.java new file mode 100644 index 0000000..ea210cf --- /dev/null +++ b/src/main/java/a8k/service/app/devicectrl/param/type/OptModuleExtParam.java @@ -0,0 +1,20 @@ +package a8k.service.app.devicectrl.param.type; + +public enum OptModuleExtParam { + OptScanRefPos("光学扫描参考坐标"), + + FOptScanShift("F光学扫描偏移"), + FOptEmissionIntensity("F发射强度"),//Int + FOptScanGainVal("F光学扫描放大倍数"),//Double + + TOptScanShift("T光学扫描偏移"), + TOptEmissionIntensity("T发射强度"), + TOptScanGainVal("T光学扫描放大倍数"), + ; + + public final String chName; + + OptModuleExtParam(String chName) { + this.chName = chName; + } +} diff --git a/src/main/java/a8k/service/app/devicectrl/param/type/OptModuleParam.java b/src/main/java/a8k/service/app/devicectrl/param/type/OptModuleParam.java index 453761d..6e48399 100644 --- a/src/main/java/a8k/service/app/devicectrl/param/type/OptModuleParam.java +++ b/src/main/java/a8k/service/app/devicectrl/param/type/OptModuleParam.java @@ -4,17 +4,7 @@ public enum OptModuleParam { PullerTargetPos("拉板目标位置"), OptScanerDropPos("丢板坐标"), OptScanerScandbyPos("扫描待机位"), - OptScanRefPos("光学扫描参考坐标"), - - FOptScanShift("F光学扫描偏移"), - FOptEmissionIntensity("F发射强度"),//Int - FOptScanGainVal("F光学扫描放大倍数"),//Double - - TOptScanShift("T光学扫描偏移"), - TOptEmissionIntensity("T发射强度"), - TOptScanGainVal("T光学扫描放大倍数"), ; - public final String chName; OptModuleParam(String chName) { diff --git a/src/main/java/a8k/service/app/devicectrl/param/type/TubePrePorcessStructConstant.java b/src/main/java/a8k/service/app/devicectrl/param/type/TubePrePorcessStructConstant.java new file mode 100644 index 0000000..b5402ea --- /dev/null +++ b/src/main/java/a8k/service/app/devicectrl/param/type/TubePrePorcessStructConstant.java @@ -0,0 +1 @@ +package a8k.service.app.devicectrl.param.type; diff --git a/src/main/java/a8k/service/app/devicectrl/param/type/TubePreProcessZAxisPos.java b/src/main/java/a8k/service/app/devicectrl/param/type/TubePreProcessZAxisPos.java new file mode 100644 index 0000000..80a8821 --- /dev/null +++ b/src/main/java/a8k/service/app/devicectrl/param/type/TubePreProcessZAxisPos.java @@ -0,0 +1,12 @@ +package a8k.service.app.devicectrl.param.type; + +public enum TubePreProcessZAxisPos { + ZMotorTakeHTubePos("取高试管位置"),// + ZMotorTakeSTubePos("取低试管位置"),// + ZMotorShakeTubePos("摇匀放置位置"),// + ; + public final String chName; + TubePreProcessZAxisPos(String chName) { + this.chName = chName; + } +} diff --git a/src/main/java/a8k/type/TipPosConfig.java b/src/main/java/a8k/type/TipPosConfig.java new file mode 100644 index 0000000..7baf628 --- /dev/null +++ b/src/main/java/a8k/type/TipPosConfig.java @@ -0,0 +1,11 @@ +package a8k.type; + +import a8k.type.cfg.Pos3d; +import a8k.type.type.TipGroup; + +public class TipPosConfig { + public TipGroup tipGroup; + public Pos3d tip000; + public Double spaceingX; + public Double spaceingY; +} diff --git a/src/main/java/a8k/type/TubePreProcessGripperPos.java b/src/main/java/a8k/type/TubePreProcessGripperPos.java index 39102dc..d4b554e 100644 --- a/src/main/java/a8k/type/TubePreProcessGripperPos.java +++ b/src/main/java/a8k/type/TubePreProcessGripperPos.java @@ -2,8 +2,8 @@ package a8k.type; public enum TubePreProcessGripperPos { GripperServoOpenPos("<抓手>张开位置"),// - GripperServoClosePos("<抓手>闭合位置"),// GripperServoTakeCapPos("<抓手>取试管位置"),// + GripperRedundancyHeight("<抓手>冗余高度"),// ; public final String chName; diff --git a/src/main/java/a8k/type/TubePreProcessZAxisPos.java b/src/main/java/a8k/type/TubePreProcessZAxisPos.java deleted file mode 100644 index 3157e12..0000000 --- a/src/main/java/a8k/type/TubePreProcessZAxisPos.java +++ /dev/null @@ -1,13 +0,0 @@ -package a8k.type; - -public enum TubePreProcessZAxisPos { - ZMotorTakeHTubePos("取高试管位置"),// - ZMotorTakeSTubePos("取低试管位置"),// - ZMotorShakeTubePos("摇匀放置位置"),// - ZMotorPutTubeCapPos("盖帽位置"),// - ; - public final String chName; - TubePreProcessZAxisPos(String chName) { - this.chName = chName; - } -} diff --git a/src/main/java/a8k/utils/ZJsonHelper.java b/src/main/java/a8k/utils/ZJsonHelper.java index ca83a14..1c908a9 100644 --- a/src/main/java/a8k/utils/ZJsonHelper.java +++ b/src/main/java/a8k/utils/ZJsonHelper.java @@ -22,20 +22,34 @@ public class ZJsonHelper { public static T objectFromJson(ObjectNode node, Class tClass) { ObjectMapper mapper = new ObjectMapper(); + if(node == null) { + return null; + } + if (tClass.getTypeName().equals(Integer.class.getTypeName())) { + if (node.get("value") == null) + return null; return (T) Integer.valueOf(node.get("value").asInt()); } if (tClass.getTypeName().equals(String.class.getTypeName())) { + if (node.get("value") == null) + return null; return (T) node.get("value").asText(); } if (tClass.getTypeName().equals(Boolean.class.getTypeName())) { + if (node.get("value") == null) + return null; return (T) Boolean.valueOf(node.get("value").asBoolean()); } if (tClass.getTypeName().equals(Double.class.getTypeName())) { + if (node.get("value") == null) + return null; return (T) Double.valueOf(node.get("value").asDouble()); } if (tClass.getTypeName().equals(Float.class.getTypeName())) { + if (node.get("value") == null) + return null; return (T) Float.valueOf(node.get("value").floatValue()); } diff --git a/src/main/resources/app.db b/src/main/resources/app.db new file mode 100644 index 0000000000000000000000000000000000000000..0429c62b75ba4c3bb6b1eb9128dbb06ae6dd408f GIT binary patch literal 225280 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 eKmter2_OL^fCP{L5