|
|
@ -10,12 +10,16 @@ import a8k.canbus.protocol.MId; |
|
|
|
import a8k.canbus.protocol.RegIndex; |
|
|
|
import a8k.service.db.entity.HardwareServiceSetting; |
|
|
|
import a8k.utils.*; |
|
|
|
import com.fasterxml.jackson.databind.ObjectMapper; |
|
|
|
import jakarta.annotation.Resource; |
|
|
|
import org.slf4j.Logger; |
|
|
|
import org.slf4j.LoggerFactory; |
|
|
|
import org.springframework.context.ApplicationContext; |
|
|
|
import org.springframework.stereotype.Component; |
|
|
|
|
|
|
|
import java.util.HashMap; |
|
|
|
import java.util.Map; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* Hbot控制服务 |
|
|
@ -43,6 +47,11 @@ public class HbotControlService implements HardwareCtrlModule { |
|
|
|
return settingReader.getInteger("ActionOvertime", 10000); |
|
|
|
} |
|
|
|
|
|
|
|
@HardwareServiceParam(name = "归零超时事件", group = "基础配置") |
|
|
|
public Integer getRuntoZeroActionOvertime() { |
|
|
|
return settingReader.getInteger("RuntoZeroActionOvertime", 20000); |
|
|
|
} |
|
|
|
|
|
|
|
@HardwareServiceParam(name = "扫码超时时间", group = "基础配置") |
|
|
|
public Integer getScancodeOvertime() { |
|
|
|
return settingReader.getInteger("ActionOvertime", 1000); |
|
|
@ -61,21 +70,21 @@ public class HbotControlService implements HardwareCtrlModule { |
|
|
|
public TipPickUpPosInfo getTipPickUpPosInfo() { |
|
|
|
return settingReader.getObject("TipPickUpPosInfo", TipPickUpPosInfo.class, |
|
|
|
new TipPickUpPosInfo( |
|
|
|
new Pos2d(903, -11), |
|
|
|
new Pos2d(0, 0), |
|
|
|
new Pos2d(0, 0), |
|
|
|
92.4, |
|
|
|
92.4, |
|
|
|
0)); |
|
|
|
new Pos2d(887, -15), |
|
|
|
new Pos2d(887, -15), |
|
|
|
new Pos2d(887, -15), |
|
|
|
92, |
|
|
|
92, |
|
|
|
585)); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@HardwareServiceParam(name = "Tip丢弃位置", group = "简单位置坐标") |
|
|
|
public Pos3d getTipDropPos() { |
|
|
|
return new Pos3d( |
|
|
|
0, |
|
|
|
0, |
|
|
|
0 |
|
|
|
4873, |
|
|
|
2563, |
|
|
|
661 |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
@ -139,14 +148,22 @@ public class HbotControlService implements HardwareCtrlModule { |
|
|
|
return settingReader.getInteger("CommonAreaYLimit", 0); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@HardwareServiceParam(name = "Hbot采样区", group = "限制值") |
|
|
|
public HbotLimitArea getSampleCollectionArea() { |
|
|
|
return settingReader.getObject("HbotPublicArea", HbotLimitArea.class, |
|
|
|
new HbotLimitArea(0, 0, 601, 3151)); |
|
|
|
} |
|
|
|
|
|
|
|
public Integer getGripperZeroYPos() { |
|
|
|
//之所以这样写,是因为是为了放置两个类之间的循环依赖 |
|
|
|
return appCxt.getBean(SamplesPreProcessModuleCtrlService.class).getGripperZeroYPos(); |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
|
* 基础方法 |
|
|
|
*/ |
|
|
|
|
|
|
|
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
|
|
|
// 基础控制 |
|
|
|
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
|
|
|
private void checkPublicArea() throws HardwareException { |
|
|
|
if (canBus.miniServoReadPos(MId.ShakeModGripperYSV) > getGripperZeroYPos() + 20) { |
|
|
|
logger.error("ShakeModGripperYSV Pos:{} > {}", canBus.miniServoReadPos(MId.ShakeModGripperYSV), getGripperZeroYPos() + 20); |
|
|
@ -154,24 +171,55 @@ public class HbotControlService implements HardwareCtrlModule { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private void checkBeforeHbotRun(Pos2d targetPos) throws HardwareException { |
|
|
|
/** |
|
|
|
* Hboot 移动 |
|
|
|
* @param targetPos 目标位置 |
|
|
|
* @throws HardwareException e |
|
|
|
* @throws InterruptedException e |
|
|
|
*/ |
|
|
|
private void hbotCheckAndMoveTo(Pos3d targetPos) throws HardwareException, InterruptedException { |
|
|
|
if (!canBus.getIOState(IOId.PlateBoxCoverClosurePPS)) { |
|
|
|
throw new HardwareException(A8kEcode.PlateBoxNotCover); |
|
|
|
} |
|
|
|
|
|
|
|
if (targetPos.y > getCommonAreaYLimit()) { |
|
|
|
checkPublicArea(); |
|
|
|
} |
|
|
|
//Z轴归零 |
|
|
|
canBus.stepMotorEnable(MId.PipetteModZM, 1); |
|
|
|
canBus.stepMotorEasyMoveToZeroPointQuickBlock(MId.PipetteModZM, getActionOvertime()); |
|
|
|
|
|
|
|
if (!getZPPS()) { |
|
|
|
throw new HardwareException(A8kEcode.ZMNotAtZPosWhenHbotTryMove); |
|
|
|
} |
|
|
|
Pos2d nowHbotPos = canBus.hbotReadPos(MId.HbotM); |
|
|
|
HbotLimitArea sampleArea = getSampleCollectionArea(); |
|
|
|
|
|
|
|
//检查采样区域是否有障碍 |
|
|
|
if (sampleArea.checkIsInArea(nowHbotPos) || sampleArea.checkIsInArea(targetPos.getXYPos())) { |
|
|
|
checkPublicArea(); |
|
|
|
} |
|
|
|
|
|
|
|
//HBot移动 |
|
|
|
canBus.hbotEnable(MId.HbotM, 1); |
|
|
|
canBus.hbotMoveToBlock(MId.HbotM, targetPos.x, targetPos.y, getRuntoZeroActionOvertime()); |
|
|
|
|
|
|
|
//Z轴移动 |
|
|
|
zMoveTo(targetPos.z); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void zMoveTo(Integer z) throws HardwareException, InterruptedException { |
|
|
|
if (z == 0) { |
|
|
|
canBus.stepMotorEasyMoveToZeroPointQuickBlock(MId.PipetteModZM, getActionOvertime()); |
|
|
|
} else { |
|
|
|
canBus.stepMotorEasyMoveToBlock(MId.PipetteModZM, z, getActionOvertime()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void hbotCheckAndMoveTo(Pos2d targetPos) throws HardwareException, InterruptedException { |
|
|
|
hbotCheckAndMoveTo(new Pos3d(targetPos.x, targetPos.y, 0)); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* 下面脚本中涉及到的动作,如果正常结束,Z轴均移动的0位置。 |
|
|
|
*/ |
|
|
|
@HardwareServiceAction(name = "模块使能", group = "基础控制") |
|
|
|
@Override public void modGroupEnable(Boolean enable) throws HardwareException, InterruptedException { |
|
|
|
if (enable) { |
|
|
@ -188,30 +236,77 @@ public class HbotControlService implements HardwareCtrlModule { |
|
|
|
|
|
|
|
@HardwareServiceAction(name = "模块归零", group = "基础控制") |
|
|
|
@Override public void modGroupMoveToZero() throws HardwareException, InterruptedException { |
|
|
|
if (!canBus.getIOState(IOId.PlateBoxCoverClosurePPS)) { |
|
|
|
throw new HardwareException(A8kEcode.PlateBoxNotCover); |
|
|
|
} |
|
|
|
|
|
|
|
//归零前检查 |
|
|
|
checkPublicArea(); |
|
|
|
canBus.stepMotorEnable(MId.PipetteModZM, 1); |
|
|
|
canBus.hbotEnable(MId.HbotM, 1); |
|
|
|
canBus.stepMotorEasyMoveToZeroBlock(MId.PipetteModZM, getRuntoZeroActionOvertime()); |
|
|
|
|
|
|
|
canBus.stepMotorEasyMoveToZeroBlock(MId.PipetteModZM, getActionOvertime()); |
|
|
|
//丢弃tip |
|
|
|
Pos3d dropPos = getTipDropPos(); |
|
|
|
hbotCheckAndMoveTo(dropPos); |
|
|
|
canBus.pipetteCtrlInitDeviceBlock(MId.PipetteMod, getRuntoZeroActionOvertime()); |
|
|
|
|
|
|
|
checkBeforeHbotRun(new Pos2d(0, 0)); |
|
|
|
canBus.hbotMoveToZeroBlock(MId.HbotM, getActionOvertime()); |
|
|
|
//快速归零 |
|
|
|
modGroupMoveToZeroQuick(); |
|
|
|
} |
|
|
|
|
|
|
|
@HardwareServiceAction(name = "模块快速归零", group = "基础控制") |
|
|
|
@Override public void modGroupMoveToZeroQuick() throws HardwareException, InterruptedException { |
|
|
|
checkPublicArea(); |
|
|
|
canBus.stepMotorEnable(MId.PipetteModZM, 1); |
|
|
|
canBus.hbotEnable(MId.HbotM, 1); |
|
|
|
hbotCheckAndMoveTo(new Pos2d(0, 0)); |
|
|
|
} |
|
|
|
|
|
|
|
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
|
|
|
// 单步测试 |
|
|
|
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
|
|
|
|
|
|
|
@HardwareServiceAction(name = "丢Tip", group = "单步测试") |
|
|
|
public void dropTip() throws HardwareException, InterruptedException { |
|
|
|
Pos3d pos = getTipDropPos(); |
|
|
|
hbotMoveTo(pos.x, pos.y); |
|
|
|
zMoveTo(pos.z); |
|
|
|
canBus.pipetteCtrlPutTip(MId.PipetteMod); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
@HardwareServiceAction(name = "取Tip", group = "单步测试") |
|
|
|
public AppRet<Boolean> takeTip(Integer groupId, Integer index) throws HardwareException, InterruptedException { |
|
|
|
logger.info("takeTip groupId:{} index:{}", groupId, index); |
|
|
|
if (groupId > 2 || groupId < 0) { |
|
|
|
throw new HardwareException(A8kEcode.ParamOutOfRange); |
|
|
|
} |
|
|
|
|
|
|
|
if (index > TipPickUpPosInfo.ROW_MAX * TipPickUpPosInfo.COL_MAX || index < 0) { |
|
|
|
throw new HardwareException(A8kEcode.ParamOutOfRange); |
|
|
|
} |
|
|
|
|
|
|
|
TipPickUpPosInfo tipPos = getTipPickUpPosInfo(); |
|
|
|
Pos2d pos = tipPos.getTipPos(groupId, index); |
|
|
|
hbotMoveTo(pos.x, pos.y); |
|
|
|
|
|
|
|
canBus.stepMotorEasyMoveToBlock(MId.PipetteModZM, tipPos.pickUpZPos, getActionOvertime()); |
|
|
|
canBus.stepMotorEasyMoveToZeroPointQuickBlock(MId.PipetteModZM, getActionOvertime()); |
|
|
|
|
|
|
|
checkBeforeHbotRun(new Pos2d(0, 0)); |
|
|
|
canBus.hbotMoveToBlock(MId.HbotM, 0, 0, getActionOvertime()); |
|
|
|
canBus.hbotMoveToZeroBlock(MId.HbotM, getActionOvertime()); |
|
|
|
Boolean isGetTip = canBus.moduleGetReg(MId.PipetteMod, RegIndex.kreg_pipette_tip_state) == 1; |
|
|
|
if (!isGetTip) { |
|
|
|
logger.error("takeTip fail"); |
|
|
|
} |
|
|
|
return AppRet.success(isGetTip); |
|
|
|
} |
|
|
|
|
|
|
|
@HardwareServiceAction(name = "HBot移动到", group = "单步测试") |
|
|
|
public void hbotMoveTo(Integer x, Integer y) throws HardwareException, InterruptedException { |
|
|
|
hbotCheckAndMoveTo(new Pos2d(x, y)); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
|
|
|
// 坐标获取工具 |
|
|
|
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
|
|
|
|
|
|
|
@HardwareServiceAction(name = "Hbot使能", group = "坐标获取工具") |
|
|
|
public void hBotEnable() throws HardwareException, InterruptedException { |
|
|
|
canBus.hbotEnable(MId.HbotM, 1); |
|
|
@ -232,74 +327,47 @@ public class HbotControlService implements HardwareCtrlModule { |
|
|
|
canBus.stepMotorEnable(MId.PipetteModZM, 0); |
|
|
|
} |
|
|
|
|
|
|
|
@HardwareServiceAction(name = "读取Z轴坐标", group = "坐标获取工具") |
|
|
|
@HardwareServiceAction(name = "归零读取Z轴坐标", group = "坐标获取工具") |
|
|
|
public AppRet<Integer> readZAxisPosByMoveToZero() throws HardwareException, InterruptedException { |
|
|
|
return AppRet.success(canBus.stepMotorReadPosByMoveToZeroBlock(MId.PipetteModZM, getActionOvertime())); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@HardwareServiceAction(name = "HBot移动到", group = "基础控制") |
|
|
|
public void hbotMoveTo(Integer x, Integer y) throws HardwareException, InterruptedException { |
|
|
|
checkPublicArea(); |
|
|
|
checkBeforeHbotRun(new Pos2d(x, y)); |
|
|
|
|
|
|
|
canBus.hbotEnable(MId.HbotM, 1); |
|
|
|
|
|
|
|
canBus.hbotMoveToBlock(MId.HbotM, x - 20, y - 20, getActionOvertime()); |
|
|
|
canBus.hbotMoveToBlock(MId.HbotM, x, y - 15, getActionOvertime()); |
|
|
|
// Thread.sleep(200); |
|
|
|
canBus.hbotMoveToBlock(MId.HbotM, x, y, getActionOvertime()); |
|
|
|
} |
|
|
|
|
|
|
|
public void zMoveTo(Integer z) throws HardwareException, InterruptedException { |
|
|
|
canBus.stepMotorEasyMoveToBlock(MId.PipetteModZM, z, getActionOvertime()); |
|
|
|
} |
|
|
|
|
|
|
|
//取tip |
|
|
|
@HardwareServiceAction(name = "取Tip", group = "单步操作") |
|
|
|
public AppRet<Boolean> takeTip(Integer groupId, Integer index) throws HardwareException, InterruptedException { |
|
|
|
logger.info("takeTip groupId:{} index:{}", groupId, index); |
|
|
|
if (groupId > 2 || groupId < 0) { |
|
|
|
throw new HardwareException(A8kEcode.ParamOutOfRange); |
|
|
|
} |
|
|
|
|
|
|
|
if (index > TipPickUpPosInfo.ROW_MAX * TipPickUpPosInfo.COL_MAX || index < 0) { |
|
|
|
throw new HardwareException(A8kEcode.ParamOutOfRange); |
|
|
|
} |
|
|
|
|
|
|
|
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
|
|
|
// 测试 |
|
|
|
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
|
|
|
Boolean testTakeTipFlag; |
|
|
|
private AppRet<Boolean> takeTipTestStep(Integer groupId, Integer index) throws HardwareException, InterruptedException { |
|
|
|
var ret = takeTip(groupId, index); |
|
|
|
TipPickUpPosInfo tipPos = getTipPickUpPosInfo(); |
|
|
|
Pos2d pos = tipPos.getTipPos(groupId, index); |
|
|
|
hbotMoveTo(pos.x, pos.y); |
|
|
|
|
|
|
|
canBus.stepMotorEasyMoveToBlock(MId.PipetteModZM, tipPos.pickUpZPos, getActionOvertime()); |
|
|
|
canBus.stepMotorEasyMoveToBlock(MId.PipetteModZM, tipPos.pickUpZPos - 100, getActionOvertime()); |
|
|
|
canBus.pipetteCtrlPutTipBlock(MId.PipetteMod); |
|
|
|
canBus.stepMotorEasyMoveToZeroPointQuickBlock(MId.PipetteModZM, getActionOvertime()); |
|
|
|
return ret; |
|
|
|
} |
|
|
|
|
|
|
|
Boolean isGetTip = canBus.moduleGetReg(MId.PipetteMod, RegIndex.kreg_pipette_tip_state) == 1; |
|
|
|
if (!isGetTip) { |
|
|
|
logger.error("takeTip fail"); |
|
|
|
@HardwareServiceAction(name = "取全部Tip", group = "测试脚本") |
|
|
|
public AppRet<Map<String, String>> testTakeAllTip(Integer group, Integer startFrom) throws HardwareException, InterruptedException { |
|
|
|
// ObjectMapper mapper = new ObjectMapper(); |
|
|
|
testTakeTipFlag = true; |
|
|
|
Map<String, String> result = new HashMap<>(); |
|
|
|
for (int i = startFrom; i < TipPickUpPosInfo.COL_MAX * TipPickUpPosInfo.ROW_MAX; i++) { |
|
|
|
var ret = takeTipTestStep(group, i); |
|
|
|
result.put("Tip" + i, ret.getData() ? "suc" : "fail"); |
|
|
|
logger.info("Take Tip {}-{} => {}", group, i, ret.getData()); |
|
|
|
if (!testTakeTipFlag) { |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
return AppRet.success(isGetTip); |
|
|
|
return AppRet.success(result); |
|
|
|
} |
|
|
|
|
|
|
|
@HardwareServiceAction(name = "取Tip测试", group = "测试") |
|
|
|
public AppRet<Boolean> takeTipTest(Integer groupId, Integer index) throws HardwareException, InterruptedException { |
|
|
|
var ret = takeTip(groupId, index); |
|
|
|
TipPickUpPosInfo tipPos = getTipPickUpPosInfo(); |
|
|
|
|
|
|
|
canBus.stepMotorEasyMoveToBlock(MId.PipetteModZM, tipPos.pickUpZPos, getActionOvertime()); |
|
|
|
canBus.pipetteCtrlPutTip(MId.PipetteMod); |
|
|
|
canBus.stepMotorEasyMoveToZeroPointQuickBlock(MId.PipetteModZM, getActionOvertime()); |
|
|
|
return ret; |
|
|
|
@HardwareServiceAction(name = "停止取全部Tip", group = "测试脚本") |
|
|
|
public void testTakeAllTipStop() throws HardwareException, InterruptedException { |
|
|
|
testTakeTipFlag = false; |
|
|
|
} |
|
|
|
|
|
|
|
//丢tip |
|
|
|
@HardwareServiceAction(name = "丢Tip", group = "单步操作") |
|
|
|
public void dropTip() throws HardwareException, InterruptedException { |
|
|
|
Pos3d pos = getTipDropPos(); |
|
|
|
hbotMoveTo(pos.x, pos.y); |
|
|
|
zMoveTo(pos.z); |
|
|
|
canBus.pipetteCtrlPutTip(MId.PipetteMod); |
|
|
|
} |
|
|
|
|
|
|
|
private AppRet<String> hBotMoveToAndScan(Pos2d pos) throws HardwareException, InterruptedException { |
|
|
|
hbotMoveTo(pos.x, pos.y); |
|
|
@ -353,27 +421,27 @@ public class HbotControlService implements HardwareCtrlModule { |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// @HardwareServiceStatus(name = "Z轴光电⬆") |
|
|
|
@HardwareServiceStatus(name = "Z轴光电⬆") |
|
|
|
public Boolean getZPPS() throws HardwareException { |
|
|
|
return canBus.stepMotorReadIoState(MId.PipetteModZM, 0); |
|
|
|
} |
|
|
|
|
|
|
|
// @HardwareServiceStatus(name = "X轴光电➡") |
|
|
|
@HardwareServiceStatus(name = "X轴光电➡") |
|
|
|
public Boolean getXPPS() throws HardwareException { |
|
|
|
return canBus.hbotReadInio(MId.HbotM, 0); |
|
|
|
} |
|
|
|
|
|
|
|
// @HardwareServiceStatus(name = "Y轴光电⬇") |
|
|
|
@HardwareServiceStatus(name = "Y轴光电⬇") |
|
|
|
public Boolean getYPPS() throws HardwareException { |
|
|
|
return canBus.hbotReadInio(MId.HbotM, 1); |
|
|
|
} |
|
|
|
|
|
|
|
// @HardwareServiceStatus(name = "TipState") |
|
|
|
// public Boolean getTipPPS() throws HardwareException { |
|
|
|
// return canBus.moduleGetReg(MId.PipetteMod, RegIndex.kreg_pipette_tip_state) == 1; |
|
|
|
// } |
|
|
|
// @HardwareServiceStatus(name = "TipState") |
|
|
|
public Boolean getTipPPS() throws HardwareException { |
|
|
|
return canBus.moduleGetReg(MId.PipetteMod, RegIndex.kreg_pipette_tip_state) == 1; |
|
|
|
} |
|
|
|
|
|
|
|
// @HardwareServiceStatus(name = "HbotPos") |
|
|
|
@HardwareServiceStatus(name = "HbotPos") |
|
|
|
public String getPos() throws HardwareException { |
|
|
|
Pos2d pos = canBus.hbotReadPos(MId.HbotM); |
|
|
|
return pos.toString(); |
|
|
|