Browse Source

update

master
zhaohe 2 months ago
parent
commit
3dbe2514e5
  1. 2
      log/死机日志.log
  2. 19
      sdk/components/pipette_module/base/pipette_action_param.hpp
  3. 8
      sdk/components/pipette_module/base/pipette_cfg.hpp
  4. 322
      sdk/components/pipette_module/pipette_ctrl_module.cpp
  5. 28
      sdk/components/pipette_module/pipette_ctrl_module.hpp
  6. 98
      sdk/components/sensors/smtp2_v2/smtp2_v2.cpp
  7. 44
      sdk/components/sensors/smtp2_v2/smtp2_v2.hpp
  8. 20
      sdk/components/tmc/ic/ztmc5130.cpp
  9. 13
      sdk/components/tmc/ic/ztmc5130.hpp
  10. 18
      sdk/components/zcan_protocol_parser/zcan_protocol_parser.cpp
  11. 3
      sdk/components/zcan_protocol_parser/zcan_protocol_parser.hpp
  12. 3
      usrc/a8000_protocol/protocol/cmdid.cpp
  13. 7
      usrc/a8000_protocol/protocol/cmdid.hpp
  14. 3
      usrc/a8000_protocol/protocol/errorcode.cpp
  15. 1
      usrc/a8000_protocol/protocol/errorcode.hpp

2
log/死机日志.log

@ -150,7 +150,7 @@
00243217 INFO [SMTP2 ] tx:/1u10,0R
00243247 INFO [SMTP2 ] rx:(6) (2F3040030D0A) /0@
00243248 INFO [SMTP2 ] pump_set_tip_size 1
00243248 INFO [SMTP2 ] pump_set_tip_type 1
00243249 INFO [SMTP2 ] tx:/1u18,1R
00243279 INFO [SMTP2 ] rx:(6) (2F3040030D0A) /0@

19
sdk/components/pipette_module/base/pipette_action_param.hpp

@ -73,4 +73,21 @@ typedef enum {
//
kaspiration_paramid_mix_volume,
kaspiration_paramid_mix_times,
} aspiration_paramid_t;
} aspiration_paramid_t;
typedef struct {
//
// 容器
//
int32_t container_pos; // 容器位置
int32_t container_info_index; // 容器配置索引
//
// 液体类型
//
int32_t liquid_cfg_index; // 液体配置索引
//
// 混匀配置
//
int32_t mix_volume; // 混匀体积
int32_t mix_times; // 混匀次数
} distribu_all_param_t;

8
sdk/components/pipette_module/base/pipette_cfg.hpp

@ -23,7 +23,7 @@ typedef struct {
int32_t tip_picking_append_distance; // 取tip时z轴的附加距离
int32_t tip_deposit_pos; // 丢tip位置(绝对位置0.1mm)
int32_t _transform_pos; // 移液枪安全移动的高度(绝对位置0.1mm)
int32_t _transform_pos; // 移液枪安全移动的高度(绝对位置0.1mm)
/**
* @brief tip类型
*
@ -70,7 +70,7 @@ typedef struct {
int32_t io_trigger_append_distance; //
int32_t pos_devi_tolerance; //
int32_t mres; //
int32_t mark; // 结构体最后一个数值,设置9973,用于保证单片机端和java端均正确更新了枚举
int32_t mark; // 结构体最后一个数值,设置9973,用于保证单片机端和java端均正确更新了枚举
} zm_bcfg_t;
typedef enum {
@ -166,7 +166,7 @@ typedef struct {
int32_t leaving_height; // 离开液面高度,此位置ZEUS开始缓慢进入液面或离开液面,精度0.1mm
int32_t jet_height; // 喷射高度(0.1mm)
int32_t lld_start_search_depth; // lld开始搜索时位置冗余,精度0.1mm,abspos = container_neck_pos + lld_start_search_pos_redundancy
int32_t fix_aspiration_depth; // 固定吸液深度((0.1mm),当lld失能时,移液枪先移动到这个位置,然后开始吸液
int32_t fix_water_level_depth; // 固定吸液深度((0.1mm),当lld失能时,移液枪先移动到这个位置,然后开始吸液
int32_t llf_vconvert_coneff; // 液面跟随转换系数 0.0001 llf_zm_vel = aspiration_pm_vel * llf_vconvert_coneff * 0.0001
int32_t pierce_depth; // 穿刺深度(0.1mm),用于刺破容器防尘膜
int32_t mark; // 结构体最后一个数值,设置9973,用于保证单片机端和java端均正确更新了枚举
@ -182,7 +182,7 @@ typedef enum {
kcontainer_info_leaving_height,
kcontainer_info_jet_height,
kcontainer_info_lld_start_search_depth,
kcontainer_info_fix_aspiration_depth,
kcontainer_info_fix_water_level_depth,
kcontainer_info_llf_vconvert_coneff,
kcontainer_info_pierce_depth,
kcontainer_info_mark,

322
sdk/components/pipette_module/pipette_ctrl_module.cpp

@ -25,16 +25,22 @@ void PipetteModule::initialize(int32_t id, hardward_config_t *hardwaredcfg) { /
m_zm->getGState(); // 读取状态,清空下复位标识
m_piette_gun_io1.initAsInput(hardwaredcfg->IO1, ZGPIO::kMode_pullup, ZGPIO::kIRQ_noIrq, hardwaredcfg->IO1Mirror);
// ZASSERT(hardwaredcfg->uart232);
// EXHAL_UART_BindUart("pipette-uart232", hardwaredcfg->uart232);
// EXHAL_UART_RegListener(hardwaredcfg->uart232, [this](UART_HandleTypeDef *huart, uint8_t *data, size_t len) {
// printf("!rx(%d): ", len);
// if (len > 0) {
// printf("%c", data[0]);
// }
// printf("\n");
// });
// EXHAL_UART_ITStartAutoRead(hardwaredcfg->uart232);
ZASSERT(hardwaredcfg->uart232);
EXHAL_UART_BindUart("pipette-uart232", hardwaredcfg->uart232);
EXHAL_UART_RegListener(hardwaredcfg->uart232, [this](UART_HandleTypeDef *huart, uint8_t *data, size_t len) {
printf("!rx(%d): ", len);
if (len > 0) {
printf("%c", data[0]);
}
printf("\n");
});
EXHAL_UART_ITStartAutoRead(hardwaredcfg->uart232);
while (true) {
EXHAL_UART_TransmitStringBlock(hardwaredcfg->uart232, "/1QR\r");
osDelay(10);
}
m_smtp2.pump_set_pressure_data_stream_port(0); //
// EXHAL_UART_BindUart("pipette-uart", hardwaredcfg->uart);
// EXHAL_UART_RegListener(hardwaredcfg->uart, [this](UART_HandleTypeDef *huart, uint8_t *data, size_t len) {
@ -49,11 +55,26 @@ void PipetteModule::initialize(int32_t id, hardward_config_t *hardwaredcfg) { /
// HAL_Delay(1000);
// EXHAL_UART_TransmitStringBlock(hardwaredcfg->uart232, "/1QR\r");
// m_smtp2.pump_factory_reset();
// osDelay(1000);
test_connectivity();
parameter_init();
zm_sync_base_cfg();
get_platinfo_smart(m_state.platinfo_cpyid, &m_now_platinfo);
int32_t maxul = 0;
// int32_t ecode = 0;
// m_smtp2.pump_set_tip_type(smtp2::TipSize_t::TS1000UL); // 默认1000ul
// m_smtp2.pump_get_max_limit(&maxul);
// ZLOGI(TAG, "1pipette gun max limit:%d", maxul);
m_smtp2.pump_set_tip_type(smtp2::TipSize_t::TS200UL); //
m_smtp2.pump_get_max_limit(&maxul);
ZLOGI(TAG, "2pipette gun max limit:%d", maxul);
ZLOGI(TAG, "pipette gun version:%s", m_smtp2.pump_read_version());
}
void PipetteModule::test_connectivity() {
@ -339,7 +360,7 @@ int32_t PipetteModule::pipette_set_container_info(int32_t cpyid, container_info_
SET_CFG(kcontainer_info_leaving_height, cfg->leaving_height, val);
SET_CFG(kcontainer_info_jet_height, cfg->jet_height, val);
SET_CFG(kcontainer_info_lld_start_search_depth, cfg->lld_start_search_depth, val);
SET_CFG(kcontainer_info_fix_aspiration_depth, cfg->fix_aspiration_depth, val);
SET_CFG(kcontainer_info_fix_water_level_depth, cfg->fix_water_level_depth, val);
SET_CFG(kcontainer_info_llf_vconvert_coneff, cfg->llf_vconvert_coneff, val);
SET_CFG(kcontainer_info_pierce_depth, cfg->pierce_depth, val);
SET_CFG(kcontainer_info_mark, cfg->mark, val);
@ -368,7 +389,7 @@ int32_t PipetteModule::pipette_get_container_info(int32_t cpyid, container_info_
GET_CFG(kcontainer_info_leaving_height, cfg->leaving_height, val);
GET_CFG(kcontainer_info_jet_height, cfg->jet_height, val);
GET_CFG(kcontainer_info_lld_start_search_depth, cfg->lld_start_search_depth, val);
GET_CFG(kcontainer_info_fix_aspiration_depth, cfg->fix_aspiration_depth, val);
GET_CFG(kcontainer_info_fix_water_level_depth, cfg->fix_water_level_depth, val);
GET_CFG(kcontainer_info_llf_vconvert_coneff, cfg->llf_vconvert_coneff, val);
GET_CFG(kcontainer_info_pierce_depth, cfg->pierce_depth, val);
GET_CFG(kcontainer_info_mark, cfg->mark, val);
@ -591,8 +612,9 @@ void PipetteModule::memset_int32_t(int32_t *table, int32_t val, int32_t num) {
int32_t PipetteModule::compute_zm_llf_vel(int32_t pm_vindex, container_info_t *container_info) {
pm_vcfg_t pmv = {0};
get_cfg_smart(pm_vindex, &pmv);
int32_t zmval = pmv.vmax * container_info->llf_vconvert_coneff * 0.0001;
return zmval * 80 / zmbcfg.one_circle_pulse;
int32_t zmval = pmv.vmax * container_info->llf_vconvert_coneff * 0.001;
if (zmval == 0) zmval = 1;
return zmval;
}
/***********************************************************************************************************************
@ -708,9 +730,9 @@ int32_t PipetteModule::pipette_pump_take_tip() {
platinfo_t *platform_info = get_platinfo_smart(m_state.platinfo_cpyid, &m_now_platinfo);
zm_move_to_block(platform_info->tip_picking_pos, kzm_v_default, 0);
zm_move_by(platform_info->tip_picking_search_range, kzm_v_picking_tip, 0);
bool takeTip = false;
bool takeTip = false;
int32_t tipstate = 0;
while (true) {
int32_t tipstate = 0;
DO_IN_THREAD(m_smtp2.pump_get_tip_state(&tipstate));
if (tipstate == 1) {
takeTip = true;
@ -723,6 +745,19 @@ int32_t PipetteModule::pipette_pump_take_tip() {
if (takeTip && platform_info->tip_picking_append_distance > 0) //
zm_move_by_block(platform_info->tip_picking_append_distance, kzm_v_picking_tip, 0);
// 移动到tip搜索位置,检查tip是否存在,如果不存在,则强制退tip一次
if (takeTip) {
zm_move_to_block(platform_info->tip_picking_pos, kzm_v_default, 0);
for (int i = 0; i < 3; i++) {
DO_IN_THREAD(m_smtp2.pump_get_tip_state(&tipstate));
if (tipstate == 0) {
DO_IN_THREAD(m_smtp2.pump_init()); // 强制退tip
takeTip = false;
break;
}
}
}
zm_move_to_zero_quick_block();
ZLOGI(TAG, "pipette_pump_take_tip takeTip %s", takeTip ? "suc" : "fail");
});
@ -866,8 +901,8 @@ int32_t PipetteModule::pipette_pump_aspirate() {
// DO_IN_THREAD(m_smtp2.pump_set_io2_mode(0)); // 通用输入
platinfo_t *platform_info = get_platinfo_smart(m_state.platinfo_cpyid, &m_now_platinfo);
liquid_info_t *liquidinfo = get_liquid_info_smart(acfg->liquid_cfg_index, &aspirate_run_cxt.liquid_info);
container_info_t *container_cfg = get_container_info_smart(acfg->container_info_index, &aspirate_run_cxt.container_info);
liquid_info_t *liquidinfo = get_liquid_info_smart(acfg->liquid_cfg_index, &m_now_aspirate_liquid_info);
container_info_t *container_cfg = get_container_info_smart(acfg->container_info_index, &m_now_container_info);
ZLOGI(TAG, "-------------------------- aspiration param --------------------------");
ZLOGI(TAG, "- x100nl :%d", acfg->volumeX100nl);
@ -920,7 +955,7 @@ int32_t PipetteModule::pipette_pump_aspirate() {
ZLOGI(TAG, "- leaving_height :%d", container_cfg->leaving_height);
ZLOGI(TAG, "- jet_height :%d", container_cfg->jet_height);
ZLOGI(TAG, "- lld_start_search_depth :%d", container_cfg->lld_start_search_depth);
ZLOGI(TAG, "- fix_aspiration_depth :%d", container_cfg->fix_aspiration_depth);
ZLOGI(TAG, "- fix_water_level_depth :%d", container_cfg->fix_water_level_depth);
ZLOGI(TAG, "- llf_vconvert_coneff :%d", container_cfg->llf_vconvert_coneff);
ZLOGI(TAG, "- pierce_depth :%d", container_cfg->pierce_depth);
ZLOGI(TAG, "- mark :%d", container_cfg->mark);
@ -929,29 +964,14 @@ int32_t PipetteModule::pipette_pump_aspirate() {
/***********************************************************************************************************************
* LLD *
***********************************************************************************************************************/
DO_IN_THREAD(m_smtp2.pump_set_tip_size((smtp2::TipSize_t)platform_info->tip_type)); // 250ul,
if (acfg->lld_enable) {
// 液面探测
_do_lld(platform_info, container_cfg, liquidinfo, acfg);
// 这里需要低速离开液面,防止携带液滴
ZLOGI(TAG, "move to swap position in v_swap");
zm_move_to_block(m_state.water_level - container_cfg->leaving_height, kzm_v_swap, 0); //
// 清空tip
ZLOGI(TAG, "clean tip.");
pump_move_to_x100nl_block(0, liquidinfo->empty_tip_pm_vcpyid);
_do_lld(acfg->container_pos, platform_info, container_cfg, liquidinfo); // 液面探测
} else {
// 没有使用lld,使用固定深度
m_state.water_level = acfg->container_pos + container_cfg->fix_aspiration_depth;
ZLOGI(TAG, "lld isn't enable,use fix depth %d", m_state.water_level);
// 由于tip原本在液面之上,这里快速移动到swap位置,
ZLOGI(TAG, "move to swap position in v_default");
zm_move_to_block(m_state.water_level - container_cfg->leaving_height, kzm_v_default, 0); //
ZLOGI(TAG, "clean tip.");
pump_move_to_x100nl_block(0, liquidinfo->empty_tip_pm_vcpyid); //
m_state.water_level = acfg->container_pos + container_cfg->fix_water_level_depth; // 没有使用lld,使用固定深度
}
if (acfg->volumeX100nl != 0) {
DO_IN_THREAD(m_smtp2.pump_set_tip_type((smtp2::TipSize_t)platform_info->tip_type));
_do_sapirate(platform_info, container_cfg, liquidinfo, acfg);
} else {
ZLOGI(TAG, "aspiration volume == 0,skip aspirate", acfg->volumeX100nl);
@ -963,32 +983,34 @@ int32_t PipetteModule::pipette_pump_aspirate() {
return 0;
}
void PipetteModule::_do_lld(platinfo_t *platform_info, container_info_t *container_cfg, liquid_info_t *liquidinfo, aspiration_param_t *acfg) {
void PipetteModule::_do_lld(int32_t container_pos, platinfo_t *platform_info, container_info_t *container_cfg, liquid_info_t *liquidinfo) {
int32_t ecode = 0;
ZLOGI(TAG, "start lld, lld_type %d lld_pm_vindex %d plld_threshold %d", acfg->lld_type, liquidinfo->plld_pm_vcpyid, liquidinfo->plld_threshold);
// 移动到转移位置
ZLOGI(TAG, "-->zm move to transform pos");
zm_move_to_block(0, kzm_v_default, 0);
// 清空tip
ZLOGI(TAG, "-->empty tip before lld");
pump_move_to_x100nl_block(0, liquidinfo->empty_tip_pm_vcpyid);
pump_move_to_x100nl_block(10, kpm_v_default); // 回转一下,消除齿轮间隙
// 移动到瓶口
zm_move_to_block(acfg->container_pos + 50 /*5mm*/, //
kzm_v_default, 0);
pump_move_to_x100nl_block(0, kpm_v_default); // 回转一下,消除齿轮间隙
ZLOGI(TAG, "-->zm move to container neck pos");
zm_move_to_block(container_pos - 50 /*5mm*/, kzm_v_default, 0);
// 启动lld
pump_apply_vcfg(liquidinfo->plld_pm_vcpyid); // 设备lld时,泵的速率
DO_IN_THREAD(m_smtp2.pump_set_tip_size(smtp2::TS200UL)); // 250ul,保护lld不超限
DO_IN_THREAD(m_smtp2.pump_set_io1_mode(1)); // lld输入高
DO_IN_THREAD(m_smtp2.pump_aspirate_plld(liquidinfo->plld_threshold));
ZLOGI(TAG, "-->start lld, lld_pm_vindex %d plld_threshold %d", liquidinfo->plld_pm_vcpyid, liquidinfo->plld_threshold);
DO_IN_THREAD(m_smtp2.pump_set_io1_mode(1)); // lld输入高
DO_IN_THREAD(m_smtp2.pump_set_tip_type((smtp2::TipSize_t)platform_info->tip_type)); // 设置tip大小
pump_do_lld(liquidinfo->plld_threshold, 200, liquidinfo->plld_pm_vcpyid); // lld延时200ms,速度为plld_zm_vel
// 快速移动到瓶口
zm_move_to_block(acfg->container_pos + container_cfg->lld_start_search_depth, //
ZLOGI(TAG, "-->zm move quick to lld search start pos");
zm_move_to_block(container_pos + container_cfg->lld_start_search_depth, //
kzm_v_default, 0);
// lld,zm移动到瓶底
zm_move_to(acfg->container_pos + container_cfg->container_depth, kzm_v_lld, liquidinfo->plld_zm_vel);
ZLOGI(TAG, "-->zm move slow to container bottom pos");
zm_move_to(container_pos + container_cfg->container_depth, kzm_v_lld, liquidinfo->plld_zm_vel);
/**
* @brief
@ -998,7 +1020,7 @@ void PipetteModule::_do_lld(platinfo_t *platform_info, container_info_t *contain
while (true) {
if (m_zm->isStoped()) {
detect_liquid = false;
ZLOGI(TAG, "zm is stoped");
ZLOGI(TAG, "-->zm is stoped");
break;
}
@ -1006,14 +1028,19 @@ void PipetteModule::_do_lld(platinfo_t *platform_info, container_info_t *contain
if (m_piette_gun_io1.getState()) {
int32_t water_level = zm_get_now_pos();
detect_liquid = true;
ZLOGI(TAG, "detect liquid, water_level %d", water_level);
m_zm->stop();
ZLOGI(TAG, "-->detect liquid, water_level %d", water_level);
break;
}
ZLOGI(TAG, "...wait for lld trigger, now zm pos %d", zm_get_now_pos());
thread_delay(1);
}
ecode = m_smtp2.pump_get_state(nullptr); // 获取泵状态,在此之前不能执行任何泵机指令,否则会丢失错误状态
int32_t now_pm_pos = pump_read_pos_nl();
ZLOGI(TAG, "pump now pos %d nl", now_pm_pos);
// 检查是否是LLD错误
ecode = m_smtp2.pump_get_state(nullptr);
if (ecode != 0) {
if (ecode == err::kpipette_error_LLDError) {
// LLD错误。在cLLD、pLLD、hLLD模式下均未检测到液体。在超过指定的压力阈值之前,泵已达到行程终点。
@ -1039,6 +1066,21 @@ void PipetteModule::_do_lld(platinfo_t *platform_info, container_info_t *contain
}
void PipetteModule::_do_sapirate(platinfo_t *platform_info, container_info_t *container_cfg, liquid_info_t *liquidinfo, aspiration_param_t *acfg) {
// 移动到液面之上
ZLOGI(TAG, "--> move to swap pos");
int32_t nowzpos = zm_get_now_pos();
if (nowzpos < m_state.water_level) {
ZLOGI(TAG, "move to swap position in v_swap");
zm_move_to_block(m_state.water_level - container_cfg->leaving_height, kzm_v_swap, 0); //
} else {
ZLOGI(TAG, "move to swap position in v_default");
zm_move_to_block(m_state.water_level - container_cfg->leaving_height, kzm_v_default, 0); //
}
// 清空tip
ZLOGI(TAG, "clean tip.");
pump_move_to_x100nl_block(0, liquidinfo->empty_tip_pm_vcpyid);
// 吸入过量的空气
if (liquidinfo->blowout_air_volume > 0) {
ZLOGI(TAG, "--> aspirate blowout_air_volume volume=%d, pm_vcpyid=%d", liquidinfo->blowout_air_volume);
@ -1118,7 +1160,60 @@ void PipetteModule::_do_sapirate(platinfo_t *platform_info, container_info_t *co
}
}
int32_t PipetteModule::pipette_pump_distribu() { return 0; }
int32_t PipetteModule::pipette_pump_distribu_all() {
thread_start_work(__FUNCTION__, [this]() {
ZLOGI(TAG, "pipette_pump_aspirate");
if (pump_read_tip_state() == 0) {
throw zapp_exception(err::kpipette_error_TipDrop);
}
});
return 0;
}
int32_t PipetteModule::pipette_test_pump_move_to_x100nl(int32_t x100nl, int32_t vcfgcpyid) {
thread_start_work(__FUNCTION__, [this, x100nl, vcfgcpyid]() {
ZLOGI(TAG, "pipette_pump_aspirate");
if (pump_read_tip_state() == 0) {
throw zapp_exception(err::kpipette_error_TipDrop);
}
// 移液枪部分参数初始化
DO_IN_THREAD(m_smtp2.pump_enable_temp_compensation(0)); // 关闭温度补偿
DO_IN_THREAD(m_smtp2.pump_set_back_clearance(0)); // 设置背隙为0
DO_IN_THREAD(m_smtp2.pump_set_io1_mode(0)); // lld输入高
int32_t diff = 0;
pump_move_to_x100nl_block(x100nl, vcfgcpyid, &diff); //
m_state.asynchronous_result0 = diff;
});
return 0;
}
int32_t PipetteModule::pipette_test_lld(int32_t container_pos, int32_t container_cpyid, int32_t liquid_cpyid) {
thread_start_work(__FUNCTION__, [this, container_pos, container_cpyid, liquid_cpyid]() {
ZLOGI(TAG, "pipette_pump_aspirate");
if (pump_read_tip_state() == 0) {
throw zapp_exception(err::kpipette_error_TipDrop);
}
// 移液枪部分参数初始化
DO_IN_THREAD(m_smtp2.pump_enable_temp_compensation(0)); // 关闭温度补偿
DO_IN_THREAD(m_smtp2.pump_set_back_clearance(0)); // 设置背隙为0
DO_IN_THREAD(m_smtp2.pump_set_io1_mode(0)); // lld输入高
platinfo_t *platform_info = get_platinfo_smart(m_state.platinfo_cpyid, &m_now_platinfo);
liquid_info_t *liquidinfo = get_liquid_info_smart(container_cpyid, &m_now_aspirate_liquid_info);
container_info_t *container_cfg = get_container_info_smart(liquid_cpyid, &m_now_container_info);
_do_lld(container_pos, platform_info, container_cfg, liquidinfo);
});
return 0;
}
/***********************************************************************************************************************
* EXT_API_UTILS *
@ -1262,32 +1357,22 @@ void PipetteModule::zm_apply_vcfg(int32_t vbasecfgindex, int32_t vel) {
*/
zm_vcfg_t cfg = {0};
get_cfg_smart(vbasecfgindex, &cfg);
if (vel > 0) {
cfg.vmax = vel;
}
TMC51X0::VCfg_t tcmvcfg;
tcmvcfg.vstart = cfg.vstart;
tcmvcfg.a1 = cfg.a1;
tcmvcfg.amax = cfg.amax;
tcmvcfg.v1 = cfg.v1;
tcmvcfg.dmax = cfg.dmax;
tcmvcfg.d1 = cfg.d1;
tcmvcfg.vstop = cfg.vstop;
tcmvcfg.vmax = cfg.vmax;
m_zm->set_vcfg(&tcmvcfg);
if (cfg.vstop > cfg.vmax) {
cfg.vstop = cfg.vmax;
}
if (cfg.vstart > cfg.vmax) {
cfg.vstart = cfg.vmax;
}
if (cfg.v1 > cfg.vmax) {
cfg.v1 = cfg.vmax;
}
m_zm->set_vstart(cfg.vstart);
m_zm->set_a1(cfg.a1);
m_zm->set_amax(cfg.amax);
m_zm->set_v1(cfg.v1);
m_zm->set_dmax(cfg.dmax);
m_zm->set_d1(cfg.d1);
m_zm->set_vstop(cfg.vstop);
m_zm->set_vmax(cfg.vmax);
ZLOGI(TAG, "zm set vstart %d,a1 %d,amax %d,v1 %d,dmax %d,d1 %d,vstop %d,vmax %d", cfg.vstart, cfg.a1, cfg.amax, cfg.v1, cfg.dmax, cfg.d1, cfg.vstop, cfg.vmax);
ZLOGI(TAG, "zm set vstart %d,a1 %d,amax %d,v1 %d,dmax %d,d1 %d,vstop %d,vmax %d", tcmvcfg.vstart, tcmvcfg.a1, tcmvcfg.amax, tcmvcfg.v1, tcmvcfg.dmax, tcmvcfg.d1, tcmvcfg.vstop, tcmvcfg.vmax);
}
void PipetteModule::zm_sync_base_cfg() {
@ -1301,6 +1386,7 @@ void PipetteModule::zm_sync_base_cfg() {
m_zm->set_tzerowait(zmbcfg.tzerowait);
m_zm->set_enc_resolution(zmbcfg.enc_resolution);
zm_apply_vcfg(kzm_v_default, 0);
m_zm->stop();
if (m_state.enable) {
m_zm->enable(true);
}
@ -1366,9 +1452,9 @@ void PipetteModule::pump_waitfor_lld_is_ready(int32_t *zpos) {
}
}
void PipetteModule::pump_get_vcfg(int32_t vcfgindex, smtp2::VelCfg *cfg) {
void PipetteModule::pump_get_vcfg(int32_t vcfgcpyid, smtp2::VelCfg *cfg) {
pm_vcfg_t cfg2 = {0};
get_cfg_smart(vcfgindex, &cfg2);
get_cfg_smart(vcfgcpyid, &cfg2);
cfg->acc = cfg2.acc;
cfg->dec = cfg2.dec;
cfg->vstart = cfg2.vstart;
@ -1376,41 +1462,69 @@ void PipetteModule::pump_get_vcfg(int32_t vcfgindex, smtp2::VelCfg *cfg) {
cfg->vmax = cfg2.vmax;
}
void PipetteModule::pump_apply_vcfg(int32_t vcfgindex, bool force) {
ZLOGI(TAG, "pump_apply_vcfg %s", get_pm_vcpyid_name((pm_vcpyid_t)vcfgindex));
if (!force && m_state.pm_now_vcfg_index == vcfgindex) {
void PipetteModule::pump_apply_vcfg(int32_t vcfgcpyid, bool force) {
ZLOGI(TAG, "pump_apply_vcfg %s", get_pm_vcpyid_name((pm_vcpyid_t)vcfgcpyid));
if (!force && m_state.pm_now_vcfg_index == vcfgcpyid) {
// 如果当前配置和目标配置相同,则不需要重新设置
return;
}
smtp2::VelCfg vcfg;
pump_get_vcfg(vcfgindex, &vcfg);
pump_get_vcfg(vcfgcpyid, &vcfg);
DO_IN_THREAD(m_smtp2.pump_set_vcfg(&vcfg));
m_state.pm_now_vcfg_index = vcfgindex;
m_state.pm_now_vcfg_index = vcfgcpyid;
}
void PipetteModule::pump_move_to_x100nl(int32_t x100nl, int32_t vcfgindex) {
void PipetteModule::_pump_move_to_x100nl(int32_t x100nl, int32_t vcfgcpyid) {
ZLOGI(TAG, "pump_move_to_x100nl %d, in %s", x100nl, get_pm_vcpyid_name((pm_vcpyid_t)vcfgcpyid));
smtp2::VelCfg vcfg;
pump_get_vcfg(vcfgindex, &vcfg);
pump_get_vcfg(vcfgcpyid, &vcfg);
m_state.pm_now_vcfg_index = vcfgcpyid; // 更新当前配置索引
DO_IN_THREAD(m_smtp2.pump_move_to_nl(&vcfg, x100nl * 100));
}
void PipetteModule::pump_move_by_x100nl(int32_t x100nl, int32_t vcfgindex) {
ZLOGI(TAG, "pump_move_by_x100nl %d, in %s", x100nl, get_pm_vcpyid_name((pm_vcpyid_t)vcfgindex));
void PipetteModule::pump_do_lld(int32_t pressure_threshold, int32_t ___, int32_t vcfgidx) {
ZLOGI(TAG, "pump_do_lld pressure_threshold %d, vcfgidx %d", pressure_threshold, vcfgidx);
smtp2::VelCfg vcfg;
pump_get_vcfg(vcfgindex, &vcfg);
DO_IN_THREAD(m_smtp2.pump_move_by_nl(&vcfg, x100nl * 100));
pump_get_vcfg(vcfgidx, &vcfg);
m_state.pm_now_vcfg_index = vcfgidx; // 更新当前配置索引
DO_IN_THREAD(m_smtp2.pump_aspirate_plld(pressure_threshold, &vcfg));
}
void PipetteModule::pump_move_to_x100nl_block(int32_t x100nl, int32_t vcfgindex) {
pump_move_to_x100nl(x100nl, vcfgindex);
pump_waitfor_stop();
ZLOGI(TAG, "pump now pos %d nl", pump_read_pos_nl());
void PipetteModule::pump_move_to_x100nl_block(double x100nl, int32_t vcfgcpyid, int32_t *diff) {
int32_t diff_pos = 0;
for (size_t i = 0; i < 3; i++) {
int32_t vcpyid = vcfgcpyid;
if (i != 0) {
vcpyid = kpm_v_slow_lv1;
}
_pump_move_to_x100nl(x100nl, vcpyid);
pump_waitfor_stop();
int32_t targetpos = x100nl * 100;
int32_t after_pos = pump_read_pos_nl();
diff_pos = targetpos - after_pos;
if (diff) *diff = diff_pos;
ZLOGI(TAG, "pump target %d nl, now pos %d nl diff %d", targetpos, after_pos, diff_pos);
if (abs(diff_pos) > 20) {
ZLOGW(TAG, "pump move to x100nl %d failed, diff is too large retrying...", x100nl);
continue;
}
break;
}
if (abs(diff_pos) > 30) {
module_detail_errorcode = diff_pos;
throw zapp_exception(err::kpipette_pm_positioning_abnormality);
}
}
void PipetteModule::pump_move_by_x100nl_block(int32_t x100nl, int32_t vcfgindex) {
pump_move_by_x100nl(x100nl, vcfgindex);
pump_waitfor_stop();
ZLOGI(TAG, "pump now pos %d nl", pump_read_pos_nl());
void PipetteModule::pump_move_by_x100nl_block(double x100nl, int32_t vcfgcpyid) {
int32_t startpos = pump_read_pos_nl();
if (startpos > 1500000) {
// 参考 https://iflytop1.feishu.cn/wiki/IWn1waKCXiUvzfkOru5c0F3HnJf
ZLOGW(TAG, "pump position is too large maybe overflow, startpos=%d", startpos);
startpos = 0;
}
double targetpos = startpos + x100nl * 100;
pump_move_to_x100nl_block(targetpos / 100, vcfgcpyid);
}
void PipetteModule::pump_read_pos_nl(int32_t *val) {
@ -1579,13 +1693,21 @@ void PipetteModule::thread_delay(int32_t delayms) { //
}
void PipetteModule::thread_start_work(const char *fnname, function<void()> fn) {
m_thread.stop();
module_status = 1;
module_errorcode = 0;
module_status = 1;
module_errorcode = 0;
module_detail_errorcode = 0;
m_state.detected_liquid = 0;
m_state.asynchronous_result0 = 0;
m_state.asynchronous_result1 = 0;
m_state.aspiration_ok = 0;
m_state.pump_lld_reach_limit = 0;
m_state.detected_liquid = 0;
m_state.water_level = 0;
m_state.tipblock = 0;
m_state.airsuction = 0;
m_state.bubble = 0;
m_thread.start([this, fnname, fn]() {
osDelay(1);
ZLOGI(TAG, "start work -> %s", fnname);

28
sdk/components/pipette_module/pipette_ctrl_module.hpp

@ -56,17 +56,8 @@ class PipetteModule : public ZIModule {
} hardward_config_t;
typedef struct {
container_info_t container_info;
liquid_info_t liquid_info;
} aspirate_run_cxt_t;
typedef struct {
platinfo_t platinfo;
container_info_t container_info;
liquid_info_t transform_liquid_info;
liquid_info_t destination_liquid_info;
} distribu_run_cxt_t;
private:
/***********************************************************************************************************************
* Hardware *
@ -84,9 +75,8 @@ class PipetteModule : public ZIModule {
pipette_state_t m_state = {0};
platinfo_t m_now_platinfo;
container_info_t m_now_container_info;
liquid_info_t m_now_aspirate_liquid_info;
aspirate_run_cxt_t aspirate_run_cxt;
distribu_run_cxt_t distribu_run_cxt;
/***********************************************************************************************************************
* Config *
***********************************************************************************************************************/
@ -182,10 +172,10 @@ class PipetteModule : public ZIModule {
virtual int32_t pipette_pump_aspirate_set_param(aspiration_paramid_t param, int32_t val);
virtual int32_t pipette_pump_aspirate();
void _do_lld(platinfo_t *platform_info, container_info_t *container_cfg, liquid_info_t *liquidinfo, aspiration_param_t *acfg);
void _do_lld(int32_t container_pos, platinfo_t *platform_info, container_info_t *container_cfg, liquid_info_t *liquidinfo);
void _do_sapirate(platinfo_t *platform_info, container_info_t *container_cfg, liquid_info_t *liquidinfo, aspiration_param_t *acfg);
virtual int32_t pipette_pump_distribu();
virtual int32_t pipette_pump_distribu_all();
virtual int32_t pipette_get_sensor_sample_data(int32_t index, int32_t *motor_pos, int32_t *pval); //
virtual int32_t pipette_get_sensor_sample_data_num(int32_t *num);
@ -194,6 +184,10 @@ class PipetteModule : public ZIModule {
virtual int32_t pipette_read_pressure(int32_t *pressure);
virtual int32_t pipette_read_capacitance(int32_t *capacitance);
// TEST CMD
virtual int32_t pipette_test_pump_move_to_x100nl(int32_t x100nl, int32_t vcfgindex);
virtual int32_t pipette_test_lld(int32_t container_pos, int32_t container_cpyid, int32_t liquid_cpyid);
private:
/***********************************************************************************************************************
* MOTOR *
@ -242,10 +236,10 @@ class PipetteModule : public ZIModule {
int32_t pump_read_tip_state();
void pump_waitfor_stop();
void pump_waitfor_lld_is_ready(int32_t *zpos);
void pump_move_to_x100nl(int32_t x100nl, int32_t vcfgindex);
void pump_move_by_x100nl(int32_t x100nl, int32_t vcfgindex);
void pump_move_to_x100nl_block(int32_t x100nl, int32_t vcfgindex);
void pump_move_by_x100nl_block(int32_t x100nl, int32_t vcfgindex);
void _pump_move_to_x100nl(int32_t x100nl, int32_t vcfgindex);
void pump_do_lld(int32_t pressure_threshold, int32_t ___, int32_t vcfgidx);
void pump_move_to_x100nl_block(double x100nl, int32_t vcfgindex, int32_t *diff = nullptr);
void pump_move_by_x100nl_block(double x100nl, int32_t vcfgindex);
private:
void push_pressure_sample_data(int32_t motor_pos, int32_t pressure_val);

98
sdk/components/sensors/smtp2_v2/smtp2_v2.cpp

@ -11,7 +11,7 @@ using namespace smtp2;
#define TAG "SMTP2"
#define OVERTIME 100
#define DUMP_HEX 1
#define DUMP_HEX 0
#define RE_SEND_TIMES 5
#define RE_SEND_DELAY 400
@ -74,10 +74,22 @@ int32_t SMTP2V2::pump_set_pressure_data_stream_port(int32_t val /*0:无 1:232 3:
return setstate(true, "/1u%d,%dR\r", kcfg_pressure_data_port_channel, val);
}
int32_t SMTP2V2::pump_set_tip_size(TipSize_t size) {
ZLOGI(TAG, "pump_set_tip_size %d", size);
int32_t SMTP2V2::pump_set_tip_type(TipSize_t size) {
ZLOGI(TAG, "pump_set_tip_type %d", size);
return setstate(true, "/1u%d,%dR\r", kcfg_tip_size, size);
}
// 该方法调用会报参数错误,原因未知
// int32_t SMTP2V2::pump_set_max_limit(int32_t nl) {
// ZLOGI(TAG, "pump_set_max_limit %d", nl);
// if (nl < 0) {
// ZLOGE(TAG, "pump_set_max_limit nl < 0");
// return -1;
// }
// return setstate(true, "/1u%d,%dR\r", kcfg_total_range, nl);
// }
int32_t SMTP2V2::pump_get_max_limit(int32_t* nl) { return pump_get_state_as_int(kstate_total_range, nl); }
int32_t SMTP2V2::pump_enable_temp_compensation(int32_t enable) {
ZLOGI(TAG, "pump_enable_temp_compensation %d", enable);
return setstate(true, "/1u%d,%dR\r", kcfg_auto_temp_compensation, enable);
@ -93,6 +105,7 @@ int32_t SMTP2V2::pump_set_plld_start_delay(int32_t delay_ms) {
int32_t SMTP2V2::pump_set_vcfg(VelCfg* vcfg) {
ZLOGI(TAG, "pump_set_vcfg %d,%d,%d,%d,%d", vcfg->acc, vcfg->dec, vcfg->vstart, vcfg->vstop, vcfg->vmax);
// L<n1>,<n2>设置加速度,和减速度 (1..20) V%d 设置最大速度 v%d 设置起始速度 c%d 设置停止速度
fix_vcfg(vcfg);
return setstate(true, "/1N2L%d,%dv%dc%dV%dR\r", //
vcfg->acc, vcfg->dec, vcfg->vstart * 1000, vcfg->vstop * 1000, vcfg->vmax * 1000);
}
@ -105,10 +118,11 @@ int32_t SMTP2V2::pump_put_tip() {
ZLOGI(TAG, "pump_put_tip");
return runaction(true, "/1E0R\r");
}
int32_t SMTP2V2::pump_reset() {
ZLOGI(TAG, "pump_reset");
_sendcmd(true, "/1!0R\r"); // 复位指令没有回执,所以这里只能使用方法_sendcmd
_sendcmd(true, "/1!0R\r"); // 复位指令没有回执,所以这里只能使用方法_sendcmd
int32_t SMTP2V2::pump_factory_reset() {
ZLOGI(TAG, "pump_factory_reset");
_sendcmd(true, "/1!22R\r"); //
_sendcmd(true, "/1!0R\r"); // 复位指令没有回执,所以这里只能使用方法_sendcmd
_sendcmd(true, "/1!0R\r"); // 复位指令没有回执,所以这里只能使用方法_sendcmd
return 0;
}
@ -116,12 +130,18 @@ int32_t SMTP2V2::pump_reset() {
* ACTION *
***********************************************************************************************************************/
int32_t SMTP2V2::pump_move_to_nl(VelCfg* vcfg, int32_t nl) {
ZLOGI(TAG, "pump_move_to_nl %d", nl);
ZLOGI(TAG, "vcfg acc %d dec %d vstart %d vstop %d vmax %d", vcfg->acc, vcfg->dec, vcfg->vstart, vcfg->vstop, vcfg->vmax);
int32_t SMTP2V2::_pump_move_to_nl(VelCfg* vcfg, int32_t nl) {
ZLOGI(TAG, " _pump_move_to_nl %d", nl);
ZLOGI(TAG, " vcfg acc %d dec %d vstart %d vstop %d vmax %d", vcfg->acc, vcfg->dec, vcfg->vstart, vcfg->vstop, vcfg->vmax);
fix_vcfg(vcfg);
return runaction(true, "/1N2L%d,%dv%dc%dV%dA%dR\r", //
vcfg->acc, vcfg->dec, vcfg->vstart * 1000, vcfg->vstop * 1000, vcfg->vmax * 1000, nl);
}
int32_t SMTP2V2::pump_move_to_nl(VelCfg* vcfg, int32_t nl) {
ZLOGI(TAG, " pump_move_to_nl %d", nl);
return _pump_move_to_nl(vcfg, nl);
}
int32_t SMTP2V2::pump_move_by_nl(VelCfg* vcfg, int32_t nl) {
ZLOGI(TAG, "pump_move_by_nl %d", nl);
int32_t nownl;
@ -226,9 +246,13 @@ int32_t SMTP2V2::pump_aspirate_infer_eigen_time(int32_t v, int32_t ul) {
int32_t SMTP2V2::pump_get_infer_eigen_time(int32_t* eigen_time) { return pump_get_state_as_int(kstate_q_time, eigen_time); }
int32_t SMTP2V2::pump_aspirate_plld(int32_t pressure_threshold) {
int32_t SMTP2V2::pump_aspirate_plld(int32_t pressure_threshold, VelCfg* vcfg) {
ZLOGI(TAG, "pump_aspirate_plld %d", pressure_threshold);
return runaction(true, "/1t%d,1R\r", pressure_threshold);
fix_vcfg(vcfg);
return runaction(true, "/1N2L%d,%dv%dc%dV%dt%d,1R\r", //
vcfg->acc, vcfg->dec, vcfg->vstart * 1000, vcfg->vstop * 1000, vcfg->vmax * 1000, //
pressure_threshold);
}
int32_t SMTP2V2::pump_aspirate_plld_get_state(int32_t* detected) {
int32_t isbusy = 0;
@ -297,6 +321,11 @@ int32_t SMTP2V2::pump_get_state_as_int(int32_t state_index, int32_t* val) {
*val = getAck0AsInt();
return err::ksucc;
}
const char* SMTP2V2::pump_read_version() {
int ret = readstate(true, "/1?%d\r", kstate_firmware);
if (ret != 0) return "fail";
return getAckStr();
}
int32_t SMTP2V2::getAckEcode() {
if (m_rxNum < 3) {
@ -331,6 +360,21 @@ int32_t SMTP2V2::getAck0AsInt() {
int intval = atoi(&m_rxprocessbuf[3]);
return intval;
}
const char* SMTP2V2::getAckStr() {
if (m_rxNum < 3) {
return nullptr;
}
memset(m_rxprocessbuf, 0, sizeof(m_rxprocessbuf));
memcpy(m_rxprocessbuf, m_rxbuf, m_rxNum);
for (size_t i = 0; i < m_rxNum; i++) {
if (m_rxprocessbuf[i] == '\r' || m_rxprocessbuf[i] == '\n' || m_rxprocessbuf[i] == 0x03) {
m_rxprocessbuf[i] = 0;
break;
}
}
return &m_rxprocessbuf[3];
}
int32_t SMTP2V2::runaction(bool dump, const char* format, ...) {
static char cmdbuf[256];
va_list args;
@ -453,3 +497,33 @@ bool SMTP2V2::_sendcmd_dma(const char* cmd) {
osDelay(10);
return true;
}
void SMTP2V2::fix_vcfg(VelCfg* vcfg) {
#if 1
// 启动速度[v] ≤ 停止速度[c] ≤ 最高速度[V]
bool fixed = false;
if (vcfg->vstop > vcfg->vmax) {
vcfg->vstop = vcfg->vmax;
fixed = true;
}
if (vcfg->vstart > vcfg->vstop) {
vcfg->vstart = vcfg->vstop;
fixed = true;
}
if (vcfg->acc < 1) {
vcfg->acc = 1;
fixed = true;
}
if (vcfg->dec < 1) {
vcfg->dec = 1;
fixed = true;
}
if (fixed) {
ZLOGI(TAG, " fixed vcfg %d,%d,%d,%d,%d", vcfg->acc, vcfg->dec, vcfg->vstart, vcfg->vstop, vcfg->vmax);
}
#endif
return;
}

44
sdk/components/sensors/smtp2_v2/smtp2_v2.hpp

@ -61,9 +61,9 @@ typedef enum {
kcfg_motor_hold_current = 13, // 电机保持电流(单位:0.01A)0...200 default:10
kcfg_motor_run_current = 14, // 电机运行电流(单位:0.01A)0...200 default:25
kcfg_pLLD_start_delay = 15, // pLLD启动延迟(毫秒)0...2000 default:100
kcfg_nL_increment = 16, // 纳升/增量。此值用于将[N2]模式的nL 输入和输出转换为增量。 (当前系统中不使用)
kcfg_nL_increment = 16, // 纳升/增量。此值用于将[N2]模式的nL 输入和输出转换为增量。
kcfg_total_range = 17, // 用nL表示的总量程。当这个值被改变时,u1所设定的值也会按照这个公式自动变更:u1=u17/u16 同时,u1改变时,此值也会自动变更:u17=u1*u16 (当前系统中不使用)
kcfg_tip_size = 18, // Tip大小。对此值进行设置之后,u1和u17的值将会自动进行变更。 (当前系统中不使用)
kcfg_tip_size = 18, // Tip大小。对此值进行设置之后,u1和u17的值将会自动进行变更。
kcfg_default_tolerance = 21, // [q] 命令默认容差
kcfg_pressure_data_stream_time = 22, // 泵运动完成后保持压力数据流输出的时间(毫秒)。请参见[+]命令。
kcfg_auto_temp_compensation = 24, // 自动使用温度补偿。
@ -195,7 +195,9 @@ class SMTP2V2 {
int32_t pump_set_io1_mode(int32_t mode); // 0LLD输出高 1LLD输出低 2通用输出
int32_t pump_set_io1_state(int32_t state); //
int32_t pump_set_io2_mode(int32_t mode); // 0通用输入 1紧急制动 2Tip脱落输出高 3Tip脱落输出低
int32_t pump_set_tip_size(TipSize_t size); // Tip大小 0:1ml 1:200ul(max:250ul) 2:50ul(max:62ul) 3=20ul(max:40ul)
int32_t pump_set_tip_type(TipSize_t size); // Tip大小 0:1ml 1:200ul(max:250ul) 2:50ul(max:62ul) 3=20ul(max:40ul)
// int32_t pump_set_max_limit(int32_t nl); //
int32_t pump_get_max_limit(int32_t* nl); // 获取最大行程
int32_t pump_enable_temp_compensation(int32_t enable); // 0:关闭 1:开启
int32_t pump_set_back_clearance(int32_t val);
int32_t pump_set_pressure_data_stream_port(int32_t val /*0:无 1:232 3:CAN*/);
@ -203,23 +205,25 @@ class SMTP2V2 {
/***********************************************************************************************************************
* STATE *
***********************************************************************************************************************/
int32_t pump_get_state(int32_t* isbusy);
int32_t pump_get_capacitance(int32_t* capacitance);
int32_t pump_get_pressure(int32_t* pressure);
int32_t pump_get_tip_state(int32_t* tipison);
int32_t pump_get_nl(int32_t* nl);
int32_t pump_get_state_as_int(int32_t state_index, int32_t* val);
int32_t pump_get_state(int32_t* isbusy);
int32_t pump_get_capacitance(int32_t* capacitance);
int32_t pump_get_pressure(int32_t* pressure);
int32_t pump_get_tip_state(int32_t* tipison);
int32_t pump_get_nl(int32_t* nl);
int32_t pump_get_state_as_int(int32_t state_index, int32_t* val);
const char* pump_read_version();
/***********************************************************************************************************************
* ACTION *
***********************************************************************************************************************/
int32_t pump_init(); // 泵机初始化(归零)
int32_t pump_put_tip(); // 丢弃TIP
int32_t pump_reset(); // 泵机复位
int32_t pump_stop(); // 停止
int32_t pump_move_to_nl(VelCfg* vcfg, int32_t nl); //
int32_t pump_move_by_nl(VelCfg* vcfg, int32_t nl); //
int32_t pump_aspirate_plld(int32_t pressure_threshold); // plld,分配探测
int32_t pump_init(); // 泵机初始化(归零)
int32_t pump_put_tip(); // 丢弃TIP
int32_t pump_factory_reset(); // 泵机复位
int32_t pump_stop(); // 停止
int32_t _pump_move_to_nl(VelCfg* vcfg, int32_t nl);
int32_t pump_move_to_nl(VelCfg* vcfg, int32_t nl); //
int32_t pump_move_by_nl(VelCfg* vcfg, int32_t nl); //
int32_t pump_aspirate_plld(int32_t pressure_threshold, VelCfg* vcfg); // plld,分配探测
int32_t pump_aspirate_plld_get_state(int32_t* detected);
int32_t pump_clld(int32_t c_threshold); // clld 0...130
@ -244,6 +248,7 @@ class SMTP2V2 {
void dumpparam();
private:
int32_t runaction(bool dump, const char* format, ...);
int32_t _runaction(bool dump, const char* cmd);
@ -253,8 +258,11 @@ class SMTP2V2 {
bool _sendcmd(bool dump, const char* cmd);
bool _sendcmd_dma(const char* cmd);
int32_t getAckEcode();
int32_t getAck0AsInt();
int32_t getAckEcode();
int32_t getAck0AsInt();
const char* getAckStr();
void fix_vcfg(VelCfg* vcfg);
};
} // namespace smtp2

20
sdk/components/tmc/ic/ztmc5130.cpp

@ -105,6 +105,26 @@ void TMC51X0::set_vstop(int32_t vel) {
}
void TMC51X0::set_tzerowait(int32_t val) { writeInt(TMC5130_TZEROWAIT, val); }
void TMC51X0::set_vmax(int32_t vmax) { writeInt(TMC5130_VMAX, to_motor_vel(vmax)); }
void TMC51X0::set_vcfg(VCfg_t *vcfg) {
// VMAX>V1>VSTOP>VSTART
if (vcfg->v1 > vcfg->vmax) {
vcfg->v1 = vcfg->vmax;
}
if (vcfg->vstop > vcfg->v1) {
vcfg->vstop = vcfg->v1;
}
if (vcfg->vstart > vcfg->vstop) {
vcfg->vstart = vcfg->vstop;
}
set_a1(vcfg->a1);
set_amax(vcfg->amax);
set_v1(vcfg->v1);
set_dmax(vcfg->dmax);
set_d1(vcfg->d1);
set_vstart(vcfg->vstart);
set_vstop(vcfg->vstop);
set_vmax(vcfg->vmax);
}
void TMC51X0::enable(bool enable) {
// m_port->TMC5130Port_setENNPinState(m_channel, !enable);

13
sdk/components/tmc/ic/ztmc5130.hpp

@ -87,6 +87,17 @@ class TMC51X0 : public IStepperMotor {
} GState_t;
typedef struct {
int32_t vstart;
int32_t a1;
int32_t amax;
int32_t v1;
int32_t dmax;
int32_t d1;
int32_t vstop;
int32_t vmax;
} VCfg_t;
typedef struct {
SPI_HandleTypeDef *spi;
Pin_t csgpio = PinNull; //
Pin_t ennPin = PinNull; //
@ -172,6 +183,8 @@ class TMC51X0 : public IStepperMotor {
virtual void set_tzerowait(int32_t val);
virtual void set_vmax(int32_t vmax);
virtual void set_vcfg(VCfg_t *vcfg);
public:
DevStatusReg_t getDevStatus() { // R 读后不清
static_assert(sizeof(DevStatusReg_t) == 4);

18
sdk/components/zcan_protocol_parser/zcan_protocol_parser.cpp

@ -196,6 +196,9 @@ void ZCanProtocolParser::initialize(ZCanReceiver* cancmder) {
REGFN(pipette_read_tip_state);
REGFN(pipette_read_pressure);
REGFN(pipette_read_capacitance);
REGFN(pipette_test_pump_move_to_x100nl);
REGFN(pipette_test_lld);
}
void ZCanProtocolParser::_registerModule(uint16_t id, ZIModule* module) { m_modulers[id] = module; }
void ZCanProtocolParser::registerModule(ZIModule* module) { _registerModule(module->getid(), module); }
@ -1103,7 +1106,7 @@ int32_t ZCanProtocolParser::pipette_pump_aspirate(cmdcontxt_t* cxt) {
int32_t ZCanProtocolParser::pipette_pump_distribu(cmdcontxt_t* cxt) {
CHECK_AND_GET_MODULE(0);
return module->pipette_pump_distribu();
return module->pipette_pump_distribu_all();
}
int32_t ZCanProtocolParser::pipette_get_sensor_sample_data(cmdcontxt_t* cxt) {
@ -1166,4 +1169,17 @@ int32_t ZCanProtocolParser::pipette_read_capacitance(cmdcontxt_t* cxt) {
return module->pipette_read_capacitance(&ack[0]);
}
// kpipette_test_pump_move_to_x100nl = 0x7600, // int32_t x100nl, int32_t vcfgindex
// kpipette_test_lld = 0x7601, // int32_t container_pos, int32_t container_cpyid, int32_t liquid_cpyid
int32_t ZCanProtocolParser::pipette_test_pump_move_to_x100nl(cmdcontxt_t* cxt) {
CHECK_AND_GET_MODULE(2);
return module->pipette_test_pump_move_to_x100nl(cxt->params[0], cxt->params[1]);
}
int32_t ZCanProtocolParser::pipette_test_lld(cmdcontxt_t* cxt) {
CHECK_AND_GET_MODULE(3);
return module->pipette_test_lld(cxt->params[0], cxt->params[1], cxt->params[2]);
}
#undef MODULE_CLASS

3
sdk/components/zcan_protocol_parser/zcan_protocol_parser.hpp

@ -217,6 +217,9 @@ class ZCanProtocolParser : public IZCanRxProcesser {
CMDFN(pipette_read_tip_state);
CMDFN(pipette_read_pressure);
CMDFN(pipette_read_capacitance);
CMDFN(pipette_test_pump_move_to_x100nl);
CMDFN(pipette_test_lld);
};
} // namespace iflytop

3
usrc/a8000_protocol/protocol/cmdid.cpp

@ -163,6 +163,9 @@ static cmdinfo_t table[] = {
CMD_ITERM(kpipette_read_tip_state),
CMD_ITERM(kpipette_read_pressure),
CMD_ITERM(kpipette_read_capacitance),
CMD_ITERM(kpipette_test_pump_move_to_x100nl),
CMD_ITERM(kpipette_test_lld),
};
const char* cmdid2str(int32_t code) {

7
usrc/a8000_protocol/protocol/cmdid.hpp

@ -158,8 +158,8 @@ typedef enum {
kpipette_zmotor_move_to = 0x7506,
kpipette_zmotor_read_zero_point_state = 0x7507,
kpipette_zmotor_read_dev_status_cache = 0x7508,
kpipette_zmotor_read_pos = 0x7509,
kpipette_zmotor_read_enc_pos = 0x750A,
kpipette_zmotor_read_pos = 0x7509,
kpipette_zmotor_read_enc_pos = 0x750A,
kpipette_pump_init_device = 0x7580,
kpipette_pump_take_tip = 0x7581,
@ -176,6 +176,9 @@ typedef enum {
kpipette_read_pressure = 0x758C, // ack:{state}
kpipette_read_capacitance = 0x758D, // ack:{state}
kpipette_test_pump_move_to_x100nl = 0x7600, // int32_t x100nl, int32_t vcfgindex
kpipette_test_lld = 0x7601, // int32_t container_pos, int32_t container_cpyid, int32_t liquid_cpyid
} cmdid_t;
typedef struct {

3
usrc/a8000_protocol/protocol/errorcode.cpp

@ -92,8 +92,7 @@ static ecode_table_item_t table[] = {
ERR_ITERM(kwater_cooling_pelter_is_error),
ERR_ITERM(kstep_motor_subic_init_fail),
ERR_ITERM(kstep_motor_subic_offline),
ERR_ITERM(kpipette_pm_positioning_abnormality),
};

1
usrc/a8000_protocol/protocol/errorcode.hpp

@ -70,6 +70,7 @@ typedef enum {
kpipette_error_pump_load_val_is_not_empty = 1503,
kpipette_lld_error_no_liquid_detected = 1504,
kpipette_lld_error_pump_reach_max_pos = 1505,
kpipette_pm_positioning_abnormality = 1506, // 电机定位异常
kstep_motor_not_found_zero_point = 1600,
kstep_motor_not_go_zero = 1601,

Loading…
Cancel
Save