diff --git a/appresource/db/app.db b/appresource/db/app.db index 2ba9267..af69001 100644 Binary files a/appresource/db/app.db and b/appresource/db/app.db differ diff --git a/doc/a8k移液泵优化方案.md b/doc/a8k移液泵优化方案.md index 59007fb..9ad25c8 100644 --- a/doc/a8k移液泵优化方案.md +++ b/doc/a8k移液泵优化方案.md @@ -8,4 +8,14 @@ TODO: lld启动时,先不移动步进电机,先读取压力值,如果压力值大于记录值,说明有液体 否则,移动步进电机,直到压力值大于记录值 +``` + +```angular2html + +1. 将液面探测做到最佳 + + + + + ``` \ No newline at end of file diff --git a/src/main/java/a8k/controler/api/v1/app/ws/AppWebSocketEndpointMgr.java b/src/main/java/a8k/controler/api/v1/app/ws/AppWebSocketEndpointMgr.java index 8cc2953..04a0219 100644 --- a/src/main/java/a8k/controler/api/v1/app/ws/AppWebSocketEndpointMgr.java +++ b/src/main/java/a8k/controler/api/v1/app/ws/AppWebSocketEndpointMgr.java @@ -1,25 +1,28 @@ package a8k.controler.api.v1.app.ws; import a8k.service.app.appstate.GStateService; -import a8k.service.app.appstate.statemgr.DeviceWorkStateMgrService; -import a8k.service.app.appstate.statemgr.IncubationPlateStateMgrService; -import a8k.service.app.appstate.statemgr.OptScanModuleStateMgrService; -import a8k.service.app.appstate.statemgr.TubeStateMgrService; +import a8k.service.app.appstate.statemgr.*; import a8k.service.bases.FrontEndEventRouter; import a8k.utils.ZJsonHelper; import jakarta.annotation.PostConstruct; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import jakarta.annotation.Resource; import jakarta.websocket.*; +import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.Future; @Component @EnableScheduling public class AppWebSocketEndpointMgr { + private static final Logger log = LoggerFactory.getLogger(AppWebSocketEndpointMgr.class); + public static class Report { public String messageType = "Report"; public String dataType; @@ -45,6 +48,8 @@ public class AppWebSocketEndpointMgr { IncubationPlateStateMgrService incubationPlateStateMgrService; @Resource OptScanModuleStateMgrService optScanModuleStateMgrService; + @Resource + ConsumablesMgrService consumablesMgrService; List stateWebsocketSessions = new ArrayList<>(); @@ -70,13 +75,21 @@ public class AppWebSocketEndpointMgr { synchronized void broadcastState(String message) { for (Session session : stateWebsocketSessions) { - session.getAsyncRemote().sendText(message); + try { + session.getBasicRemote().sendText(message); + } catch (IOException e) { + log.warn("broadcastState: session.getBasicRemote().sendText() failed: {}", e.getMessage()); + } } } synchronized void broadcastEvent(String message) { for (Session session : eventWebsocketSessions) { - session.getAsyncRemote().sendText(message); + try { + session.getBasicRemote().sendText(message); + } catch (IOException e) { + log.warn("broadcastEvent: session.getBasicRemote().sendText() failed: {}", e.getMessage()); + } } } @@ -115,6 +128,7 @@ public class AppWebSocketEndpointMgr { reportState("OptScanModuleState", optScanModuleStateMgrService.getOptScanModule()); reportState("EmergencyPosState", tubeStateMgrService.getEmergencyPosRunState()); reportState("SensorState", gstate.getSensorState()); + reportState("ConsumablesStateService", consumablesMgrService.getState()); } diff --git a/src/main/java/a8k/hardware/A8kModParamInitializer.java b/src/main/java/a8k/hardware/A8kModParamInitializer.java index 2363441..7f680f3 100644 --- a/src/main/java/a8k/hardware/A8kModParamInitializer.java +++ b/src/main/java/a8k/hardware/A8kModParamInitializer.java @@ -113,7 +113,7 @@ public class A8kModParamInitializer { pipetteCtrlDriver.setReg(PipetteRegIndex.kreg_pipette_zm_default_velocity, 1500); - pipetteCtrlDriver.setReg(PipetteRegIndex.kreg_pipette_lld_motor_vel_rpm, 100);//80的时候,刚好和液面齐平 +// pipetteCtrlDriver.setReg(PipetteRegIndex.kreg_pipette_lld_motor_vel_rpm, 100);//80的时候,刚好和液面齐平 canBus.moduleSetReg(MId.HbotM, RegIndex.kreg_xyrobot_look_zero_edge_speed, 10); diff --git a/src/main/java/a8k/hardware/type/a8kcanprotocol/CmdId.java b/src/main/java/a8k/hardware/type/a8kcanprotocol/CmdId.java index 8ecb913..689ada8 100644 --- a/src/main/java/a8k/hardware/type/a8kcanprotocol/CmdId.java +++ b/src/main/java/a8k/hardware/type/a8kcanprotocol/CmdId.java @@ -116,6 +116,18 @@ public enum CmdId { pipette_zmotor_move_by(0x7405, "pipette_zmotor_move_by"), pipette_zmotor_move_to(0x7406, "pipette_zmotor_move_to"), + // virtual int32_t liquid_operation_clear_params(); 0x7450 + // virtual int32_t liquid_operation_set_gun_runparams(int32_t acc, int32_t dec, int32_t vstart, int32_t vstop, int32_t vmax); 0x7451 + // virtual int32_t liquid_operation_set_zmotor_runparams(int32_t posmin, int32_t posmax, int32_t vmax); 0x7452 + // virtual int32_t liquid_operation_enable_lld_record(); 0x7453 + // virtual int32_t liquid_operation_fresh_params(); 0x7454 + + liquid_operation_clear_params(0x7450, "liquid_operation_clear_params"), + liquid_operation_set_gun_runparams(0x7451, "liquid_operation_set_gun_runparams"), + liquid_operation_set_zmotor_runparams(0x7452, "liquid_operation_set_zmotor_runparams"), + liquid_operation_enable_lld_record(0x7453, "liquid_operation_enable_lld_record"), + liquid_operation_fresh_params(0x7454, "liquid_operation_fresh_params"), + pipette_init_device(0x7501, "pipette_init_device"), pipette_put_tip(0x7502, "pipette_put_tip"), pipette_pump_move_to(0x7503, "pipette_pump_move_to"), diff --git a/src/main/java/a8k/hardware/type/regindex/RegIndex.java b/src/main/java/a8k/hardware/type/regindex/RegIndex.java index 279adf6..ed4ebba 100644 --- a/src/main/java/a8k/hardware/type/regindex/RegIndex.java +++ b/src/main/java/a8k/hardware/type/regindex/RegIndex.java @@ -40,17 +40,17 @@ public enum RegIndex { kreg_pipette_tip_state(4002, false), // 移动液枪tip状态 // kreg_pipette_limit_ul(4051), // - kreg_pipette_pump_acc(4052), // - kreg_pipette_pump_dec(4053), // - kreg_pipette_pump_vstart(4054), // - kreg_pipette_pump_vstop(4055), // - kreg_pipette_pump_vmax(4056), // - kreg_pipette_aspirate_distribut_pump_vel(4057), // - kreg_pipette_lld_pump_vel(4058), // - kreg_pipette_lld_motor_vel_rpm(4059), // - kreg_pipette_lld_detect_period_ms(4060), // - kreg_pipette_lld_prepare_pos(4061), // - kreg_pipette_lld_prepare_distribut_pos(4062), // +// kreg_pipette_pump_acc(4052), // +// kreg_pipette_pump_dec(4053), // +// kreg_pipette_pump_vstart(4054), // +// kreg_pipette_pump_vstop(4055), // +// kreg_pipette_pump_vmax(4056), // +// kreg_pipette_aspirate_distribut_pump_vel(4057), // +// kreg_pipette_lld_pump_vel(4058), // +// kreg_pipette_lld_motor_vel_rpm(4059), // +// kreg_pipette_lld_detect_period_ms(4060), // +// kreg_pipette_lld_prepare_pos(4061), // +// kreg_pipette_lld_prepare_distribut_pos(4062), // kreg_pipette_zm_pos(4101), kreg_pipette_zm_is_enable(4102), diff --git a/src/main/java/a8k/service/app/appctrl/mainflowctrl/action/SEQ5_PROCESS.java b/src/main/java/a8k/service/app/appctrl/mainflowctrl/action/SEQ5_PROCESS.java index 71c39b1..2146984 100644 --- a/src/main/java/a8k/service/app/appctrl/mainflowctrl/action/SEQ5_PROCESS.java +++ b/src/main/java/a8k/service/app/appctrl/mainflowctrl/action/SEQ5_PROCESS.java @@ -348,13 +348,13 @@ public class SEQ5_PROCESS extends A8kStepAction { log.info(" FlowType2->移动到大缓冲液取液位 {}", consumableGroup); hbotCtrlService.moveToLargeBSSamplePos(consumableGroup);//移动到取样位置 log.info(" FlowType2->液面探测准备"); - pipeGunCtrlScripter.lld(PipetteGunBindActionType.TAKE_LARGE_BUFFER_SOLUTION, cxt); //优化这个方法的接口,尽量去除掉cxt +// pipeGunCtrlScripter.lld(PipetteGunBindActionType.TAKE_LARGE_BUFFER_SOLUTION, cxt); //优化这个方法的接口,尽量去除掉cxt log.info(" FlowType2->取液 {}", largeBsVolume); - pipeGunCtrlScripter.aspirate(PipetteGunBindActionType.TAKE_LARGE_BUFFER_SOLUTION, cxt, largeBsVolume);//取液 +// pipeGunCtrlScripter.aspirate(PipetteGunBindActionType.TAKE_LARGE_BUFFER_SOLUTION, cxt, largeBsVolume);//取液 log.info(" FlowType2->移动到探测物质吐液位 {}", consumableGroup); hbotCtrlService.moveToProbeSubstanceSamplePos(consumableGroup, consumablePos);//移动到吐液位 log.info(" FlowType2->吐液 {}", largeBsVolume); - pipetteCtrlDriver.pipettePumpMoveTo(PipetteGunConstant.ASPIRATE_PUMP_V, 0);//这个步骤tip头最后是浸没在溶液中的 +// pipetteCtrlDriver.pipettePumpMoveTo(PipetteGunConstant.ASPIRATE_PUMP_V, 0);//这个步骤tip头最后是浸没在溶液中的 log.info(" FlowType2->hbot归零"); hbotCtrlService.quickResetHbot(); } @@ -422,9 +422,9 @@ public class SEQ5_PROCESS extends A8kStepAction { Integer sampleul = ProjProcessContextUtils.getSampleVol(cxt); Integer reactionul = ProjProcessContextUtils.getReactionPlateDropletVolUl(cxt); log.info(" FlowTypeX->吐液 {}", sampleul); - pipetteCtrlDriver.pipettePumpMoveTo(PipetteGunConstant.ASPIRATE_PUMP_V, 0);// +// pipetteCtrlDriver.pipettePumpMoveTo(PipetteGunConstant.ASPIRATE_PUMP_V, 0);// log.info(" FlowTypeX->吸吐混匀 {}ul {} times", reactionul, ProjProcessContextUtils.getBSMixingCnt(cxt)); - pipeGunCtrlScripter.mix(PipetteGunBindActionType.MIX_REACTION_LIQUOR, cxt, sampleul, ProjProcessContextUtils.getBSMixingCnt(cxt)); +// pipeGunCtrlScripter.mix(PipetteGunBindActionType.MIX_REACTION_LIQUOR, cxt, sampleul, ProjProcessContextUtils.getBSMixingCnt(cxt)); } // @@ -435,10 +435,10 @@ public class SEQ5_PROCESS extends A8kStepAction { ) { Integer reactionul = ProjProcessContextUtils.getReactionPlateDropletVolUl(cxt); log.info(" FlowTypeX->吸液 {}", reactionul); - pipetteCtrlDriver.pipetteAspirate(0, 0, PipetteGunConstant.ASPIRATE_PUMP_V, reactionul); +// pipetteCtrlDriver.pipetteAspirate(0, 0, PipetteGunConstant.ASPIRATE_PUMP_V, reactionul); log.info(" FlowTypeX->吐液到反应板"); hbotCtrlService.moveTo(hbotFixedPosParamMgr.getDropLiquidPos()); - pipetteCtrlDriver.pipettePumpMoveTo(PipetteGunConstant.DISTRIBU_ALL_VOL, 0); +// pipetteCtrlDriver.pipettePumpMoveTo(PipetteGunConstant.DISTRIBU_ALL_VOL, 0); pipetteCtrlDriver.pipetteClearHangingLiquid(3); pipetteCtrlDriver.zMotorMoveToZeroPointQuickBlock(); @@ -462,14 +462,14 @@ public class SEQ5_PROCESS extends A8kStepAction { log.info(" -->移动到取样位置 {}", samplePos); hbotCtrlService.moveToSamplePosXY(samplePos); log.info(" -->液面探测"); - pipeGunCtrlScripter.lld(PipetteGunBindActionType.SAMPLE, ctx); +// pipeGunCtrlScripter.lld(PipetteGunBindActionType.SAMPLE, ctx); log.info(" -->取液准备"); if (ProjProcessContextUtils.isDoMixTubeSample(ctx)) { log.info(" -->吸吐混匀 {}", ProjProcessContextUtils.getTubeMixingCount(ctx)); - pipeGunCtrlScripter.mix(PipetteGunBindActionType.MIX_SAMPLE, ctx, sampleul, ProjProcessContextUtils.getTubeMixingCount(ctx)); +// pipeGunCtrlScripter.mix(PipetteGunBindActionType.MIX_SAMPLE, ctx, sampleul, ProjProcessContextUtils.getTubeMixingCount(ctx)); } log.info(" -->取样 {}", sampleul); - pipeGunCtrlScripter.aspirate(PipetteGunBindActionType.SAMPLE, ctx, sampleul); +// pipeGunCtrlScripter.aspirate(PipetteGunBindActionType.SAMPLE, ctx, sampleul); } diff --git a/src/main/java/a8k/service/app/devicectrl/ctrlservice/HbotCtrlService.java b/src/main/java/a8k/service/app/devicectrl/ctrlservice/HbotCtrlService.java index 32aee5b..3180ebf 100644 --- a/src/main/java/a8k/service/app/devicectrl/ctrlservice/HbotCtrlService.java +++ b/src/main/java/a8k/service/app/devicectrl/ctrlservice/HbotCtrlService.java @@ -163,6 +163,13 @@ public class HbotCtrlService { hbotBaseMoveExDriver.hbotMoveTo(toPos); } + + public void moveToLargeBSSamplePosXY(ConsumableGroup group) throws AppException { + Pos3d toPos = hbotConsumableParamMgr.getLargeBufferSamplePos(group); + toPos.z = 0; + hbotBaseMoveExDriver.hbotMoveTo(toPos); + } + public void moveToLargeBSSampleEndPos(ConsumableGroup group) throws AppException { Pos3d toPos = hbotConsumableParamMgr.getLargeBufferSamplePosEnd(group); hbotBaseMoveExDriver.hbotMoveTo(toPos); diff --git a/src/main/java/a8k/service/app/devicectrl/driver/PipetteCtrlDriver.java b/src/main/java/a8k/service/app/devicectrl/driver/PipetteCtrlDriver.java index 4398987..e114f1a 100644 --- a/src/main/java/a8k/service/app/devicectrl/driver/PipetteCtrlDriver.java +++ b/src/main/java/a8k/service/app/devicectrl/driver/PipetteCtrlDriver.java @@ -42,10 +42,6 @@ public class PipetteCtrlDriver { @Resource A8kCanBusService canBusService; - @Setter - @Getter - Double volumeCalibrationCoefficient = 1.0; - final Integer overtime = 10000; static class FnOrder { @@ -60,6 +56,12 @@ public class PipetteCtrlDriver { public static final int initDeviceBlock = 9; public static final int putTipBlock = 11; + public static final int liquidOperationClearParams = 20; + public static final int liquidOperationSetGunRunParams = 21; + public static final int liquidOperationSetZMotorRunParams = 22; + public static final int liquidOperationEnableLldRecord = 23; + public static final int liquidOperationFreshParams = 24; + public static final int getSensorSampleData = 29; public static final int readCapacitance = 30; public static final int pipetteInitDevice = 31; @@ -166,6 +168,31 @@ public class PipetteCtrlDriver { return dataList; } + @ExtApiFn(name = "液体操作.清除参数", order = FnOrder.liquidOperationClearParams) + public void liquidOperationClearParams() throws AppException { + canBusService.callcmd(MId.PipetteMod.toInt(), CmdId.liquid_operation_clear_params.toInt()); + } + + @ExtApiFn(name = "液体操作.设置移液枪运行参数", order = FnOrder.liquidOperationSetGunRunParams) + public void liquidOperationSetGunRunParams(Integer acc, Integer dec, Integer vstart, Integer vstop, Integer vmax) throws AppException { + canBusService.callcmd(MId.PipetteMod.toInt(), CmdId.liquid_operation_set_gun_runparams.toInt(), acc, dec, vstart, vstop, vmax); + } + + @ExtApiFn(name = "液体操作.设置z轴电机运行参数", order = FnOrder.liquidOperationSetZMotorRunParams) + public void liquidOperationSetZMotorRunParams(Integer posmin, Integer posmax, Integer vmax) throws AppException { + canBusService.callcmd(MId.PipetteMod.toInt(), CmdId.liquid_operation_set_zmotor_runparams.toInt(), posmin, posmax, vmax); + } + + @ExtApiFn(name = "液体操作.使能LLD记录", order = FnOrder.liquidOperationEnableLldRecord) + public void liquidOperationEnableLldRecord() throws AppException { + canBusService.callcmd(MId.PipetteMod.toInt(), CmdId.liquid_operation_enable_lld_record.toInt()); + } + + @ExtApiFn(name = "液体操作.刷新参数", order = FnOrder.liquidOperationFreshParams) + public void liquidOperationFreshParams() throws AppException { + canBusService.callcmd(MId.PipetteMod.toInt(), CmdId.liquid_operation_fresh_params.toInt()); + } + @ExtApiFn(name = "LLD.读取电容值", order = FnOrder.readCapacitance) public Integer readCapacitance() throws AppException { return getReg(PipetteRegIndex.kreg_pipette_capactitance_val); @@ -185,36 +212,37 @@ public class PipetteCtrlDriver { } @ExtApiFn(name = "泵移动到", order = FnOrder.pipettePumpMoveTo) - public void pipettePumpMoveTo(Integer pumpv, Integer ul) throws AppException { - double nl = ul * 1000 * volumeCalibrationCoefficient; - canBusService.callcmd(MId.PipetteMod.toInt(), CmdId.pipette_pump_move_to.toInt(), pumpv, (int) nl); + public void pipettePumpMoveTo(Double ul) throws AppException { + double nl = ul * 1000; + canBusService.callcmd(MId.PipetteMod.toInt(), CmdId.pipette_pump_move_to.toInt(), (int) nl); canBusService.waitForMod(MId.PipetteMod, overtime); } + @ExtApiFn(name = "LLD", order = FnOrder.pipetteLld) - public void pipetteLld(LldType lldtype, Integer maxzpos, Integer c_threshold, Integer p_threshold) throws AppException { - canBusService.callcmd(MId.PipetteMod.toInt(), CmdId.pipette_lld.toInt(), lldtype.getIndex(), maxzpos, c_threshold, p_threshold); + public void pipetteLld(LldType lldtype, Integer c_threshold, Integer p_threshold) throws AppException { + canBusService.callcmd(MId.PipetteMod.toInt(), CmdId.pipette_lld.toInt(), lldtype.getIndex(), c_threshold, p_threshold); canBusService.waitForMod(MId.PipetteMod, overtime); } @ExtApiFn(name = "吸液", order = FnOrder.pipetteAspirate) - public void pipetteAspirate(Integer llfrpm, Integer llftpos, Integer pumpv, Integer ul) throws AppException { - double nl = ul * 1000 * volumeCalibrationCoefficient; - canBusService.callcmd(MId.PipetteMod.toInt(), CmdId.pipette_aspirate.toInt(), llfrpm, llftpos, pumpv, (int) nl); + public void pipetteAspirate(Double ul) throws AppException { + double nl = ul * 1000; + canBusService.callcmd(MId.PipetteMod.toInt(), CmdId.pipette_aspirate.toInt(), (int) nl); canBusService.waitForMod(MId.PipetteMod, overtime); } @ExtApiFn(name = "分液", order = FnOrder.pipetteDistribu) - public void pipetteDistribu(Integer llfrpm, Integer pumpv, Integer ul) throws AppException { - double nl = ul * 1000 * volumeCalibrationCoefficient; - canBusService.callcmd(MId.PipetteMod.toInt(), CmdId.pipette_distribu.toInt(), llfrpm, pumpv, (int) nl); + public void pipetteDistribu(Double ul) throws AppException { + double nl = ul * 1000; + canBusService.callcmd(MId.PipetteMod.toInt(), CmdId.pipette_distribu.toInt(), (int) nl); canBusService.waitForMod(MId.PipetteMod, overtime); } @ExtApiFn(name = "振荡", order = FnOrder.pipetteShakeUp) - public void pipetteShakeUp(Integer llfrpm, Integer maxzpos, Integer pumpv, Integer ul, Integer times) throws AppException { - double nl = ul * 1000 * volumeCalibrationCoefficient; - canBusService.callcmd(MId.PipetteMod.toInt(), CmdId.pipette_shake_up.toInt(), llfrpm, maxzpos, pumpv, (int) nl, times); + public void pipetteShakeUp(Double ul, Integer times) throws AppException { + double nl = ul * 1000; + canBusService.callcmd(MId.PipetteMod.toInt(), CmdId.pipette_shake_up.toInt(), (int) nl, times); canBusService.waitForMod(MId.PipetteMod, overtime); } //pipette_clear_hanging_liquid diff --git a/src/main/java/a8k/service/app/devicectrl/driver/type/PipetteRegIndex.java b/src/main/java/a8k/service/app/devicectrl/driver/type/PipetteRegIndex.java index 043b956..3877238 100644 --- a/src/main/java/a8k/service/app/devicectrl/driver/type/PipetteRegIndex.java +++ b/src/main/java/a8k/service/app/devicectrl/driver/type/PipetteRegIndex.java @@ -14,17 +14,17 @@ public enum PipetteRegIndex { kreg_pipette_tip_state(RegIndex.kreg_pipette_tip_state), // 移动液枪tip状态 // kreg_pipette_limit_ul(RegIndex.kreg_pipette_limit_ul), // - kreg_pipette_pump_acc(RegIndex.kreg_pipette_pump_acc), // - kreg_pipette_pump_dec(RegIndex.kreg_pipette_pump_dec), // - kreg_pipette_pump_vstart(RegIndex.kreg_pipette_pump_vstart), // - kreg_pipette_pump_vstop(RegIndex.kreg_pipette_pump_vstop), // - kreg_pipette_pump_vmax(RegIndex.kreg_pipette_pump_vmax), // - kreg_pipette_aspirate_distribut_pump_vel(RegIndex.kreg_pipette_aspirate_distribut_pump_vel), // - kreg_pipette_lld_pump_vel(RegIndex.kreg_pipette_lld_pump_vel), // - kreg_pipette_lld_motor_vel_rpm(RegIndex.kreg_pipette_lld_motor_vel_rpm), // - kreg_pipette_lld_detect_period_ms(RegIndex.kreg_pipette_lld_detect_period_ms), // - kreg_pipette_lld_prepare_pos(RegIndex.kreg_pipette_lld_prepare_pos), // - kreg_pipette_lld_prepare_distribut_pos(RegIndex.kreg_pipette_lld_prepare_distribut_pos), // +// kreg_pipette_pump_acc(RegIndex.kreg_pipette_pump_acc), // +// kreg_pipette_pump_dec(RegIndex.kreg_pipette_pump_dec), // +// kreg_pipette_pump_vstart(RegIndex.kreg_pipette_pump_vstart), // +// kreg_pipette_pump_vstop(RegIndex.kreg_pipette_pump_vstop), // +// kreg_pipette_pump_vmax(RegIndex.kreg_pipette_pump_vmax), // +// kreg_pipette_aspirate_distribut_pump_vel(RegIndex.kreg_pipette_aspirate_distribut_pump_vel), // +// kreg_pipette_lld_pump_vel(RegIndex.kreg_pipette_lld_pump_vel), // +// kreg_pipette_lld_motor_vel_rpm(RegIndex.kreg_pipette_lld_motor_vel_rpm), // +// kreg_pipette_lld_detect_period_ms(RegIndex.kreg_pipette_lld_detect_period_ms), // +// kreg_pipette_lld_prepare_pos(RegIndex.kreg_pipette_lld_prepare_pos), // +// kreg_pipette_lld_prepare_distribut_pos(RegIndex.kreg_pipette_lld_prepare_distribut_pos), // kreg_pipette_zm_pos(RegIndex.kreg_pipette_zm_pos), kreg_pipette_zm_is_enable(RegIndex.kreg_pipette_zm_is_enable), diff --git a/src/main/java/a8k/service/app/devicectrl/exdriver/PipetteCtrlExDriver.java b/src/main/java/a8k/service/app/devicectrl/exdriver/PipetteCtrlExDriver.java new file mode 100644 index 0000000..ccf204c --- /dev/null +++ b/src/main/java/a8k/service/app/devicectrl/exdriver/PipetteCtrlExDriver.java @@ -0,0 +1,42 @@ +package a8k.service.app.devicectrl.exdriver; + + +import a8k.extapi.utils.ExtApiTab; +import a8k.service.app.devicectrl.driver.PipetteCtrlDriver; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Component; + +@Component +@ExtApiTab() +public class PipetteCtrlExDriver { + @Resource + PipetteCtrlDriver pipetteCtrlDriver; + + /* + * + * 取样(取样位置lld,,目标位置吸吐混匀) + * 1. 取大瓶缓冲液到探测物质位置 (非接触分配)取样一般比较大,lld探测到液面后,直接吸取即可 + * 2. 取样本到探测物质 (接触分配) 取样比较小,lld探测到液面后,先排空,再吸取 + * 3. 取样本到小瓶缓冲液位置 (接触分配) + * + * + * 分配:(先接触分配,后快速分配) + * 1. 从探测物质取混合液到反应板 + * 2. 从小瓶缓冲液取混合液到反应板 + * + * + */ + + // + // 取大瓶缓冲液到探测物质位置 + // 取样本到探测物质 + // 取样本到小瓶缓冲液位置 + // + // 从探测物质取混合液到 + // 从小瓶缓冲液取混合液到 + // + // 吸吐混匀 + + + +} diff --git a/src/main/java/a8k/service/app/devicectrl/param/calibration/PipetteGunLLDParamCalibration.java b/src/main/java/a8k/service/app/devicectrl/param/calibration/PipetteGunLLDParamCalibration.java index a484b1b..5ad4b73 100644 --- a/src/main/java/a8k/service/app/devicectrl/param/calibration/PipetteGunLLDParamCalibration.java +++ b/src/main/java/a8k/service/app/devicectrl/param/calibration/PipetteGunLLDParamCalibration.java @@ -17,93 +17,93 @@ import org.springframework.stereotype.Component; @Component public class PipetteGunLLDParamCalibration { - @Resource - PipetteGunLLDParamMgr pipetteGunLLDParamMgr; - - @Resource - PipetteCtrlDriver pipetteCtrlDriver; - @Resource - HbotBaseMoveExDriver hbotBaseMoveExDriver; - @Resource - MotorEnableExDriver motorEnableExDriver; - - - // 测试工具 - // @ExtApiFn(name = "归零", group = "基础", order = 1) - // public void moveToZero() throws AppException { - // enableModule(); - // pipetteCtrlDriver.zMotorMoveZeroBlock(); - // } - - @ExtApiFn(name = "移液枪初始化(Tip会掉落)", group = "基础", order = 2) - public void pipetteInitDeviceBlock() throws AppException { - pipetteCtrlDriver.pipetteInitDeviceBlock(); - - } - - @ExtApiFn(name = "使能相关模块", group = "基础", order = 3) - public void enableModule() throws AppException { - pipetteCtrlDriver.zMotorEnable(1); - } - - @ExtApiFn(name = "失能相关模块", group = "基础", order = 4) - public void disableModule() throws AppException { - motorEnableExDriver.forceDisableAllMotor(); - } - - @ExtApiFn(name = "获取相关参数", group = "基础", order = 5) - public Object getParams() throws AppException { - return pipetteGunLLDParamMgr.getParams(); - } - - - Integer lldStartPos; - Integer lldEndPos; - - @ExtApiFn(name = "设置LLD开始位置", group = "测试", order = 100) - public void setStartTestPos() throws AppException { - pipetteCtrlDriver.zMotorEnable(1); - pipetteCtrlDriver.zMotorMeasureDistance(); - lldStartPos = pipetteCtrlDriver.zMotorReadMeasureDistanceResult(); - pipetteCtrlDriver.zMotorEnable(0); - } - - @ExtApiFn(name = "设置LLD结束位置", group = "测试", order = 101) - public void setEndTestPos() throws AppException { - pipetteCtrlDriver.zMotorEnable(1); - pipetteCtrlDriver.zMotorMeasureDistance(); - lldEndPos = pipetteCtrlDriver.zMotorReadMeasureDistanceResult(); - pipetteCtrlDriver.zMotorEnable(0); - } - - @ExtApiFn(name = "LDD测量液体属性", group = "测试", order = 103) - public Object lldCalibrate() throws AppException { - if (lldStartPos > lldEndPos) { - throw AppException.ofAECodeError("开始位置大于结束位置"); - } - - pipetteCtrlDriver.zMotorEnable(1); - pipetteCtrlDriver.zMotorMoveZeroBlock(); - - pipetteCtrlDriver.pipetteLld(LldType.kplld, lldEndPos, 100, 100); - return pipetteCtrlDriver.getSensorSampleData(); - } - - @ExtApiFn(name = "LLD测试", group = "测试", order = 104) - public void lldTest(LldType type, Integer c_val, Integer p_val) throws AppException { - pipetteCtrlDriver.zMotorEnable(1); - pipetteCtrlDriver.zMotorMoveZeroBlock(); - pipetteCtrlDriver.pipetteLld(type, lldEndPos, c_val, p_val); - } - - - @ExtApiFn(name = "设置阈值", group = "设置", order = 200) - public void setThreshold(PipetteGunLLDThresholdParam param, Integer val) throws AppException { - pipetteGunLLDParamMgr.setParam(param, val); - } - - @ExtApiFn(name = "设置默认LLD方式", group = "设置", order = 201) - public void setLLDType(PipetteGunLLDTypeParam param, LldType type) throws AppException { - pipetteGunLLDParamMgr.setParam(param, type.name()); - } +// @Resource +// PipetteGunLLDParamMgr pipetteGunLLDParamMgr; +// +// @Resource +// PipetteCtrlDriver pipetteCtrlDriver; +// @Resource +// HbotBaseMoveExDriver hbotBaseMoveExDriver; +// @Resource +// MotorEnableExDriver motorEnableExDriver; +// +// +// // 测试工具 +// // @ExtApiFn(name = "归零", group = "基础", order = 1) +// // public void moveToZero() throws AppException { +// // enableModule(); +// // pipetteCtrlDriver.zMotorMoveZeroBlock(); +// // } +// +// @ExtApiFn(name = "移液枪初始化(Tip会掉落)", group = "基础", order = 2) +// public void pipetteInitDeviceBlock() throws AppException { +// pipetteCtrlDriver.pipetteInitDeviceBlock(); +// +// } +// +// @ExtApiFn(name = "使能相关模块", group = "基础", order = 3) +// public void enableModule() throws AppException { +// pipetteCtrlDriver.zMotorEnable(1); +// } +// +// @ExtApiFn(name = "失能相关模块", group = "基础", order = 4) +// public void disableModule() throws AppException { +// motorEnableExDriver.forceDisableAllMotor(); +// } +// +// @ExtApiFn(name = "获取相关参数", group = "基础", order = 5) +// public Object getParams() throws AppException { +// return pipetteGunLLDParamMgr.getParams(); +// } +// +// +// Integer lldStartPos; +// Integer lldEndPos; +// +// @ExtApiFn(name = "设置LLD开始位置", group = "测试", order = 100) +// public void setStartTestPos() throws AppException { +// pipetteCtrlDriver.zMotorEnable(1); +// pipetteCtrlDriver.zMotorMeasureDistance(); +// lldStartPos = pipetteCtrlDriver.zMotorReadMeasureDistanceResult(); +// pipetteCtrlDriver.zMotorEnable(0); +// } +// +// @ExtApiFn(name = "设置LLD结束位置", group = "测试", order = 101) +// public void setEndTestPos() throws AppException { +// pipetteCtrlDriver.zMotorEnable(1); +// pipetteCtrlDriver.zMotorMeasureDistance(); +// lldEndPos = pipetteCtrlDriver.zMotorReadMeasureDistanceResult(); +// pipetteCtrlDriver.zMotorEnable(0); +// } +// +// @ExtApiFn(name = "LDD测量液体属性", group = "测试", order = 103) +// public Object lldCalibrate() throws AppException { +// if (lldStartPos > lldEndPos) { +// throw AppException.ofAECodeError("开始位置大于结束位置"); +// } +// +// pipetteCtrlDriver.zMotorEnable(1); +// pipetteCtrlDriver.zMotorMoveZeroBlock(); +// +// pipetteCtrlDriver.pipetteLld(LldType.kplld, lldEndPos, 100, 100); +// return pipetteCtrlDriver.getSensorSampleData(); +// } +// +// @ExtApiFn(name = "LLD测试", group = "测试", order = 104) +// public void lldTest(LldType type, Integer c_val, Integer p_val) throws AppException { +// pipetteCtrlDriver.zMotorEnable(1); +// pipetteCtrlDriver.zMotorMoveZeroBlock(); +// pipetteCtrlDriver.pipetteLld(type, lldEndPos, c_val, p_val); +// } +// +// +// @ExtApiFn(name = "设置阈值", group = "设置", order = 200) +// public void setThreshold(PipetteGunLLDThresholdParam param, Integer val) throws AppException { +// pipetteGunLLDParamMgr.setParam(param, val); +// } +// +// @ExtApiFn(name = "设置默认LLD方式", group = "设置", order = 201) +// public void setLLDType(PipetteGunLLDTypeParam param, LldType type) throws AppException { +// pipetteGunLLDParamMgr.setParam(param, type.name()); +// } } diff --git a/src/main/java/a8k/service/app/devicectrl/param/calibration/PipetteGunLLFParamCalibration.java b/src/main/java/a8k/service/app/devicectrl/param/calibration/PipetteGunLLFParamCalibration.java index 747c2fe..22bad8a 100644 --- a/src/main/java/a8k/service/app/devicectrl/param/calibration/PipetteGunLLFParamCalibration.java +++ b/src/main/java/a8k/service/app/devicectrl/param/calibration/PipetteGunLLFParamCalibration.java @@ -15,75 +15,75 @@ import org.springframework.stereotype.Component; @ExtApiTab() @Component public class PipetteGunLLFParamCalibration { - - @Resource - PipetteGunLLFParamMgr pipetteGunLLFParamMgr; - - @Resource - PipetteCtrlDriver pipetteCtrlDriver; - - @Resource - MotorEnableExDriver motorEnableExDriver; - - - @ExtApiFn(name = "移液枪初始化(Tip会掉落)", group = "基础", order = 2) - public void pipetteInitDeviceBlock() throws AppException { - pipetteCtrlDriver.pipetteInitDeviceBlock(); - - } - - @ExtApiFn(name = "使能相关模块", group = "基础", order = 3) - public void enableModule() throws AppException { - pipetteCtrlDriver.zMotorEnable(1); - } - - @ExtApiFn(name = "失能相关模块", group = "基础", order = 4) - public void disableModule() throws AppException { - motorEnableExDriver.forceDisableAllMotor(); - } - - @ExtApiFn(name = "获取相关参数", group = "基础", order = 5) - public Object getParams() throws AppException { - return pipetteGunLLFParamMgr.getParams(); - } - - - Integer llfStartPos; - Integer llfEndPos; - - - @ExtApiFn(name = "设置llf开始位置", group = "测试", order = 100) - public void setStartTestPos() throws AppException { - pipetteCtrlDriver.zMotorEnable(1); - pipetteCtrlDriver.zMotorMeasureDistance(); - llfStartPos = pipetteCtrlDriver.zMotorReadMeasureDistanceResult(); - pipetteCtrlDriver.zMotorEnable(0); - } - - @ExtApiFn(name = "设置llf结束位置", group = "测试", order = 101) - public void setEndTestPos() throws AppException { - pipetteCtrlDriver.zMotorEnable(1); - pipetteCtrlDriver.zMotorMeasureDistance(); - llfEndPos = pipetteCtrlDriver.zMotorReadMeasureDistanceResult(); - pipetteCtrlDriver.zMotorEnable(0); - } - - - @ExtApiFn(name = "吸液", group = "测试", order = 104) - public void aspirate(Integer llfv, Integer ul) throws AppException { - pipetteCtrlDriver.zMotorMoveToBlock(llfStartPos); - pipetteCtrlDriver.pipetteAspirate(llfv, llfEndPos, PipetteGunConstant.ASPIRATE_PUMP_V, ul); - } - - @ExtApiFn(name = "分液", group = "测试", order = 105) - public void distribute() throws AppException { - pipetteCtrlDriver.zMotorMoveToBlock(llfStartPos - 100); - pipetteCtrlDriver.pipetteDistribu(0, PipetteGunConstant.MAX_PUMP_V, PipetteGunConstant.DISTRIBU_ALL_VOL); - } - - @ExtApiFn(name = "设置参数", group = "设置", order = 200) - public void setDefaultCThread(PipetteGunLLFParam param, Integer val) throws AppException { - pipetteGunLLFParamMgr.setParam(param, val); - } +// +// @Resource +// PipetteGunLLFParamMgr pipetteGunLLFParamMgr; +// +// @Resource +// PipetteCtrlDriver pipetteCtrlDriver; +// +// @Resource +// MotorEnableExDriver motorEnableExDriver; +// +// +// @ExtApiFn(name = "移液枪初始化(Tip会掉落)", group = "基础", order = 2) +// public void pipetteInitDeviceBlock() throws AppException { +// pipetteCtrlDriver.pipetteInitDeviceBlock(); +// +// } +// +// @ExtApiFn(name = "使能相关模块", group = "基础", order = 3) +// public void enableModule() throws AppException { +// pipetteCtrlDriver.zMotorEnable(1); +// } +// +// @ExtApiFn(name = "失能相关模块", group = "基础", order = 4) +// public void disableModule() throws AppException { +// motorEnableExDriver.forceDisableAllMotor(); +// } +// +// @ExtApiFn(name = "获取相关参数", group = "基础", order = 5) +// public Object getParams() throws AppException { +// return pipetteGunLLFParamMgr.getParams(); +// } +// +// +// Integer llfStartPos; +// Integer llfEndPos; +// +// +// @ExtApiFn(name = "设置llf开始位置", group = "测试", order = 100) +// public void setStartTestPos() throws AppException { +// pipetteCtrlDriver.zMotorEnable(1); +// pipetteCtrlDriver.zMotorMeasureDistance(); +// llfStartPos = pipetteCtrlDriver.zMotorReadMeasureDistanceResult(); +// pipetteCtrlDriver.zMotorEnable(0); +// } +// +// @ExtApiFn(name = "设置llf结束位置", group = "测试", order = 101) +// public void setEndTestPos() throws AppException { +// pipetteCtrlDriver.zMotorEnable(1); +// pipetteCtrlDriver.zMotorMeasureDistance(); +// llfEndPos = pipetteCtrlDriver.zMotorReadMeasureDistanceResult(); +// pipetteCtrlDriver.zMotorEnable(0); +// } +// +// +// @ExtApiFn(name = "吸液", group = "测试", order = 104) +// public void aspirate(Integer llfv, Integer ul) throws AppException { +// pipetteCtrlDriver.zMotorMoveToBlock(llfStartPos); +// pipetteCtrlDriver.pipetteAspirate(llfv, llfEndPos, PipetteGunConstant.ASPIRATE_PUMP_V, ul); +// } +// +// @ExtApiFn(name = "分液", group = "测试", order = 105) +// public void distribute() throws AppException { +// pipetteCtrlDriver.zMotorMoveToBlock(llfStartPos - 100); +// pipetteCtrlDriver.pipetteDistribu(0, PipetteGunConstant.MAX_PUMP_V, PipetteGunConstant.DISTRIBU_ALL_VOL); +// } +// +// @ExtApiFn(name = "设置参数", group = "设置", order = 200) +// public void setDefaultCThread(PipetteGunLLFParam param, Integer val) throws AppException { +// pipetteGunLLFParamMgr.setParam(param, val); +// } } diff --git a/src/main/java/a8k/service/app/devicectrl/param/param_mgr/PipetteGunExParamMgr.java b/src/main/java/a8k/service/app/devicectrl/param/param_mgr/PipetteGunExParamMgr.java index 5b537d5..36c03c8 100644 --- a/src/main/java/a8k/service/app/devicectrl/param/param_mgr/PipetteGunExParamMgr.java +++ b/src/main/java/a8k/service/app/devicectrl/param/param_mgr/PipetteGunExParamMgr.java @@ -9,7 +9,8 @@ import org.springframework.stereotype.Component; @Slf4j public class PipetteGunExParamMgr extends ParamMgr { enum PipetteGunParam { - VOLUME_CALIBRATION_COEFFICIENT("体积校准系数", Double.class), + VOLUME_CALIBRATION_COEFFICIENT_A("体积校准系数-A", Double.class), + VOLUME_CALIBRATION_COEFFICIENT_B("体积校准系数-B", Double.class), ; public final String chName; @@ -29,16 +30,14 @@ public class PipetteGunExParamMgr extends ParamMgr { } } - public void setVolumeCalibrationCoefficient(Double value) { - setParam(PipetteGunParam.VOLUME_CALIBRATION_COEFFICIENT, value); + public void setVolumeCalibrationCoefficient(Double A, Double B) { + setParam(PipetteGunParam.VOLUME_CALIBRATION_COEFFICIENT_A, A); + setParam(PipetteGunParam.VOLUME_CALIBRATION_COEFFICIENT_B, B); } - public Double getVolumeCalibrationCoefficient() { - Double val = getParam(PipetteGunParam.VOLUME_CALIBRATION_COEFFICIENT, Double.class); - if (val == null) { - return 1.0; - } - return val; + public double calibrateVolume(double rawVolume) { + Double A = getParam(PipetteGunParam.VOLUME_CALIBRATION_COEFFICIENT_A, Double.class); + Double B = getParam(PipetteGunParam.VOLUME_CALIBRATION_COEFFICIENT_B, Double.class); + return A * rawVolume + B; } - } diff --git a/src/main/java/a8k/service/app/devicectrl/script/PipeGunCtrlScripter.java b/src/main/java/a8k/service/app/devicectrl/script/PipeGunCtrlScripter.java index f884e3e..9db53c1 100644 --- a/src/main/java/a8k/service/app/devicectrl/script/PipeGunCtrlScripter.java +++ b/src/main/java/a8k/service/app/devicectrl/script/PipeGunCtrlScripter.java @@ -30,63 +30,63 @@ import org.springframework.util.Assert; @Component @Slf4j public class PipeGunCtrlScripter { - - - @Resource - PipetteCtrlDriver pipetteCtrlDriver; - @Resource - HbotSamplePosParamMgr hbotSamplePosParamMgr; - @Resource - HbotConsumableParamMgr hbotConsumableParamMgr; - @Resource - PipetteGunParamExMgr pipetteGunParamExMgr; - @Resource - TestModeState testModeState; - - public void mix(PipetteGunBindActionType actionType, ProjectTaskContext ctx, Integer ul, Integer times) throws AppException { - LLFParamPack llfParamPack = pipetteGunParamExMgr.getLLFParam(actionType, ctx); - pipetteCtrlDriver.pipetteShakeUp(llfParamPack.llfVel, llfParamPack.llfEndPos, PipetteGunConstant.ASPIRATE_PUMP_V, ul, times); - } - - - public void aspirate(PipetteGunBindActionType actionType, ProjectTaskContext ctx, Integer ul) throws AppException { - LLFParamPack llfParamPack = pipetteGunParamExMgr.getLLFParam(actionType, ctx); - log.info("吸液 {} , llfvel {} , llfStartPos {} , llfEndPos {}", ul, llfParamPack.llfVel, llfParamPack.llfStartPos, llfParamPack.llfEndPos); - pipetteCtrlDriver.pipetteAspirate(llfParamPack.llfVel, llfParamPack.llfEndPos, PipetteGunConstant.ASPIRATE_PUMP_V, ul); - } - - - public void lld(PipetteGunBindActionType actionType, ProjectTaskContext ctx) throws AppException { - log.info("液面探测 {}", actionType); - LLDParamPack lldparm = pipetteGunParamExMgr.getLLDParam(actionType, ctx); - Pos3d sampleStartPos = null; - Pos3d sampleEndPos = null; - - //取tip,移动到样本所在的位置,并液面探测 - switch (actionType) { - case SAMPLE -> { - A8kSamplePos samplePos = ProjProcessContextUtils.getSamplePos(ctx); - sampleStartPos = hbotSamplePosParamMgr.getSampleStartPos(samplePos); - sampleEndPos = hbotSamplePosParamMgr.getSampleEndPos(samplePos); - } - case TAKE_LARGE_BUFFER_SOLUTION -> { //取大瓶缓冲液 - var group = ctx.getConsumable().getGroup(); - sampleStartPos = hbotConsumableParamMgr.getLargeBufferSamplePos(group); - sampleEndPos = hbotConsumableParamMgr.getLargeBufferSamplePosEnd(group); - } - } - - Assert.notNull(sampleStartPos, "sampleStartPos is null"); - Assert.notNull(sampleEndPos, "sampleEndPos is null"); - - pipetteCtrlDriver.pipetteLld(LldType.kplld, sampleEndPos.z, lldparm.cThreshold, lldparm.pThreshold); - if (!pipetteCtrlDriver.lldIsDetectLiquid()) { - if (testModeState.getNoCheckMode()) { - log.warn("没有液体"); - } else { - throw new AppException(A8kEcode.APPE_DETECT_SAMPLE_FAIL); - } - } - } + // + // + // @Resource + // PipetteCtrlDriver pipetteCtrlDriver; + // @Resource + // HbotSamplePosParamMgr hbotSamplePosParamMgr; + // @Resource + // HbotConsumableParamMgr hbotConsumableParamMgr; + // @Resource + // PipetteGunParamExMgr pipetteGunParamExMgr; + // @Resource + // TestModeState testModeState; + // + // public void mix(PipetteGunBindActionType actionType, ProjectTaskContext ctx, Integer ul, Integer times) throws AppException { + // LLFParamPack llfParamPack = pipetteGunParamExMgr.getLLFParam(actionType, ctx); + // pipetteCtrlDriver.pipetteShakeUp(llfParamPack.llfVel, llfParamPack.llfEndPos, PipetteGunConstant.ASPIRATE_PUMP_V, ul, times); + // } + // + // + // public void aspirate(PipetteGunBindActionType actionType, ProjectTaskContext ctx, Integer ul) throws AppException { + // LLFParamPack llfParamPack = pipetteGunParamExMgr.getLLFParam(actionType, ctx); + // log.info("吸液 {} , llfvel {} , llfStartPos {} , llfEndPos {}", ul, llfParamPack.llfVel, llfParamPack.llfStartPos, llfParamPack.llfEndPos); + // pipetteCtrlDriver.pipetteAspirate(llfParamPack.llfVel, llfParamPack.llfEndPos, PipetteGunConstant.ASPIRATE_PUMP_V, ul); + // } + // + // + // public void lld(PipetteGunBindActionType actionType, ProjectTaskContext ctx) throws AppException { + // log.info("液面探测 {}", actionType); + // LLDParamPack lldparm = pipetteGunParamExMgr.getLLDParam(actionType, ctx); + // Pos3d sampleStartPos = null; + // Pos3d sampleEndPos = null; + // + // //取tip,移动到样本所在的位置,并液面探测 + // switch (actionType) { + // case SAMPLE -> { + // A8kSamplePos samplePos = ProjProcessContextUtils.getSamplePos(ctx); + // sampleStartPos = hbotSamplePosParamMgr.getSampleStartPos(samplePos); + // sampleEndPos = hbotSamplePosParamMgr.getSampleEndPos(samplePos); + // } + // case TAKE_LARGE_BUFFER_SOLUTION -> { //取大瓶缓冲液 + // var group = ctx.getConsumable().getGroup(); + // sampleStartPos = hbotConsumableParamMgr.getLargeBufferSamplePos(group); + // sampleEndPos = hbotConsumableParamMgr.getLargeBufferSamplePosEnd(group); + // } + // } + // + // Assert.notNull(sampleStartPos, "sampleStartPos is null"); + // Assert.notNull(sampleEndPos, "sampleEndPos is null"); + // + // pipetteCtrlDriver.pipetteLld(LldType.kplld, sampleEndPos.z, lldparm.cThreshold, lldparm.pThreshold); + // if (!pipetteCtrlDriver.lldIsDetectLiquid()) { + // if (testModeState.getNoCheckMode()) { + // log.warn("没有液体"); + // } else { + // throw new AppException(A8kEcode.APPE_DETECT_SAMPLE_FAIL); + // } + // } + // } } diff --git a/src/main/java/a8k/service/verification/PipetteGunVerificationV2.java b/src/main/java/a8k/service/verification/PipetteGunVerificationV2.java index 2cd2ecd..1de8b0a 100644 --- a/src/main/java/a8k/service/verification/PipetteGunVerificationV2.java +++ b/src/main/java/a8k/service/verification/PipetteGunVerificationV2.java @@ -1,9 +1,7 @@ package a8k.service.verification; import a8k.constant.AppConstant; -import a8k.constant.PipetteGunConstant; import a8k.extapi.utils.ExtApiFn; -import a8k.extapi.utils.ExtApiStatu; import a8k.extapi.utils.ExtApiTab; import a8k.hardware.type.LldType; import a8k.service.app.devicectrl.ctrlservice.DeviceInitCtrlService; @@ -16,17 +14,14 @@ import a8k.service.app.devicectrl.param.ext_param_mgr.HbotConsumableParamMgr; import a8k.service.app.devicectrl.param.ext_param_mgr.PipetteGunParamExMgr; import a8k.service.app.devicectrl.param.param_mgr.*; import a8k.type.ConsumableGroup; -import a8k.type.checkpoint.CheckResult; +import a8k.type.cfg.Pos3d; import a8k.type.exception.AppException; import a8k.type.pos.TipPos; import a8k.type.type.TipGroup; -import jakarta.annotation.PostConstruct; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; -import java.util.List; - @ExtApiTab() @Component @Slf4j @@ -65,56 +60,50 @@ public class PipetteGunVerificationV2 { PipetteGunExParamMgr pipetteGunExParamMgr; - Integer tipNum = 0; - Integer m_loadUl = 0; - Integer lldpThreshold = 20; + Integer tipNum = 0; + Integer liquidPos = null; - @PostConstruct - void initialize() { - pipetteCtrlDriver.setVolumeCalibrationCoefficient(pipetteGunExParamMgr.getVolumeCalibrationCoefficient()); + public void pipetteGunInit() throws AppException { + pipetteCtrlDriver.liquidOperationClearParams(); // + pipetteCtrlDriver.liquidOperationSetGunRunParams(14, 14, 0, 900, 8000); //pump param + pipetteCtrlDriver.liquidOperationFreshParams(); + pipetteCtrlDriver.pipetteInitDeviceBlock(); } - @ExtApiFn(name = "初始化设备", group = "测试准备工作", order = 11) - public List initDevice() throws AppException { - List checkResult = deviceInitializationModule.initDevice(); - for (CheckResult result : checkResult) { - if (!result.pass) { - return checkResult; - } - } - return checkResult; - } + @ExtApiFn(name = "初始化设备", group = "基础", order = 11) + public void initDevice() throws AppException { + pipetteCtrlDriver.zMotorEnable(1); + hbotBaseMoveExDriver.enable(1); - @ExtApiFn(name = "加载tip头", group = "测试准备工作", order = 12) - public void loadTip() throws AppException { - tipNum = AppConstant.TIP_NUM; - } + pipetteCtrlDriver.zMotorMoveZeroBlock(); + hbotBaseMoveExDriver.moveToZero(); + hbotBaseMoveExDriver.hbotMoveTo(hbotTipPosMgr.getDropTipPos()); + + pipetteGunInit(); + hbotBaseMoveExDriver.hbotMoveTo(new Pos3d(0, 0, 0)); + tipNum = AppConstant.TIP_NUM; - @ExtApiFn(name = "设置吸液量", group = "测试准备工作", order = 13) - public void setM_loadUl(Integer m_loadUl) { - this.m_loadUl = m_loadUl; } - @ExtApiFn(name = "设置LLD P阈值(建议20)", group = "测试准备工作", order = 14) - public void setLldpThreshold(Integer lldpThreshold) { - this.lldpThreshold = lldpThreshold; + @ExtApiFn(name = "停止测试", group = "基础", order = 12) + public void stopTest() throws AppException { + pipetteCtrlDriver.zMotorEnable(0); + hbotBaseMoveExDriver.enable(0); } @ExtApiFn(name = "校准系数(realul:实际体积)", group = "测试准备工作", order = 15) - public void calibration(Double realul) { - Double nowcoefficient = pipetteCtrlDriver.getVolumeCalibrationCoefficient(); - Double coefficient = m_loadUl * nowcoefficient / realul; - pipetteGunExParamMgr.setVolumeCalibrationCoefficient(coefficient); - pipetteCtrlDriver.setVolumeCalibrationCoefficient(coefficient); + public void calibration(Double coefficientK, Double coefficientB) { + pipetteGunExParamMgr.setVolumeCalibrationCoefficient(coefficientK, coefficientB); } Boolean takeOneTip() throws AppException { hbotBaseMoveExDriver.hbotMoveTo(hbotTipPosMgr.getDropTipPos()); - pipetteCtrlDriver.pipetteInitDeviceBlock(); + pipetteGunInit(); + TipPos tipPos = new TipPos(); tipPos.group = TipGroup.GROUP0; if (tipNum == 0) { @@ -135,174 +124,96 @@ public class PipetteGunVerificationV2 { } - // @ExtApiFn(name = "吸取并释放一次", group = "测试", order = 21) - // public void aspirateAndDistruptOnce() throws AppException { - // if (loadUl == 0) { - // throw AppException.ofAECodeError("吸液量为0"); - // } - // - // // - // // param - // // - // - // Integer startZPos = hbotConsumableParamMgr.getLargeBufferSamplePos(ConsumableGroup.GROUP0).z; - // Integer endZPos = hbotConsumableParamMgr.getLargeBufferSamplePosEnd(ConsumableGroup.GROUP0).z; - // Integer llfv = 5; - // - // while (!pipetteCtrlDriver.isHasTip()) { - // if (takeOneTip()) { - // break; - // } - // } - // // - // // lld - // // - // hbotCtrlService.moveToLargeBSSamplePos(ConsumableGroup.GROUP0); - // pipetteCtrlDriver.zMotorMoveToBlock(startZPos); - // - // pipetteCtrlDriver.pipetteLld(LldType.kclld, endZPos, 20, 20); - // if (!pipetteCtrlDriver.lldIsDetectLiquid()) { - // throw AppException.ofAECodeError("没有液体"); - // } - // - // Integer liquidZPos = pipetteCtrlDriver.getReg(PipetteRegIndex.kreg_pipette_zm_pos); - // pipetteCtrlDriver.pipetteAspirate(0, 0, PipetteGunConstant.ASPIRATE_PUMP_V, 20); - // pipetteCtrlDriver.zMotorMoveToBlock(liquidZPos - 100); - // // pipetteCtrlDriver.pipetteClearHangingLiquid(3); - // pipetteCtrlDriver.pipettePumpMoveTo(1000, 0); //移除探测吸入的液体 - // pipetteCtrlDriver.pipettePumpMoveTo(500, 50); //吸入10ul的空气消除部分误差 - // pipetteCtrlDriver.zMotorMoveToBlock(liquidZPos); - // - // // - // // aspirate - // // - // if (loadUl < 50) { - // pipetteCtrlDriver.pipetteAspirate(llfv, endZPos, PipetteGunConstant.ASPIRATE_PUMP_V, loadUl + 10); - // pipetteCtrlDriver.pipetteDistribu(0, PipetteGunConstant.ASPIRATE_PUMP_V, 10); - // // pipetteCtrlDriver.pipetteAspirate(0, endZPos, PipetteGunConstant.ASPIRATE_PUMP_V, loadUl); - // } else { - // pipetteCtrlDriver.pipetteAspirate(llfv, endZPos, PipetteGunConstant.ASPIRATE_PUMP_V, loadUl); - // } - // pipetteCtrlDriver.zMotorMoveToZeroPointQuickBlock(); - // - // // - // // move to distrube pos - // // - // hbotCtrlService.moveToLargeBSSamplePos(ConsumableGroup.GROUP1); - // // pipetteCtrlDriver.pipetteDistribu(0, PipetteGunConstant.ASPIRATE_PUMP_V, loadUl); - // pipetteCtrlDriver.pipettePumpMoveTo(1000, 0); //分配所有液体 - // pipetteCtrlDriver.pipetteClearHangingLiquid(1); - // hbotCtrlService.moveQuickToZero(); - // } - - - @ExtApiFn(name = "取一次10ul", group = "测试", order = 22) - public void aspirate10ul() throws AppException { - var loadUl = 10; + public void pumpMoveTo(Integer pumpvmax, Double ul) throws AppException { + pipetteCtrlDriver.liquidOperationClearParams(); + pipetteCtrlDriver.liquidOperationSetGunRunParams(14, 14, 0, 1000, pumpvmax); + pipetteCtrlDriver.liquidOperationFreshParams(); + pipetteCtrlDriver.pipettePumpMoveTo(ul); + } - // - // param - // + public Integer lld() throws AppException { + liquidPos = 0; + hbotCtrlService.moveToLargeBSSamplePosXY(ConsumableGroup.GROUP0); - Integer startZPos = hbotConsumableParamMgr.getLargeBufferSamplePos(ConsumableGroup.GROUP0).z; - Integer endZPos = hbotConsumableParamMgr.getLargeBufferSamplePosEnd(ConsumableGroup.GROUP0).z; + pipetteCtrlDriver.zMotorMoveToBlock(0); - // - // lld - // - hbotCtrlService.moveToLargeBSSamplePos(ConsumableGroup.GROUP0); - pipetteCtrlDriver.zMotorMoveToBlock(startZPos); + pumpMoveTo(8000, 0.0); + pumpMoveTo(8000, 50.0); - pipetteCtrlDriver.pipettePumpMoveTo(1000, 0); //移除探测吸入的液体 - pipetteCtrlDriver.pipettePumpMoveTo(500, 100); //吸入10ul的空气消除部分误差 + pipetteCtrlDriver.liquidOperationClearParams(); // + pipetteCtrlDriver.liquidOperationSetGunRunParams(14, 14, 0, 900, 30); //pump param + pipetteCtrlDriver.liquidOperationSetZMotorRunParams(0, 300, 30); // z motor param + pipetteCtrlDriver.liquidOperationFreshParams(); + pipetteCtrlDriver.pipetteLld(LldType.kplld, 0, 15); - pipetteCtrlDriver.pipetteLld(LldType.kclld, endZPos, 20, 20); - if (!pipetteCtrlDriver.lldIsDetectLiquid()) { - throw AppException.ofAECodeError("没有液体"); + if (pipetteCtrlDriver.lldIsDetectLiquid()) { + liquidPos = pipetteCtrlDriver.getReg(PipetteRegIndex.kreg_pipette_zm_pos); } - pipetteCtrlDriver.pipetteAspirate(0, 10, 50, loadUl + 10); - pipetteCtrlDriver.pipetteDistribu(0, 50, 10); - - pipetteCtrlDriver.zMotorMoveToZeroPointQuickBlock(); - // - // move to distrube pos - // - hbotCtrlService.moveToLargeBSSamplePos(ConsumableGroup.GROUP1); - pipetteCtrlDriver.pipettePumpMoveTo(1000, 0); //分配所有液体 - hbotCtrlService.moveQuickToZero(); + pipetteCtrlDriver.zMotorMoveToBlock(0); + pumpMoveTo(8000, 0.0); + return liquidPos; } - @ExtApiFn(name = "取多次", group = "测试", order = 23) - public void takeMuti(Integer times,Integer loadUl) throws AppException { - for (int i = 0; i < times; i++) { - takeOnce(loadUl); - } - } - - @ExtApiFn(name = "取一次", group = "测试", order = 23) - public void takeOnce(Integer loadUl) throws AppException { - takeTip(); - - Integer startZPos = hbotConsumableParamMgr.getLargeBufferSamplePos(ConsumableGroup.GROUP0).z; - Integer endZPos = hbotConsumableParamMgr.getLargeBufferSamplePosEnd(ConsumableGroup.GROUP0).z; - - // move To Take Pos - hbotCtrlService.moveToLargeBSSamplePos(ConsumableGroup.GROUP0); - - - // lld - pipetteCtrlDriver.pipettePumpMoveTo(1000, 0); //移除探测吸入的液体 - pipetteCtrlDriver.pipettePumpMoveTo(500, 100); //吸入10ul的空气消除部分误差 - pipetteCtrlDriver.zMotorMoveToBlock(startZPos); - pipetteCtrlDriver.pipetteLld(LldType.kplld, endZPos, 20, 10); - if (!pipetteCtrlDriver.lldIsDetectLiquid()) { - throw AppException.ofAECodeError("没有液体"); - } - pipetteCtrlDriver.pipetteAspirate(10, endZPos, 200, 50);// + public void takeLiquid(Double ul) throws AppException { + /* + * 1. + */ + hbotCtrlService.moveToLargeBSSamplePosXY(ConsumableGroup.GROUP0); + pipetteCtrlDriver.zMotorMoveToBlock(0); + pumpMoveTo(8000, 0.0); + pumpMoveTo(8000, 150.0); - Integer liquidZPos = pipetteCtrlDriver.getReg(PipetteRegIndex.kreg_pipette_zm_pos); - pipetteCtrlDriver.zMotorMoveToBlock(startZPos); - pipetteCtrlDriver.pipetteAspirate(0, 0, 200, 5); - pipetteCtrlDriver.pipettePumpMoveTo(1000, 0); - pipetteCtrlDriver.pipettePumpMoveTo(500, 100); + pipetteCtrlDriver.zMotorMoveToBlock(liquidPos); + pipetteCtrlDriver.liquidOperationClearParams(); // + pipetteCtrlDriver.liquidOperationSetGunRunParams(14, 14, 0, 900, 100); //pump param + pipetteCtrlDriver.liquidOperationSetZMotorRunParams(0, 300, 10); // z motor param + pipetteCtrlDriver.liquidOperationFreshParams(); - pipetteCtrlDriver.zMotorMoveToBlock(liquidZPos); - pipetteCtrlDriver.pipetteAspirate(0, 12, 50, loadUl + 50); - pipetteCtrlDriver.pipetteDistribu(0, 200, 50); - // move to distrube pos - hbotCtrlService.moveToLargeBSSamplePos(ConsumableGroup.GROUP1); - pipetteCtrlDriver.pipettePumpMoveTo(1000, 0); //分配所有液体 + ul = pipetteGunExParamMgr.calibrateVolume(ul); + log.info("取液体 {}", ul); - pipetteCtrlDriver.pipettePumpMoveTo(200, 100); //分配所有液体 - pipetteCtrlDriver.pipettePumpMoveTo(1000, 0); //分配所有液体 - - - hbotCtrlService.moveQuickToZero(); + pipetteCtrlDriver.pipetteAspirate(ul); + pipetteCtrlDriver.zMotorMoveToBlock(0); } - @ExtApiStatu(name = "val", group = "tipNum", order = 100) - public Integer readTipNum() throws AppException { - return tipNum; + public void distributeLiquid() throws AppException { + hbotCtrlService.moveToLargeBSSamplePosXY(ConsumableGroup.GROUP5); + pipetteCtrlDriver.zMotorMoveToBlock(50); + pumpMoveTo(8000, 0.0); + pipetteCtrlDriver.zMotorMoveToBlock(0); } - @ExtApiStatu(name = "val", group = "loadUl", order = 101) - public Integer readLoadUl() throws AppException { - return m_loadUl; + public void resetPos() throws AppException { + hbotCtrlService.moveToLargeBSSamplePosXY(ConsumableGroup.GROUP1); } - @ExtApiStatu(name = "val", group = "lldpThreshold", order = 102) - public Integer readLldpThreshold() throws AppException { - return lldpThreshold; + + @ExtApiFn(name = "取一次10ul", group = "测试", order = 22) + public void aspirate10ul() throws AppException { + takeTip(); + lld(); + if (liquidPos == 0) + throw AppException.ofAECodeError("未检测到液体"); + takeLiquid(10.0); + distributeLiquid(); + resetPos(); } - @ExtApiStatu(name = "val", group = "volumeCalibrationConff", order = 103) - public Double readVolumeCalibrationConff() throws AppException { - return pipetteCtrlDriver.getVolumeCalibrationCoefficient(); + @ExtApiFn(name = "取一次75ul", group = "测试", order = 23) + public void aspirate75ul() throws AppException { + takeTip(); + lld(); + if (liquidPos == 0) + throw AppException.ofAECodeError("未检测到液体"); + takeLiquid(75.0); + distributeLiquid(); + resetPos(); } + }