diff --git a/.gitignore b/.gitignore index 3943326..0e1d2c2 100644 --- a/.gitignore +++ b/.gitignore @@ -35,4 +35,5 @@ build/ runenv/ tmp/ -app.db \ No newline at end of file +app.db +!/bak/app.db \ No newline at end of file diff --git a/bak/app.db b/bak/app.db new file mode 100644 index 0000000..0a50e82 Binary files /dev/null and b/bak/app.db differ diff --git a/src/main/java/a8k/app/service/lowerctrl/LiquidOperationCtrlService.java b/src/main/java/a8k/app/service/lowerctrl/LiquidOperationCtrlService.java index fa17c1c..10d3fe0 100644 --- a/src/main/java/a8k/app/service/lowerctrl/LiquidOperationCtrlService.java +++ b/src/main/java/a8k/app/service/lowerctrl/LiquidOperationCtrlService.java @@ -147,12 +147,12 @@ public class LiquidOperationCtrlService { //lld // //清空tip中的液体和空气,同时预先吸入部分空气,以便后续清空由于lld吸入的液体,提高lld的准确性 - lddprepare(); - ldd(largeBottlePos.z, 1000, 30); - if (pipetteCtrlDriver.lldIsDetectLiquid() && gstate.isInMode(DeviceRunMode.RealMode)) { - throw AppException.of(A8kEcode.APPE_TAKE_LARGE_BUFFER_LIQUID_FAIL); - } - liquidLevel = pipetteCtrlDriver.getReg(PipetteRegIndex.kreg_pipette_zm_pos); + // lddprepare(); + // ldd(largeBottlePos.z, 1000, 30); + // if (pipetteCtrlDriver.lldIsDetectLiquid() && gstate.isInMode(DeviceRunMode.RealMode)) { + // throw AppException.of(A8kEcode.APPE_TAKE_LARGE_BUFFER_LIQUID_FAIL); + // } +// liquidLevel = pipetteCtrlDriver.getReg(PipetteRegIndex.kreg_pipette_zm_pos); pipetteCtrlDriver.zMotorMoveToBlock(0); pumpMoveTo(8000, 0.0); @@ -223,13 +223,13 @@ public class LiquidOperationCtrlService { //清空tip中的液体和空气,同时预先吸入部分空气,以便后续清空由于lld吸入的液体,提高lld的准确性 lddprepare(); ldd(sampleStartPos.z, sampleEndZPos, 20); - if (!pipetteCtrlDriver.lldIsDetectLiquid() && gstate.isInMode(DeviceRunMode.RealMode)) { - throw AppException.of(A8kEcode.APPE_TAKE_SAMPLE_FAIL); - } + // if (!pipetteCtrlDriver.lldIsDetectLiquid() && gstate.isInMode(DeviceRunMode.RealMode)) { + // throw AppException.of(A8kEcode.APPE_TAKE_SAMPLE_FAIL); + // } //获取当前液面高度 - liquidLevel = pipetteCtrlDriver.getReg(PipetteRegIndex.kreg_pipette_zm_pos); - liquidLevel += 10;//保证液面高度 + // liquidLevel = pipetteCtrlDriver.getReg(PipetteRegIndex.kreg_pipette_zm_pos); + // liquidLevel += 10;//保证液面高度 //取样准备 pipetteCtrlDriver.zMotorMoveToBlock(sampleStartPos.z); //回到0 @@ -308,7 +308,8 @@ public class LiquidOperationCtrlService { pipetteCtrlDriver.liquidOperationClearParams(); pipetteCtrlDriver.liquidOperationSetGunRunParams(14, 14, 0, 1000, pumpvmax); pipetteCtrlDriver.liquidOperationFreshParams(); - pipetteCtrlDriver.pipettePumpMoveTo(ul); + //TODO:临时代码,屏蔽掉移液枪操作 + // pipetteCtrlDriver.pipettePumpMoveTo(ul); } private void lddprepare() throws AppException { @@ -317,8 +318,9 @@ public class LiquidOperationCtrlService { pipetteCtrlDriver.liquidOperationSetGunRunParams(14, 14, 0, 1000, 8000); pipetteCtrlDriver.liquidOperationFreshParams(); - pipetteCtrlDriver.pipettePumpMoveTo(0.0); - pipetteCtrlDriver.pipettePumpMoveTo(50.0); + //TODO:临时代码,屏蔽掉移液枪操作 + // pipetteCtrlDriver.pipettePumpMoveTo(0.0); + // pipetteCtrlDriver.pipettePumpMoveTo(50.0); } @@ -332,7 +334,8 @@ public class LiquidOperationCtrlService { pipetteCtrlDriver.liquidOperationSetZMotorRunParams(0, maxpos, lldZmotorVmax); pipetteCtrlDriver.liquidOperationFreshParams(); - pipetteCtrlDriver.pipetteLld(LldType.kplld, 0, p_threshold); + //TODO:临时代码,屏蔽掉移液枪操作 + // pipetteCtrlDriver.pipetteLld(LldType.kplld, 0, p_threshold); } private void makeReserveAir(Integer ul) throws AppException { @@ -340,8 +343,9 @@ public class LiquidOperationCtrlService { pipetteCtrlDriver.liquidOperationSetGunRunParams(14, 14, 0, 1000, 8000); pipetteCtrlDriver.liquidOperationFreshParams(); - pipetteCtrlDriver.pipettePumpMoveTo(0.0); - pipetteCtrlDriver.pipettePumpMoveTo(Double.valueOf(ul)); + //TODO:临时代码,屏蔽掉移液枪操作 + // pipetteCtrlDriver.pipettePumpMoveTo(0.0); + // pipetteCtrlDriver.pipettePumpMoveTo(Double.valueOf(ul)); } @@ -362,7 +366,9 @@ public class LiquidOperationCtrlService { Double realul = pipetteGunExParamMgr.calibrateVolume(ul); // Double realul = ul; - pipetteCtrlDriver.pipetteAspirate(realul); + + //TODO:临时代码,屏蔽掉移液枪操作 + // pipetteCtrlDriver.pipetteAspirate(realul); } private void shakeUp(Integer ul, Integer times) throws AppException { @@ -370,7 +376,9 @@ public class LiquidOperationCtrlService { pipetteCtrlDriver.liquidOperationClearParams(); pipetteCtrlDriver.liquidOperationSetGunRunParams(14, 14, 0, 1000, 8000); pipetteCtrlDriver.liquidOperationFreshParams(); - pipetteCtrlDriver.pipetteShakeUp((double) ul, times); + // pipetteCtrlDriver.pipetteShakeUp((double) ul, times); + //TODO:临时代码,屏蔽掉移液枪操作 + // pipetteCtrlDriver.pipetteAspirate(realul); } diff --git a/src/main/java/a8k/app/service/lowerctrl/LiquidOperationCtrlServiceBak.java b/src/main/java/a8k/app/service/lowerctrl/LiquidOperationCtrlServiceBak.java new file mode 100644 index 0000000..d96a890 --- /dev/null +++ b/src/main/java/a8k/app/service/lowerctrl/LiquidOperationCtrlServiceBak.java @@ -0,0 +1,377 @@ +package a8k.app.service.lowerctrl; + + +import a8k.app.dao.type.combination.ProjBuildinInfo; +import a8k.app.dao.type.db.ProjExtInfoCard; +import a8k.app.hardware.driver.PipetteCtrlDriver; +import a8k.app.hardware.type.A8kEcode; +import a8k.app.hardware.type.LldType; +import a8k.app.hardware.type.PipetteRegIndex; +import a8k.app.service.param.exparam.HbotConsumableExParamMgr; +import a8k.app.service.param.hbotpos.HbotSamplePosParamMgr; +import a8k.app.service.param.pipetteparam.PipetteGunExParamMgr; +import a8k.app.service.param.pipetteparam.PipetteGunLLFParamMgr; +import a8k.app.service.statemgr.ConsumablesMgrService; +import a8k.app.service.statemgr.GStateMgrService; +import a8k.app.service.utils.ZAppChecker; +import a8k.app.type.DeviceRunMode; +import a8k.app.type.a8k.ConsumableType; +import a8k.app.type.a8k.Pos3d; +import a8k.app.type.a8k.pos.LargeBufferPos; +import a8k.app.type.a8k.pos.PreReactionPos; +import a8k.app.type.a8k.pos.TipGroupPos; +import a8k.app.type.a8k.pos.TipPos; +import a8k.app.type.exception.AppException; +import a8k.app.type.param.type.A8kSamplePos; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +@Component +@Slf4j +public class LiquidOperationCtrlServiceBak { + static public final Integer lldZmotorVmax = 50; + static public final Integer lldGunPumpVmax = 50; + static public final Integer aspiratePumpVmax = 100; + static public final Integer reactionVolumeUL = 75; + static public final Integer mixVolumeUL = 200; + + @Resource + GStateMgrService gstate; + + /* + * CTRL-SERVICE + */ + @Resource + HbotMoveExCtrlService hbotMoveExCtrlService; + @Resource + PipetteCtrlDriver pipetteCtrlDriver; + + /* + * PARAM-MGR + */ + @Resource + HbotConsumableExParamMgr hbotConsumableExParamMgr; + @Resource + PipetteGunLLFParamMgr pipetteGunLLFParamMgr; + @Resource + PipetteGunExParamMgr pipetteGunExParamMgr; + + /** + * StateMgr + */ + @Resource + ConsumablesMgrService consumablesMgrService; + @Resource + HbotSamplePosParamMgr hbotSamplePosParamMgr; + + + ProjBuildinInfo projBuildinInfo; + ProjExtInfoCard projExtInfo; + + + synchronized public void setProjContext(ProjBuildinInfo projBuildinInfo, ProjExtInfoCard projExtInfo) { + this.projBuildinInfo = projBuildinInfo; + this.projExtInfo = projExtInfo; + } + + + /** + * 取TIP + * @param group TIP组 + * @param index TIP序号 + * @throws AppException 异常 + */ + public void takeTip(TipGroupPos group, Integer index) throws AppException { + // 移动到取TIP位 + TipPos tipPos = new TipPos(); + tipPos.group = group; + tipPos.index = index; + hbotMoveExCtrlService.takeTip(tipPos); + } + + public void forceTakeTip() throws AppException { + if (hbotMoveExCtrlService.isHasTip()) { + return; + } + while (true) { + hbotMoveExCtrlService.takeTip(consumablesMgrService.takeNextTipPos()); + if (gstate.isInMode(DeviceRunMode.RunOnlyMode)) { + break; + } + if (hbotMoveExCtrlService.isHasTip()) { + break; + } + } + } + + public void dropTip() throws AppException { + hbotMoveExCtrlService.dropTip(); + } + + public Boolean checkTipIsExist(TipPos tipPos) throws AppException { + return hbotMoveExCtrlService.checkIfTipExist(tipPos.group, tipPos.index); + } + + /** + * 取大瓶缓冲液到探测物质位置(不接触分配) + * @param from 大瓶缓冲液 + * @param topos 探测物质位置 + * @param ul 吸取量 + */ + public void takeLargeBottleBufferLiquidToProbeSubstance(LargeBufferPos from, PreReactionPos topos, Integer ul) throws AppException { + // 取TIP + forceTakeTip(); + + // 检查是否有TIP + ZAppChecker.check(pipetteCtrlDriver.isHasTip(), A8kEcode.CODEERROR, "未检测到TIP"); + Pos3d largeBottleEndPos = hbotConsumableExParamMgr.getLargeBufferSamplePosEnd(from.group); + Pos3d largeBottlePos = hbotConsumableExParamMgr.getLargeBufferSamplePos(from.group); + Integer liquidLevel = 0; + + + // + // 刺破探测物质 + // + Pos3d piercePos = hbotConsumableExParamMgr.getProbeSubstancePiercePos(topos.group, topos.index); + hbotMoveExCtrlService.moveTo(piercePos); + pipetteCtrlDriver.zMotorMoveToBlock(0); + + + // + // 移动到取样位 + // + hbotMoveExCtrlService.moveToXY(largeBottlePos); + + // + //lld + // + //清空tip中的液体和空气,同时预先吸入部分空气,以便后续清空由于lld吸入的液体,提高lld的准确性 + lddprepare(); + ldd(largeBottlePos.z, 1000, 30); + if (pipetteCtrlDriver.lldIsDetectLiquid() && gstate.isInMode(DeviceRunMode.RealMode)) { + throw AppException.of(A8kEcode.APPE_TAKE_LARGE_BUFFER_LIQUID_FAIL); + } + liquidLevel = pipetteCtrlDriver.getReg(PipetteRegIndex.kreg_pipette_zm_pos); + pipetteCtrlDriver.zMotorMoveToBlock(0); + pumpMoveTo(8000, 0.0); + + // + //取样 + // + pipetteCtrlDriver.zMotorMoveToBlock(liquidLevel); + if (ul < 100) { + pumpMoveTo(8000, 50.0);//预先吸入部分空气 + } else { + pumpMoveTo(8000, 25.0);//预先吸入部分空气 + } + + aspirate(largeBottleEndPos.z, aspiratePumpVmax, pipetteGunLLFParamMgr.getLargeBSBottleLlfVel(), ul * 1.0); + pipetteCtrlDriver.zMotorMoveToBlock(0); + + // + // 移动到探测物质的位置 + // + Pos3d toCPos = hbotConsumableExParamMgr.getProbeSubstanceSamplePos(topos.group, topos.index); + hbotMoveExCtrlService.moveTo(toCPos); + pumpMoveTo(8000, 0.0); + pipetteCtrlDriver.zMotorMoveToBlock(0); + + // + // 丢弃TIP + // + hbotMoveExCtrlService.initPipetterGun(); + hbotMoveExCtrlService.moveQuickToZero(); + } + + private Pos3d getPreReactionPos(PreReactionPos pos) { + Pos3d toCPos = null; + if (pos.type.equals(ConsumableType.ProbeSubstance)) { + toCPos = hbotConsumableExParamMgr.getProbeSubstanceSamplePos(pos.group, pos.index); + } else { + toCPos = hbotConsumableExParamMgr.getLittleBufferSamplePos(pos.group, pos.index); + } + return toCPos; + } + + + /** + * 取样本到探测物质 + * @param from 样本位置 + * @param pos 预先反应位置P + * @param ul 吸取量 + * @throws AppException 异常 + */ + public void takeSample(A8kSamplePos from, PreReactionPos pos, Integer ul) throws AppException { + log.info("takeSampleToPreReactionPos: from={}, pos={}, ul={}ul", from, pos, ul); + // 取TIP + forceTakeTip(); + ZAppChecker.check(pipetteCtrlDriver.isHasTip(), A8kEcode.CODEERROR, "未检测到TIP"); + + // + // 取样位 + // + + // 取样 + Pos3d sampleStartPos = hbotSamplePosParamMgr.getSampleStartPos(from); + Integer sampleEndZPos = hbotSamplePosParamMgr.getSampleEndPos(from); + Integer liquidLevel = 0; + // 移动到取样位 + hbotMoveExCtrlService.moveToXY(sampleStartPos); + + //lld + //清空tip中的液体和空气,同时预先吸入部分空气,以便后续清空由于lld吸入的液体,提高lld的准确性 + lddprepare(); + ldd(sampleStartPos.z, sampleEndZPos, 20); + if (!pipetteCtrlDriver.lldIsDetectLiquid() && gstate.isInMode(DeviceRunMode.RealMode)) { + throw AppException.of(A8kEcode.APPE_TAKE_SAMPLE_FAIL); + } + + //获取当前液面高度 + liquidLevel = pipetteCtrlDriver.getReg(PipetteRegIndex.kreg_pipette_zm_pos); + liquidLevel += 10;//保证液面高度 + + //取样准备 + pipetteCtrlDriver.zMotorMoveToBlock(sampleStartPos.z); //回到0 + pumpMoveTo(8000, 0.0); //排空 + pumpMoveTo(aspiratePumpVmax, 10.0); //预先吸入部分空气 + + //取样 + pipetteCtrlDriver.zMotorMoveToBlock(liquidLevel); + aspirate(sampleEndZPos, aspiratePumpVmax, pipetteGunLLFParamMgr.getSampleLLFVel(from), ul * 1.0); + pipetteCtrlDriver.zMotorMoveToBlock(0); + + + // + // 移动到反应位 + // + log.info("move to pre reaction pos: {}", pos); + hbotMoveExCtrlService.moveTo(getPreReactionPos(pos)); + + //吐液,此过程会产生气泡,但由于气泡在液面附近,而吸吐位在液面之下,问题不大 + log.info("drop liquid"); + pumpMoveTo(200, 0.0); + + //混匀 + Integer shakeUl = mixVolumeUL; + Integer shakeTimes = 5; + if (projBuildinInfo != null) { + shakeUl = projBuildinInfo.mixedLiquidMixingVolUl; + shakeTimes = projBuildinInfo.mixedLiquidMixingTimes; + } + //摇匀 + shakeUp(shakeUl, shakeTimes); + + //z轴回0 + pipetteCtrlDriver.zMotorMoveToZeroPointQuickBlock(); + } + + public void pirceLittleBuffer(PreReactionPos pos) throws AppException { + forceTakeTip(); + + hbotMoveExCtrlService.moveToLittleBufferPiercePos(pos.group, pos.index); + pipetteCtrlDriver.zMotorMoveToBlock(0); + } + + + /** + * 取反应液到反应板上 + * @param pos 反应板位置 + * @throws AppException 异常 + */ + public void takePreReactionLiquidToReation(PreReactionPos pos) throws AppException { + log.info("takePreReactionLiquidToReactionPos: from pos={}", pos); + forceTakeTip(); + Pos3d reactionPos = getPreReactionPos(pos); + + hbotMoveExCtrlService.moveToXY(reactionPos); + pipetteCtrlDriver.zMotorMoveByBlock(0); + makeReserveAir(100); + + hbotMoveExCtrlService.moveToZ(reactionPos); + aspirate(reactionPos.z, aspiratePumpVmax, 0, (double) reactionVolumeUL); + + hbotMoveExCtrlService.moveToDropLiquidPos(); + pumpMoveTo(8000, 0.0); + + hbotMoveExCtrlService.initPipetterGun(); + hbotMoveExCtrlService.moveQuickToZero(); + } + + + // + // PRIVATE + // + + + private void pumpMoveTo(Integer pumpvmax, Double ul) throws AppException { + pipetteCtrlDriver.liquidOperationClearParams(); + pipetteCtrlDriver.liquidOperationSetGunRunParams(14, 14, 0, 1000, pumpvmax); + pipetteCtrlDriver.liquidOperationFreshParams(); + pipetteCtrlDriver.pipettePumpMoveTo(ul); + } + + private void lddprepare() throws AppException { + + pipetteCtrlDriver.liquidOperationClearParams(); + pipetteCtrlDriver.liquidOperationSetGunRunParams(14, 14, 0, 1000, 8000); + pipetteCtrlDriver.liquidOperationFreshParams(); + + pipetteCtrlDriver.pipettePumpMoveTo(0.0); + pipetteCtrlDriver.pipettePumpMoveTo(50.0); + } + + + private void ldd(Integer startpos, Integer maxpos, Integer p_threshold) throws AppException { + log.info("lld: startpos={}, maxpos={}, p_threshold={}", startpos, maxpos, p_threshold); + + pipetteCtrlDriver.zMotorMoveToBlock(startpos); + + pipetteCtrlDriver.liquidOperationClearParams(); + pipetteCtrlDriver.liquidOperationSetGunRunParams(14, 14, 0, 1000, lldGunPumpVmax); + pipetteCtrlDriver.liquidOperationSetZMotorRunParams(0, maxpos, lldZmotorVmax); + pipetteCtrlDriver.liquidOperationFreshParams(); + + pipetteCtrlDriver.pipetteLld(LldType.kplld, 0, p_threshold); + } + + private void makeReserveAir(Integer ul) throws AppException { + pipetteCtrlDriver.liquidOperationClearParams(); + pipetteCtrlDriver.liquidOperationSetGunRunParams(14, 14, 0, 1000, 8000); + pipetteCtrlDriver.liquidOperationFreshParams(); + + pipetteCtrlDriver.pipettePumpMoveTo(0.0); + pipetteCtrlDriver.pipettePumpMoveTo(Double.valueOf(ul)); + } + + + /** + * 在当前位置吸取液体 + * @param maxpos 最大位置 + * @param gunv 枪速 + * @param zv z轴速度 + * @param ul 吸取量 + * @throws AppException 异常 + */ + private void aspirate(Integer maxpos, int gunv, int zv, Double ul) throws AppException { + log.info("aspirate: maxpos={}, gunv={}, zv={}, ul={}", maxpos, gunv, zv, ul); + pipetteCtrlDriver.liquidOperationClearParams(); + pipetteCtrlDriver.liquidOperationSetGunRunParams(14, 14, 0, 1000, gunv); + pipetteCtrlDriver.liquidOperationSetZMotorRunParams(0, maxpos, zv); + pipetteCtrlDriver.liquidOperationFreshParams(); + + Double realul = pipetteGunExParamMgr.calibrateVolume(ul); + // Double realul = ul; + pipetteCtrlDriver.pipetteAspirate(realul); + } + + private void shakeUp(Integer ul, Integer times) throws AppException { + log.info("shakeUp: ul={}, times={}", ul, times); + pipetteCtrlDriver.liquidOperationClearParams(); + pipetteCtrlDriver.liquidOperationSetGunRunParams(14, 14, 0, 1000, 8000); + pipetteCtrlDriver.liquidOperationFreshParams(); + pipetteCtrlDriver.pipetteShakeUp((double) ul, times); + } + + +}