From 67130a56608ce69a33d24e6a8c2c3eba7f0981da Mon Sep 17 00:00:00 2001 From: sige Date: Fri, 10 May 2024 17:10:11 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A4=A7=E7=BC=93=E5=86=B2=E6=B6=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iflytop/a800/controller/DemoController.java | 9 +++ src/main/java/com/iflytop/a800/device/Device.java | 3 + src/main/java/com/iflytop/a800/device/Pipette.java | 72 +++++++++++++++++++++- .../com/iflytop/a800/resource/LargeBufferTube.java | 6 ++ .../a800/resource/LargeBufferTubeManager.java | 29 +++++++++ 5 files changed, 116 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/iflytop/a800/resource/LargeBufferTube.java create mode 100644 src/main/java/com/iflytop/a800/resource/LargeBufferTubeManager.java diff --git a/src/main/java/com/iflytop/a800/controller/DemoController.java b/src/main/java/com/iflytop/a800/controller/DemoController.java index 86a1dba..140ffd0 100644 --- a/src/main/java/com/iflytop/a800/controller/DemoController.java +++ b/src/main/java/com/iflytop/a800/controller/DemoController.java @@ -32,4 +32,13 @@ public class DemoController extends UfApiControllerBase { pipette.dispense(tube); return this.success(); } + + @PostMapping("/api/demo/pipette-aspirate-from-large-buffer-tube") + @ResponseBody + public UfApiResponse pipetteAspirateFromLargeBufferTube() { + var tube = Device.getInstance().largeBufferTube.getTube(); + var pipette = Device.getInstance().pipette; + pipette.aspirateFromLargeBufferTube(tube, 50); + return this.success(); + } } diff --git a/src/main/java/com/iflytop/a800/device/Device.java b/src/main/java/com/iflytop/a800/device/Device.java index fbd9b65..276a79e 100644 --- a/src/main/java/com/iflytop/a800/device/Device.java +++ b/src/main/java/com/iflytop/a800/device/Device.java @@ -1,6 +1,7 @@ package com.iflytop.a800.device; import com.iflytop.a800.resource.BufferTubeManager; +import com.iflytop.a800.resource.LargeBufferTubeManager; public class Device { // singleton instance @@ -11,6 +12,8 @@ public class Device { public final Pipette pipette = new Pipette(); // buffer tube manager public final BufferTubeManager bufferTube = new BufferTubeManager(); + // large buffer tube manager + public final LargeBufferTubeManager largeBufferTube = new LargeBufferTubeManager(); // get instance public static Device getInstance() { diff --git a/src/main/java/com/iflytop/a800/device/Pipette.java b/src/main/java/com/iflytop/a800/device/Pipette.java index 818f800..5112120 100644 --- a/src/main/java/com/iflytop/a800/device/Pipette.java +++ b/src/main/java/com/iflytop/a800/device/Pipette.java @@ -1,5 +1,6 @@ package com.iflytop.a800.device; import com.iflytop.a800.resource.BufferTube; +import com.iflytop.a800.resource.LargeBufferTube; import com.iflytop.uf.UfActuatorCmdExecutor; import com.iflytop.uf.UfCmdSnippetExecutor; import com.iflytop.uf.model.UfMdbOption; @@ -19,9 +20,9 @@ public class Pipette { // public Pipette() { - this.tipAmountList.add(0); - this.tipAmountList.add(0); - this.tipAmountList.add(0); + this.tipAmountList.add(120); + this.tipAmountList.add(120); + this.tipAmountList.add(120); } // set tip amount @@ -137,4 +138,69 @@ public class Pipette { } UfCmdSnippetExecutor.execute(snippetKey, dispenseParams); } + + // 从大缓冲液管吸液 + public void aspirateFromLargeBufferTube(LargeBufferTube tube, Integer volume) { + Integer startX = UfMdbOption.getInteger("LargeBufferTubeZoneStartX"); + Integer startY = UfMdbOption.getInteger("LargeBufferTubeZoneStartY"); + Integer distanceX = UfMdbOption.getInteger("LargeBufferTubeDistanceX"); + Integer distanceY = UfMdbOption.getInteger("LargeBufferTubeDistanceY"); + Integer indexX = tube.index % 3; + Integer indexY = tube.index / 3; + Integer tubeX = startX + indexX * distanceX; + Integer tubeY = startY + indexY * distanceY; + Map dispenseParams = Map.of("tubeX", tubeX, "tubeY", tubeY); + + String snippetKey = "PipetteAspirateFromLargeBufferTubePrepare"; + UfCmdSnippetExecutor.execute(snippetKey, dispenseParams); + + var maxDepth = UfMdbOption.getInteger("LargeBufferTubeLiquidDetectMaxDepth"); + var threshold = UfMdbOption.getInteger("LargeBufferTubeLiquidDetectThreshold"); + this.moveToLiquidLevel(maxDepth, threshold); + + Double coefficient = UfMdbOption.getDouble("LargeBufferTubeLiquidLevelFollowCoefficient"); + Integer depth = (int)(coefficient * volume); + this.aspirateWithLiquidLevelFollow(volume, depth); + } + + // 移动到液面 + private void moveToLiquidLevel( Integer maxDepth, Integer threshold ) { + int stepDepth = 10; + int depth = 0; + do { + String capValStr = UfActuatorCmdExecutor.execute("Pipette", "read_pipette_capacitance_val"); + int capVal = Integer.parseInt(capValStr); + if ( capVal > threshold ) { + break; + } + + depth += stepDepth; + if ( depth > maxDepth ) { + UfCmdSnippetExecutor.execute("ArmResetZ"); + throw new RuntimeException("未检测到液面"); + } + UfActuatorCmdExecutor.execute("ArmZ", "motor_easy_move_by", Integer.toString(stepDepth)); + } while (true); + } + + // 吸液并跟随液面 + private void aspirateWithLiquidLevelFollow( Integer volume, Integer depth ) { + String moveByParams = String.format("%d,%d,%d", depth, 300, 5); + Thread threadArmZMove = new Thread(() -> { + UfActuatorCmdExecutor.execute("ArmZ", "motor_move_by", moveByParams); + }); + Thread threadAspirate = new Thread(() -> { + UfActuatorCmdExecutor.execute("Pipette", "pipette_ctrl_move_to_ul", Integer.toString(volume)); + }); + + threadArmZMove.start(); + threadAspirate.start(); + try { + threadArmZMove.join(); + threadAspirate.join(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + UfCmdSnippetExecutor.execute("ArmResetZ"); + } } diff --git a/src/main/java/com/iflytop/a800/resource/LargeBufferTube.java b/src/main/java/com/iflytop/a800/resource/LargeBufferTube.java new file mode 100644 index 0000000..3943bdf --- /dev/null +++ b/src/main/java/com/iflytop/a800/resource/LargeBufferTube.java @@ -0,0 +1,6 @@ +package com.iflytop.a800.resource; + +public class LargeBufferTube { + public Integer index; + public Integer quantity; +} diff --git a/src/main/java/com/iflytop/a800/resource/LargeBufferTubeManager.java b/src/main/java/com/iflytop/a800/resource/LargeBufferTubeManager.java new file mode 100644 index 0000000..c752177 --- /dev/null +++ b/src/main/java/com/iflytop/a800/resource/LargeBufferTubeManager.java @@ -0,0 +1,29 @@ +package com.iflytop.a800.resource; +import java.util.ArrayList; +import java.util.List; +public class LargeBufferTubeManager { + // tubes + public List tubes; + + // Constructor + public LargeBufferTubeManager() { + this.tubes = new ArrayList<>(); + for (int i = 0; i < 6; i++) { + var tube = new LargeBufferTube(); + tube.index = i; + tube.quantity = 3; + tubes.add(tube); + } + } + + // get tube + public LargeBufferTube getTube() { + for (LargeBufferTube tube : tubes) { + if (tube.quantity > 0) { + tube.quantity --; + return tube; + } + } + throw new RuntimeException("No tube available"); + } +}