From 2d3748394e237a6ede32dcc9be23dd9a48fe022e Mon Sep 17 00:00:00 2001 From: zhaohe Date: Mon, 26 May 2025 17:03:22 +0800 Subject: [PATCH] update --- .../pipette_module/base/pipette_action_param.hpp | 93 +- sdk/components/pipette_module/base/pipette_cfg.hpp | 146 ++- .../pipette_module/base/pipette_enum.hpp | 34 +- .../pipette_module/base/pipette_marco_utils.hpp | 1 + .../pipette_module/base/pipette_state.hpp | 49 +- .../pipette_module/pipette_ctrl_module.cpp | 1292 +++----------------- .../pipette_module/pipette_ctrl_module.hpp | 197 +-- .../pipette_ctrl_module_config_function_impl.cpp | 477 ++++++++ .../pipette_module/pipette_ctrl_module_pm_ctrl.cpp | 124 ++ .../pipette_module/pipette_ctrl_module_test.cpp | 116 ++ .../pipette_module/pipette_ctrl_module_utils.cpp | 194 +++ .../pipette_module/pipette_ctrl_module_zm_ctrl.cpp | 242 ++++ .../zcan_protocol_parser/zcan_protocol_parser.cpp | 58 + .../zcan_protocol_parser/zcan_protocol_parser.hpp | 11 + usrc/a8000_protocol/protocol/cmdid.cpp | 10 + usrc/a8000_protocol/protocol/cmdid.hpp | 44 +- usrc/a8000_protocol/protocol/errorcode.cpp | 2 + usrc/a8000_protocol/protocol/errorcode.hpp | 1 + 18 files changed, 1826 insertions(+), 1265 deletions(-) create mode 100644 sdk/components/pipette_module/pipette_ctrl_module_config_function_impl.cpp create mode 100644 sdk/components/pipette_module/pipette_ctrl_module_pm_ctrl.cpp create mode 100644 sdk/components/pipette_module/pipette_ctrl_module_test.cpp create mode 100644 sdk/components/pipette_module/pipette_ctrl_module_utils.cpp create mode 100644 sdk/components/pipette_module/pipette_ctrl_module_zm_ctrl.cpp diff --git a/sdk/components/pipette_module/base/pipette_action_param.hpp b/sdk/components/pipette_module/base/pipette_action_param.hpp index 28e74a3..86d4390 100644 --- a/sdk/components/pipette_module/base/pipette_action_param.hpp +++ b/sdk/components/pipette_module/base/pipette_action_param.hpp @@ -2,6 +2,10 @@ #include +#define CASE_ENUM_TO_STRING(enum_name) \ + case enum_name: \ + return #enum_name; + typedef struct { // // 吸取体积 @@ -37,6 +41,7 @@ typedef struct { // int32_t mix_volume; // 吸取前混匀体积 int32_t mix_times; // 吸取前混匀次数 + int32_t max; // 占位 } aspiration_param_t; typedef enum { @@ -73,21 +78,99 @@ typedef enum { // kaspiration_paramid_mix_volume, kaspiration_paramid_mix_times, + kaspiration_paramid_max, } aspiration_paramid_t; +static inline const char *aspiration_paramid_to_string(aspiration_paramid_t index) { + switch (index) { + CASE_ENUM_TO_STRING(kaspiration_paramid_volume); + CASE_ENUM_TO_STRING(kaspiration_paramid_container_pos); + CASE_ENUM_TO_STRING(kaspiration_paramid_container_info_index); + CASE_ENUM_TO_STRING(kaspiration_paramid_liquid_cfg_index); + CASE_ENUM_TO_STRING(kaspiration_paramid_aspiration_mode); + CASE_ENUM_TO_STRING(kaspiration_paramid_lld_enable); + CASE_ENUM_TO_STRING(kaspiration_paramid_lld_type); + CASE_ENUM_TO_STRING(kaspiration_paramid_lld_enable_protect); + CASE_ENUM_TO_STRING(kaspiration_paramid_mix_llf_enable); + CASE_ENUM_TO_STRING(kaspiration_paramid_llf_enable); + CASE_ENUM_TO_STRING(kaspiration_paramid_mix_volume); + CASE_ENUM_TO_STRING(kaspiration_paramid_mix_times); + CASE_ENUM_TO_STRING(kaspiration_paramid_max); + } + return "unknown"; +} + typedef struct { // - // 容器 + // 容器位置 // - int32_t container_pos; // 容器位置 - int32_t container_info_index; // 容器配置索引 + int32_t container_pos; // 容器位置 + // - // 液体类型 + // 目标容器信息 // - int32_t liquid_cfg_index; // 液体配置索引 + int32_t dest_container_cpyid; // 目标容器配置索引 + int32_t dest_container_is_empty; // 目标容器是否为空 + int32_t dest_liquid_cfg_index; // 目标容器中的液体类型 + + // + // 分配方式 + // + int32_t distribu_type; // 分配类型 0:液面上分配,1:液面下分配 + // // 混匀配置 // int32_t mix_volume; // 混匀体积 int32_t mix_times; // 混匀次数 + // + // 其他配置 + // + int32_t zm_auto_move_to_zero; // zm自动归零 + int32_t max; } distribu_all_param_t; + +typedef enum { + // + // 容器位置 + // + kdistribu_all_paramid_container_pos, + // + // 目标容器信息 + // + kdistribu_all_paramid_dest_container_cpyid, + kdistribu_all_paramid_dest_container_is_empty, + kdistribu_all_paramid_dest_liquid_cfg_index, + // + // 分配方式 + // + kdistribu_all_paramid_distribu_type, + // + // 混匀配置 + // + kdistribu_all_paramid_mix_volume, + kdistribu_all_paramid_mix_times, + // + // 其他配置 + // + kdistribu_all_paramid_zm_auto_move_to_zero, // zm自动归零 + kdistribu_all_paramid_max, +} distribu_all_paramid_t; + +static inline const char *distribu_all_paramid_to_string(distribu_all_paramid_t index) { + switch (index) { + CASE_ENUM_TO_STRING(kdistribu_all_paramid_container_pos); + CASE_ENUM_TO_STRING(kdistribu_all_paramid_dest_container_cpyid); + CASE_ENUM_TO_STRING(kdistribu_all_paramid_dest_container_is_empty); + CASE_ENUM_TO_STRING(kdistribu_all_paramid_dest_liquid_cfg_index); + CASE_ENUM_TO_STRING(kdistribu_all_paramid_distribu_type); + CASE_ENUM_TO_STRING(kdistribu_all_paramid_mix_volume); + CASE_ENUM_TO_STRING(kdistribu_all_paramid_mix_times); + CASE_ENUM_TO_STRING(kdistribu_all_paramid_zm_auto_move_to_zero); + CASE_ENUM_TO_STRING(kdistribu_all_paramid_max); + } + return "unknown"; +} +#undef CASE_ENUM_TO_STRING + +// \ No newline at end of file diff --git a/sdk/components/pipette_module/base/pipette_cfg.hpp b/sdk/components/pipette_module/base/pipette_cfg.hpp index 2fddaef..7e9b5f7 100644 --- a/sdk/components/pipette_module/base/pipette_cfg.hpp +++ b/sdk/components/pipette_module/base/pipette_cfg.hpp @@ -6,6 +6,10 @@ * 所有成员,必须是int32_t,则有效值必须大于零,小于零的认为是无效值 */ +#define CASE_ENUM_TO_STRING(enum_name) \ + case enum_name: \ + return #enum_name; + /*********************************************************************************************************************** * 平台参数 * ***********************************************************************************************************************/ @@ -50,6 +54,21 @@ typedef enum { kplatinfo_mark, } platinfo_index_t; +static inline const char *platinfo_index_to_string(platinfo_index_t index) { + switch (index) { + CASE_ENUM_TO_STRING(kplatinfo_work_ref_pos) + CASE_ENUM_TO_STRING(kplatinfo_tip_picking_pos) + CASE_ENUM_TO_STRING(kplatinfo_tip_picking_search_range) + CASE_ENUM_TO_STRING(kplatinfo_tip_picking_append_distance) + CASE_ENUM_TO_STRING(kplatinfo_tip_deposit_pos) + CASE_ENUM_TO_STRING(kplatinfo_transform_pos) + CASE_ENUM_TO_STRING(kplatinfo_tip_type) + CASE_ENUM_TO_STRING(kplatinfo_tip_length) + CASE_ENUM_TO_STRING(kplatinfo_mark) + } + return "unknown"; +} // platinfo_index_to_string + /*********************************************************************************************************************** * Z轴电机基础配置 * ***********************************************************************************************************************/ @@ -90,9 +109,32 @@ typedef enum { kzm_bcfg_io_trigger_append_distance, kzm_bcfg_pos_devi_tolerance, kzm_bcfg_mres, - kzm_bcfg_mark, + kzm_bcfg_max, } zm_bcfg_index_t; +static inline const char *zm_bcfg_index_to_string(zm_bcfg_index_t index) { + switch (index) { + CASE_ENUM_TO_STRING(kzm_bcfg_shaft) + CASE_ENUM_TO_STRING(kzm_bcfg_one_circle_pulse) + CASE_ENUM_TO_STRING(kzm_bcfg_one_circle_pulse_denominator) + CASE_ENUM_TO_STRING(kzm_bcfg_ihold) + CASE_ENUM_TO_STRING(kzm_bcfg_irun) + CASE_ENUM_TO_STRING(kzm_bcfg_iholddelay) + CASE_ENUM_TO_STRING(kzm_bcfg_iglobalscaler) + CASE_ENUM_TO_STRING(kzm_bcfg_min_d) + CASE_ENUM_TO_STRING(kzm_bcfg_max_d) + CASE_ENUM_TO_STRING(kzm_bcfg_tzerowait) + CASE_ENUM_TO_STRING(kzm_bcfg_enc_resolution) + CASE_ENUM_TO_STRING(kzm_bcfg_enable_enc) + CASE_ENUM_TO_STRING(kzm_bcfg_dzero) + CASE_ENUM_TO_STRING(kzm_bcfg_io_trigger_append_distance) + CASE_ENUM_TO_STRING(kzm_bcfg_pos_devi_tolerance) + CASE_ENUM_TO_STRING(kzm_bcfg_mres) + CASE_ENUM_TO_STRING(kzm_bcfg_max) + } + return "unknown"; +} // zm_bcfg_index_to_string + /*********************************************************************************************************************** * 移液枪基础配置 * ***********************************************************************************************************************/ @@ -105,6 +147,14 @@ typedef enum { kpm_bcfg_mark, } pm_bcfg_index_t; +static inline const char *pm_bcfg_index_to_string(pm_bcfg_index_t index) { + switch (index) { + CASE_ENUM_TO_STRING(kpm_bcfg_pad) + CASE_ENUM_TO_STRING(kpm_bcfg_mark) + } + return "unknown"; +} // pm_bcfg_index_to_string + /*********************************************************************************************************************** * Z轴速度配置 * ***********************************************************************************************************************/ @@ -129,9 +179,24 @@ typedef enum { kzm_vcfg_d1, kzm_vcfg_vstop, kzm_vcfg_vmax, - kzm_vcfg_mark, + kzm_vcfg_max, } zm_vcfg_index_t; +static inline const char *zm_vcfg_index_to_string(zm_vcfg_index_t index) { + switch (index) { + CASE_ENUM_TO_STRING(kzm_vcfg_vstart) + CASE_ENUM_TO_STRING(kzm_vcfg_a1) + CASE_ENUM_TO_STRING(kzm_vcfg_amax) + CASE_ENUM_TO_STRING(kzm_vcfg_v1) + CASE_ENUM_TO_STRING(kzm_vcfg_dmax) + CASE_ENUM_TO_STRING(kzm_vcfg_d1) + CASE_ENUM_TO_STRING(kzm_vcfg_vstop) + CASE_ENUM_TO_STRING(kzm_vcfg_vmax) + CASE_ENUM_TO_STRING(kzm_vcfg_max) + } + return "unknown"; +} // zm_vcfg_index_to_string + /*********************************************************************************************************************** * 移液枪速度配置 * ***********************************************************************************************************************/ @@ -150,9 +215,21 @@ typedef enum { kpm_vcfg_vstart, // 启动速度 ul/s (0...319) kpm_vcfg_vstop, // 停止速度 ul/s (0...319) kpm_vcfg_vmax, // 最大速度 ul/s (0...2552) - kpm_vcfg_mark, // 结构体最后一个数值,设置9973,用于保证单片机端和java端均正确更新了枚举 + kpm_vcfg_max, // 结构体最后一个数值,设置9973,用于保证单片机端和java端均正确更新了枚举 } pm_vcfg_index_t; +static inline const char *pm_vcfg_index_to_string(pm_vcfg_index_t index) { + switch (index) { + CASE_ENUM_TO_STRING(kpm_vcfg_acc) + CASE_ENUM_TO_STRING(kpm_vcfg_dec) + CASE_ENUM_TO_STRING(kpm_vcfg_vstart) + CASE_ENUM_TO_STRING(kpm_vcfg_vstop) + CASE_ENUM_TO_STRING(kpm_vcfg_vmax) + CASE_ENUM_TO_STRING(kpm_vcfg_max) + } + return "unknown"; +} // pm_vcfg_index_to_string + /*********************************************************************************************************************** * 容器参数 * ***********************************************************************************************************************/ @@ -188,6 +265,25 @@ typedef enum { kcontainer_info_mark, } container_info_index_t; +static inline const char *container_info_index_to_string(container_info_index_t index) { + switch (index) { + CASE_ENUM_TO_STRING(kcontainer_info_container_type) + CASE_ENUM_TO_STRING(kcontainer_info_container_neck_pos) + CASE_ENUM_TO_STRING(kcontainer_info_container_depth) + CASE_ENUM_TO_STRING(kcontainer_info_container_round) + CASE_ENUM_TO_STRING(kcontainer_info_container_bottom_section_height) + CASE_ENUM_TO_STRING(kcontainer_info_immersion_depth) + CASE_ENUM_TO_STRING(kcontainer_info_leaving_height) + CASE_ENUM_TO_STRING(kcontainer_info_jet_height) + CASE_ENUM_TO_STRING(kcontainer_info_lld_start_search_depth) + CASE_ENUM_TO_STRING(kcontainer_info_fix_water_level_depth) + CASE_ENUM_TO_STRING(kcontainer_info_llf_vconvert_coneff) + CASE_ENUM_TO_STRING(kcontainer_info_pierce_depth) + CASE_ENUM_TO_STRING(kcontainer_info_mark) + } + return "unknown"; +} + /*********************************************************************************************************************** * 液体参数 * ***********************************************************************************************************************/ @@ -267,14 +363,21 @@ typedef struct { // // 转移时多吸入的量 // - int32_t transport_volume; // 转移过程中多吸入的量,精度0.1ul (放滴落) + int32_t transport_volume; // 转移过程中多吸入的量,精度0.1ul (防滴落) int32_t transport_volume_pm_vcpyid; // 吸入过量空气时泵机速率 // // 混匀pm速率 // int32_t mix_pm_vcpyid; // 混匀时泵机速率配置 - int32_t mark; // 结构体最后一个数值,设置9973,用于保证单片机端和java端均正确更新了枚举 + + // + // 分配配置 + // + int32_t jet_pm_vcpyid; // 喷射时泵机速率配置 + int32_t distribu_pm_vpyid; // 分配时泵机速率配置 + + int32_t mark; // 结构体最后一个数值,设置9973,用于保证单片机端和java端均正确更新了枚举 } liquid_info_t; typedef enum { @@ -295,5 +398,36 @@ typedef enum { kliquid_info_transport_volume, kliquid_info_transport_volume_pm_vcpyid, kliquid_info_mix_pm_vindex, + kliquid_info_jet_pm_vcpyid, + kliquid_info_distribu_pm_vpyid, kliquid_info_mark, -} liquid_info_index_t; \ No newline at end of file +} liquid_info_index_t; + +static inline const char *liquid_info_index_to_string(liquid_info_index_t index) { + switch (index) { + CASE_ENUM_TO_STRING(kliquid_info_plld_pm_vcpyid); + CASE_ENUM_TO_STRING(kliquid_info_plld_threshold); + CASE_ENUM_TO_STRING(kliquid_info_plld_zm_vel); + CASE_ENUM_TO_STRING(kliquid_info_empty_tip_pm_vcpyid); + CASE_ENUM_TO_STRING(kliquid_info_blowout_air_volume); + CASE_ENUM_TO_STRING(kliquid_info_blowout_air_pm_vcpyid); + CASE_ENUM_TO_STRING(kliquid_info_over_aspirated_volume); + CASE_ENUM_TO_STRING(kliquid_info_over_aspirated_pm_vcpyid); + CASE_ENUM_TO_STRING(kliquid_info_aspiration_pm_vindex_low); + CASE_ENUM_TO_STRING(kliquid_info_aspiration_pm_vindex_high); + CASE_ENUM_TO_STRING(kliquid_info_aspiration_volume_break_val); + CASE_ENUM_TO_STRING(kliquid_info_volume_calibration_coefficient_b); + CASE_ENUM_TO_STRING(kliquid_info_volume_calibration_coefficient_k); + CASE_ENUM_TO_STRING(kliquid_info_settling_time); + CASE_ENUM_TO_STRING(kliquid_info_transport_volume); + CASE_ENUM_TO_STRING(kliquid_info_transport_volume_pm_vcpyid); + CASE_ENUM_TO_STRING(kliquid_info_mix_pm_vindex); + CASE_ENUM_TO_STRING(kliquid_info_jet_pm_vcpyid); + CASE_ENUM_TO_STRING(kliquid_info_distribu_pm_vpyid); + CASE_ENUM_TO_STRING(kliquid_info_mark); + default: + return "unknown liquid info index"; + } +} + +#undef CASE_ENUM_TO_STRING diff --git a/sdk/components/pipette_module/base/pipette_enum.hpp b/sdk/components/pipette_module/base/pipette_enum.hpp index a5b3812..e6e87e6 100644 --- a/sdk/components/pipette_module/base/pipette_enum.hpp +++ b/sdk/components/pipette_module/base/pipette_enum.hpp @@ -12,20 +12,6 @@ typedef enum { kpm_v_max = 6, // 高速 kpm_v_lld = 7, // 液面探测vlld } pm_vcpyid_t; - -/*********************************************************************************************************************** - * Z电机预设速度配置 * - ***********************************************************************************************************************/ -typedef enum { - kzm_v_default = 0, // 默认速度 - kzm_v_move_to_zero = 1, // 回零速度 - kzm_v_look_zero_edge = 2, // 找零点偏移速度 - kzm_v_lld = 3, // 液面探测vlld - kzm_v_swap = 4, // 交换液面探测 - kzm_v_llf = 5, // 液面基础速度配置 - kzm_v_picking_tip = 6, // 取tip速度 -} zm_vcpyid_t; - static inline const char *get_pm_vcpyid_name(pm_vcpyid_t id) { static char buf[20]; #define CASE(x) \ @@ -47,6 +33,21 @@ static inline const char *get_pm_vcpyid_name(pm_vcpyid_t id) { snprintf(buf, sizeof(buf), "unmatch(%d)", id); return buf; } +/*********************************************************************************************************************** + * Z电机预设速度配置 * + ***********************************************************************************************************************/ +typedef enum { + kzm_v_default = 0, // 默认速度 + kzm_v_move_to_zero = 1, // 回零速度 + kzm_v_look_zero_edge = 2, // 找零点偏移速度 + kzm_v_lld = 3, // 液面探测vlld + kzm_v____0 = 4, // 占位 + kzm_v_llf = 5, // 液面基础速度配置 + kzm_v_picking_tip = 6, // 取tip速度 + kzm_v_swap_in = 7, // 交换液面探测 + kzm_v_swap_out = 8, // 交换液面探测 + +} zm_vcpyid_t; static inline const char *get_zm_vcpyid_name(zm_vcpyid_t id) { static char buf[20]; @@ -58,13 +59,14 @@ static inline const char *get_zm_vcpyid_name(zm_vcpyid_t id) { CASE(kzm_v_move_to_zero); CASE(kzm_v_look_zero_edge); CASE(kzm_v_lld); - CASE(kzm_v_swap); CASE(kzm_v_llf); CASE(kzm_v_picking_tip); + CASE(kzm_v_swap_in); + CASE(kzm_v_swap_out); default: break; } #undef CASE snprintf(buf, sizeof(buf), "unmatch(%d)", id); return buf; -} \ No newline at end of file +} diff --git a/sdk/components/pipette_module/base/pipette_marco_utils.hpp b/sdk/components/pipette_module/base/pipette_marco_utils.hpp index 308e02e..053168f 100644 --- a/sdk/components/pipette_module/base/pipette_marco_utils.hpp +++ b/sdk/components/pipette_module/base/pipette_marco_utils.hpp @@ -62,4 +62,5 @@ break; \ } + // \ No newline at end of file diff --git a/sdk/components/pipette_module/base/pipette_state.hpp b/sdk/components/pipette_module/base/pipette_state.hpp index e29c086..473f16b 100644 --- a/sdk/components/pipette_module/base/pipette_state.hpp +++ b/sdk/components/pipette_module/base/pipette_state.hpp @@ -1,6 +1,10 @@ #pragma once #include +#define CASE_ENUM_TO_STRING(enum_name) \ + case enum_name: \ + return #enum_name; + typedef struct { /** * @brief Z轴状态 @@ -11,7 +15,7 @@ typedef struct { int32_t zm_has_move_zero; /** - * @brief 泵机状态 + * @brief 吸液结果报告 */ int32_t aspiration_ok; // 吸液成功 @@ -22,14 +26,16 @@ typedef struct { int32_t airsuction; // int32_t bubble; // - int32_t zm_now_vcfg_index = -1; - int32_t pm_now_vcfg_index = -1; - + /** + * @brief 异步执行结果通用报告 + */ int32_t asynchronous_result0; int32_t asynchronous_result1; + /** + * @brief 当前平台参数 + */ int32_t platinfo_cpyid = 0; - } pipette_state_t; typedef enum { @@ -44,10 +50,39 @@ typedef enum { kpipette_state_tipblock, kpipette_state_airsuction, kpipette_state_bubble, - kpipette_state_zm_now_vcfg_index, - kpipette_state_pm_now_vcfg_index, kpipette_state_asynchronous_result0, kpipette_state_asynchronous_result1, kpipette_state_platinfo_cpyid, kpipette_state_max, } pipette_state_index_t; + +static inline const char *pipette_state_index_to_string(pipette_state_index_t index) { + switch (index) { + CASE_ENUM_TO_STRING(kpipette_state_enable) + CASE_ENUM_TO_STRING(kpipette_state_dul) + CASE_ENUM_TO_STRING(kpipette_state_dpos) + CASE_ENUM_TO_STRING(kpipette_state_zm_has_move_zero) + CASE_ENUM_TO_STRING(kpipette_state_aspiration_ok) + CASE_ENUM_TO_STRING(kpipette_state_pump_lld_reach_limit) + CASE_ENUM_TO_STRING(kpipette_state_detected_liquid) + CASE_ENUM_TO_STRING(kpipette_state_water_level) + CASE_ENUM_TO_STRING(kpipette_state_tipblock) + CASE_ENUM_TO_STRING(kpipette_state_airsuction) + CASE_ENUM_TO_STRING(kpipette_state_bubble) + CASE_ENUM_TO_STRING(kpipette_state_asynchronous_result0) + CASE_ENUM_TO_STRING(kpipette_state_asynchronous_result1) + CASE_ENUM_TO_STRING(kpipette_state_platinfo_cpyid) + CASE_ENUM_TO_STRING(kpipette_state_max) + } + return "unknown"; +} // pipette_state_index_to_string + +typedef struct { + int32_t is_has_liquid; // 是否有液体 + int32_t liquid_type_cpyidx; // 移液枪中液体类型索引 + int32_t liquid_volume; // 移液枪中液体体积(0.1ul) + int32_t transport_volume; // 转移过程中多吸入的量,精度0.1ul (放滴落) + int32_t blowout_air_volume; // 预先吸入的空气体积(0.1ul) +} pump_gun_state_t; + +#undef CASE_ENUM_TO_STRING \ No newline at end of file diff --git a/sdk/components/pipette_module/pipette_ctrl_module.cpp b/sdk/components/pipette_module/pipette_ctrl_module.cpp index e59ef49..cdddc79 100644 --- a/sdk/components/pipette_module/pipette_ctrl_module.cpp +++ b/sdk/components/pipette_module/pipette_ctrl_module.cpp @@ -119,395 +119,10 @@ int32_t PipetteModule::module_stop() { return 0; } -int32_t PipetteModule::pipette_set_zmbcfg(zm_bcfg_index_t index, int32_t val) { - switch (index) { - SET_CFG(kzm_bcfg_shaft, zmbcfg.shaft, val); - SET_CFG(kzm_bcfg_one_circle_pulse, zmbcfg.one_circle_pulse, val); - SET_CFG(kzm_bcfg_one_circle_pulse_denominator, zmbcfg.one_circle_pulse_denominator, val); - SET_CFG(kzm_bcfg_ihold, zmbcfg.ihold, val); - SET_CFG(kzm_bcfg_irun, zmbcfg.irun, val); - SET_CFG(kzm_bcfg_iholddelay, zmbcfg.iholddelay, val); - SET_CFG(kzm_bcfg_iglobalscaler, zmbcfg.iglobalscaler, val); - SET_CFG(kzm_bcfg_min_d, zmbcfg.min_d, val); - SET_CFG(kzm_bcfg_max_d, zmbcfg.max_d, val); - SET_CFG(kzm_bcfg_tzerowait, zmbcfg.tzerowait, val); - SET_CFG(kzm_bcfg_enc_resolution, zmbcfg.enc_resolution, val); - SET_CFG(kzm_bcfg_enable_enc, zmbcfg.enable_enc, val); - SET_CFG(kzm_bcfg_dzero, zmbcfg.dzero, val); - SET_CFG(kzm_bcfg_io_trigger_append_distance, zmbcfg.io_trigger_append_distance, val); - SET_CFG(kzm_bcfg_pos_devi_tolerance, zmbcfg.pos_devi_tolerance, val); - SET_CFG(kzm_bcfg_mres, zmbcfg.mres, val); - SET_CFG(kzm_bcfg_mark, zmbcfg.mark, val); - - default: { - ZLOGE(TAG, "pipette_set_zmbcfg index %d out of range", index); - return err::kparam_out_of_range; - } - } - zm_sync_base_cfg(); - return 0; -} -int32_t PipetteModule::pipette_get_zmbcfg(zm_bcfg_index_t index, int32_t *val) { - switch (index) { - GET_CFG(kzm_bcfg_shaft, zmbcfg.shaft, val); - GET_CFG(kzm_bcfg_one_circle_pulse, zmbcfg.one_circle_pulse, val); - GET_CFG(kzm_bcfg_one_circle_pulse_denominator, zmbcfg.one_circle_pulse_denominator, val); - GET_CFG(kzm_bcfg_ihold, zmbcfg.ihold, val); - GET_CFG(kzm_bcfg_irun, zmbcfg.irun, val); - GET_CFG(kzm_bcfg_iholddelay, zmbcfg.iholddelay, val); - GET_CFG(kzm_bcfg_iglobalscaler, zmbcfg.iglobalscaler, val); - GET_CFG(kzm_bcfg_min_d, zmbcfg.min_d, val); - GET_CFG(kzm_bcfg_max_d, zmbcfg.max_d, val); - GET_CFG(kzm_bcfg_tzerowait, zmbcfg.tzerowait, val); - GET_CFG(kzm_bcfg_enc_resolution, zmbcfg.enc_resolution, val); - GET_CFG(kzm_bcfg_enable_enc, zmbcfg.enable_enc, val); - GET_CFG(kzm_bcfg_dzero, zmbcfg.dzero, val); - GET_CFG(kzm_bcfg_io_trigger_append_distance, zmbcfg.io_trigger_append_distance, val); - GET_CFG(kzm_bcfg_pos_devi_tolerance, zmbcfg.pos_devi_tolerance, val); - GET_CFG(kzm_bcfg_mres, zmbcfg.mres, val); - GET_CFG(kzm_bcfg_mark, zmbcfg.mark, val); - default: { - ZLOGE(TAG, "pipette_get_zmbcfg index %d out of range", index); - return err::kparam_out_of_range; - } - } - - return 0; -} -int32_t PipetteModule::pipette_set_pmbcfg(pm_bcfg_index_t index, int32_t val) { - switch (index) { - SET_CFG(kpm_bcfg_pad, pm_base_cfg.pad, val); - SET_CFG(kpm_bcfg_mark, pm_base_cfg.mark, val); - default: { - ZLOGE(TAG, "pipette_set_pmbcfg index %d out of range", index); - return err::kparam_out_of_range; - } - } - return 0; -} -int32_t PipetteModule::pipette_get_pmbcfg(pm_bcfg_index_t index, int32_t *val) { - switch (index) { - GET_CFG(kpm_bcfg_pad, pm_base_cfg.pad, val); - GET_CFG(kpm_bcfg_mark, pm_base_cfg.mark, val); - default: { - ZLOGE(TAG, "pipette_get_pmbcfg index %d out of range", index); - return err::kparam_out_of_range; - } - } - return 0; -} -int32_t PipetteModule::pipette_set_platinfo(int32_t cpyid, platinfo_index_t index, int32_t val) { - if (cpyid < 0 || cpyid >= ARRARY_SIZE(m_platinfo)) { - ZLOGE(TAG, "pipette_set_platinfo cpyid %d out of range", cpyid); - return err::kparam_out_of_range; - } - - platinfo_t *platinfo = &m_platinfo[cpyid]; - - switch (index) { - SET_CFG(kplatinfo_work_ref_pos, platinfo->work_ref_pos, val); - SET_CFG(kplatinfo_tip_picking_pos, platinfo->tip_picking_pos, val); - SET_CFG(kplatinfo_tip_picking_search_range, platinfo->tip_picking_search_range, val); - SET_CFG(kplatinfo_tip_picking_append_distance, platinfo->tip_picking_append_distance, val); - SET_CFG(kplatinfo_tip_deposit_pos, platinfo->tip_deposit_pos, val); - SET_CFG(kplatinfo_transform_pos, platinfo->_transform_pos, val); - SET_CFG(kplatinfo_tip_type, platinfo->tip_type, val); - SET_CFG(kplatinfo_tip_length, platinfo->tip_length, val); - SET_CFG(kplatinfo_mark, platinfo->mark, val); - default: { - ZLOGE(TAG, "pipette_set_platinfo index %d out of range", index); - return err::kparam_out_of_range; - } - } - return 0; -} -int32_t PipetteModule::pipette_get_platinfo(int32_t cpyid, platinfo_index_t index, int32_t *val) { - if (cpyid < 0 || cpyid >= ARRARY_SIZE(m_platinfo)) { - ZLOGE(TAG, "pipette_get_platinfo cpyid %d out of range", cpyid); - return err::kparam_out_of_range; - } - - platinfo_t *platinfo = &m_platinfo[cpyid]; - switch (index) { - GET_CFG(kplatinfo_work_ref_pos, platinfo->work_ref_pos, val); - GET_CFG(kplatinfo_tip_picking_pos, platinfo->tip_picking_pos, val); - GET_CFG(kplatinfo_tip_picking_search_range, platinfo->tip_picking_search_range, val); - GET_CFG(kplatinfo_tip_picking_append_distance, platinfo->tip_picking_append_distance, val); - GET_CFG(kplatinfo_tip_deposit_pos, platinfo->tip_deposit_pos, val); - GET_CFG(kplatinfo_transform_pos, platinfo->_transform_pos, val); - GET_CFG(kplatinfo_tip_type, platinfo->tip_type, val); - GET_CFG(kplatinfo_tip_length, platinfo->tip_length, val); - GET_CFG(kplatinfo_mark, platinfo->mark, val); - default: { - ZLOGE(TAG, "pipette_get_platinfo index %d out of range", index); - return err::kparam_out_of_range; - } - } - return 0; -} -int32_t PipetteModule::pipette_set_zmvcfg(int32_t cpyid, zm_vcfg_index_t index, int32_t val) { - if (cpyid < 0 || cpyid >= ARRARY_SIZE(m_zm_vcfg)) { - ZLOGE(TAG, "pipette_set_zmvcfg cpyid %d out of range", cpyid); - return err::kparam_out_of_range; - } - - zm_vcfg_t *cfg = &m_zm_vcfg[cpyid]; - switch (index) { - SET_CFG(kzm_vcfg_vstart, cfg->vstart, val); - SET_CFG(kzm_vcfg_a1, cfg->a1, val); - SET_CFG(kzm_vcfg_amax, cfg->amax, val); - SET_CFG(kzm_vcfg_v1, cfg->v1, val); - SET_CFG(kzm_vcfg_dmax, cfg->dmax, val); - SET_CFG(kzm_vcfg_d1, cfg->d1, val); - SET_CFG(kzm_vcfg_vstop, cfg->vstop, val); - SET_CFG(kzm_vcfg_vmax, cfg->vmax, val); - SET_CFG(kzm_vcfg_mark, cfg->mark, val); - default: { - ZLOGE(TAG, "pipette_set_zmvcfg index %d out of range", index); - return err::kparam_out_of_range; - } - } - - if (cpyid == m_state.zm_now_vcfg_index) { - m_state.zm_now_vcfg_index = -1; - } - - return 0; -} -int32_t PipetteModule::pipette_get_zmvcfg(int32_t cpyid, zm_vcfg_index_t index, int32_t *val) { - if (cpyid < 0 || cpyid >= ARRARY_SIZE(m_zm_vcfg)) { - ZLOGE(TAG, "pipette_get_zmvcfg cpyid %d out of range", cpyid); - return err::kparam_out_of_range; - } - zm_vcfg_t *cfg = &m_zm_vcfg[cpyid]; - switch (index) { - GET_CFG(kzm_vcfg_vstart, cfg->vstart, val); - GET_CFG(kzm_vcfg_a1, cfg->a1, val); - GET_CFG(kzm_vcfg_amax, cfg->amax, val); - GET_CFG(kzm_vcfg_v1, cfg->v1, val); - GET_CFG(kzm_vcfg_dmax, cfg->dmax, val); - GET_CFG(kzm_vcfg_d1, cfg->d1, val); - GET_CFG(kzm_vcfg_vstop, cfg->vstop, val); - GET_CFG(kzm_vcfg_vmax, cfg->vmax, val); - GET_CFG(kzm_vcfg_mark, cfg->mark, val); - default: { - ZLOGE(TAG, "pipette_get_zmvcfg index %d out of range", index); - return err::kparam_out_of_range; - } - } - return 0; -} -int32_t PipetteModule::pipette_set_pmvcfg(int32_t cpyid, pm_vcfg_index_t index, int32_t val) { - if (cpyid < 0 || cpyid >= ARRARY_SIZE(m_pm_vcfg)) { - ZLOGE(TAG, "pipette_set_pmvcfg cpyid %d out of range", cpyid); - return err::kparam_out_of_range; - } - - pm_vcfg_t *cfg = &m_pm_vcfg[cpyid]; - switch (index) { - SET_CFG(kpm_vcfg_acc, cfg->acc, val); - SET_CFG(kpm_vcfg_dec, cfg->dec, val); - SET_CFG(kpm_vcfg_vstart, cfg->vstart, val); - SET_CFG(kpm_vcfg_vstop, cfg->vstop, val); - SET_CFG(kpm_vcfg_vmax, cfg->vmax, val); - SET_CFG(kpm_vcfg_mark, cfg->mark, val); - default: { - ZLOGE(TAG, "pipette_set_pmvcfg index %d out of range", index); - return err::kparam_out_of_range; - } - } - - if (cpyid == m_state.pm_now_vcfg_index) { - m_state.pm_now_vcfg_index = -1; - } - - return 0; -} -int32_t PipetteModule::pipette_get_pmvcfg(int32_t cpyid, pm_vcfg_index_t index, int32_t *val) { - if (cpyid < 0 || cpyid >= ARRARY_SIZE(m_pm_vcfg)) { - ZLOGE(TAG, "pipette_get_pmvcfg cpyid %d out of range", cpyid); - return err::kparam_out_of_range; - } - pm_vcfg_t *cfg = &m_pm_vcfg[cpyid]; - switch (index) { - GET_CFG(kpm_vcfg_acc, cfg->acc, val); - GET_CFG(kpm_vcfg_dec, cfg->dec, val); - GET_CFG(kpm_vcfg_vstart, cfg->vstart, val); - GET_CFG(kpm_vcfg_vstop, cfg->vstop, val); - GET_CFG(kpm_vcfg_vmax, cfg->vmax, val); - GET_CFG(kpm_vcfg_mark, cfg->mark, val); - default: { - ZLOGE(TAG, "pipette_get_pmvcfg index %d out of range", index); - return err::kparam_out_of_range; - } - } - return 0; -} -int32_t PipetteModule::pipette_set_container_info(int32_t cpyid, container_info_index_t index, int32_t val) { - if (cpyid < 0 || cpyid >= ARRARY_SIZE(m_container_info)) { - ZLOGE(TAG, "pipette_set_container_info cpyid %d out of range", cpyid); - return err::kparam_out_of_range; - } - - container_info_t *cfg = &m_container_info[cpyid]; - switch (index) { - SET_CFG(kcontainer_info_container_type, cfg->container_type, val); - SET_CFG(kcontainer_info_container_neck_pos, cfg->_container_neck_pos, val); - SET_CFG(kcontainer_info_container_depth, cfg->container_depth, val); - SET_CFG(kcontainer_info_container_round, cfg->container_round, val); - SET_CFG(kcontainer_info_container_bottom_section_height, cfg->container_bottom_section_height, val); - SET_CFG(kcontainer_info_immersion_depth, cfg->immersion_depth, val); - 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_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); - - default: { - ZLOGE(TAG, "pipette_set_container_info index %d out of range", index); - return err::kparam_out_of_range; - } - } - return 0; -} -int32_t PipetteModule::pipette_get_container_info(int32_t cpyid, container_info_index_t index, int32_t *val) { - if (cpyid < 0 || cpyid >= ARRARY_SIZE(m_container_info)) { - ZLOGE(TAG, "pipette_get_container_info cpyid %d out of range", cpyid); - return err::kparam_out_of_range; - } - - container_info_t *cfg = &m_container_info[cpyid]; - switch (index) { - GET_CFG(kcontainer_info_container_type, cfg->container_type, val); - GET_CFG(kcontainer_info_container_neck_pos, cfg->_container_neck_pos, val); - GET_CFG(kcontainer_info_container_depth, cfg->container_depth, val); - GET_CFG(kcontainer_info_container_round, cfg->container_round, val); - GET_CFG(kcontainer_info_container_bottom_section_height, cfg->container_bottom_section_height, val); - GET_CFG(kcontainer_info_immersion_depth, cfg->immersion_depth, val); - 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_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); - default: { - ZLOGE(TAG, "pipette_get_container_info index %d out of range", index); - return err::kparam_out_of_range; - } - } - return 0; -} -int32_t PipetteModule::pipette_set_liquid_info(int32_t cpyid, liquid_info_index_t index, int32_t val) { - if (cpyid < 0 || cpyid >= ARRARY_SIZE(m_liquid_info)) { - ZLOGE(TAG, "pipette_set_liquid_info cpyid %d out of range", cpyid); - return err::kparam_out_of_range; - } - - liquid_info_t *cfg = &m_liquid_info[cpyid]; - switch (index) { - SET_CFG(kliquid_info_plld_pm_vcpyid, cfg->plld_pm_vcpyid, val); - SET_CFG(kliquid_info_plld_threshold, cfg->plld_threshold, val); - SET_CFG(kliquid_info_plld_zm_vel, cfg->plld_zm_vel, val); - SET_CFG(kliquid_info_empty_tip_pm_vcpyid, cfg->empty_tip_pm_vcpyid, val); - SET_CFG(kliquid_info_blowout_air_volume, cfg->blowout_air_volume, val); - SET_CFG(kliquid_info_blowout_air_pm_vcpyid, cfg->blowout_air_pm_vcpyid, val); - SET_CFG(kliquid_info_over_aspirated_volume, cfg->over_aspirated_volume, val); - SET_CFG(kliquid_info_over_aspirated_pm_vcpyid, cfg->over_aspirated_pm_vcpyid, val); - SET_CFG(kliquid_info_aspiration_pm_vindex_low, cfg->aspiration_pm_vindex_low, val); - SET_CFG(kliquid_info_aspiration_pm_vindex_high, cfg->aspiration_pm_vindex_high, val); - SET_CFG(kliquid_info_aspiration_volume_break_val, cfg->aspiration_volume_break_val, val); - SET_CFG(kliquid_info_volume_calibration_coefficient_b, cfg->volume_calibration_coefficient_b, val); - SET_CFG(kliquid_info_volume_calibration_coefficient_k, cfg->volume_calibration_coefficient_k, val); - SET_CFG(kliquid_info_settling_time, cfg->settling_time, val); - SET_CFG(kliquid_info_transport_volume, cfg->transport_volume, val); - SET_CFG(kliquid_info_transport_volume_pm_vcpyid, cfg->transport_volume_pm_vcpyid, val); - SET_CFG(kliquid_info_mix_pm_vindex, cfg->mix_pm_vcpyid, val); - SET_CFG(kliquid_info_mark, cfg->mark, val); - - default: { - ZLOGE(TAG, "pipette_set_liquid_info index %d out of range", index); - return err::kparam_out_of_range; - } - } - return 0; -} -int32_t PipetteModule::pipette_get_liquid_info(int32_t cpyid, liquid_info_index_t index, int32_t *val) { - if (cpyid < 0 || cpyid >= ARRARY_SIZE(m_liquid_info)) { - ZLOGE(TAG, "pipette_get_liquid_info cpyid %d out of range", cpyid); - return err::kparam_out_of_range; - } - - liquid_info_t *cfg = &m_liquid_info[cpyid]; - switch (index) { - GET_CFG(kliquid_info_plld_pm_vcpyid, cfg->plld_pm_vcpyid, val); - GET_CFG(kliquid_info_plld_threshold, cfg->plld_threshold, val); - GET_CFG(kliquid_info_plld_zm_vel, cfg->plld_zm_vel, val); - GET_CFG(kliquid_info_empty_tip_pm_vcpyid, cfg->empty_tip_pm_vcpyid, val); - GET_CFG(kliquid_info_blowout_air_volume, cfg->blowout_air_volume, val); - GET_CFG(kliquid_info_blowout_air_pm_vcpyid, cfg->blowout_air_pm_vcpyid, val); - GET_CFG(kliquid_info_over_aspirated_volume, cfg->over_aspirated_volume, val); - GET_CFG(kliquid_info_over_aspirated_pm_vcpyid, cfg->over_aspirated_pm_vcpyid, val); - GET_CFG(kliquid_info_aspiration_pm_vindex_low, cfg->aspiration_pm_vindex_low, val); - GET_CFG(kliquid_info_aspiration_pm_vindex_high, cfg->aspiration_pm_vindex_high, val); - GET_CFG(kliquid_info_aspiration_volume_break_val, cfg->aspiration_volume_break_val, val); - GET_CFG(kliquid_info_volume_calibration_coefficient_b, cfg->volume_calibration_coefficient_b, val); - GET_CFG(kliquid_info_volume_calibration_coefficient_k, cfg->volume_calibration_coefficient_k, val); - GET_CFG(kliquid_info_settling_time, cfg->settling_time, val); - GET_CFG(kliquid_info_transport_volume, cfg->transport_volume, val); - GET_CFG(kliquid_info_transport_volume_pm_vcpyid, cfg->transport_volume_pm_vcpyid, val); - GET_CFG(kliquid_info_mix_pm_vindex, cfg->mix_pm_vcpyid, val); - GET_CFG(kliquid_info_mark, cfg->mark, val); - default: { - ZLOGE(TAG, "pipette_get_liquid_info index %d out of range", index); - return err::kparam_out_of_range; - } - } - return 0; -} - -int32_t PipetteModule::pipette_read_state(pipette_state_index_t stateindex, int32_t *val) { - static_assert(kpipette_state_max == sizeof(m_state) / 4); - int32_t off = (int32_t)stateindex; - if (off < 0 || off >= (int32_t)kpipette_state_max) { - ZLOGE(TAG, "pipette_read_state index %d out of range", stateindex); - return err::kparam_out_of_range; - } - *val = *(((int32_t *)&m_state) + off); - ZLOGI(TAG, "pipette_read_state index %d val %d", stateindex, *val); - return 0; -} - int32_t PipetteModule::pipette_read_tip_state(int32_t *tipstate) { return m_smtp2.pump_get_tip_state(tipstate); } int32_t PipetteModule::pipette_read_pressure(int32_t *pressure) { return m_smtp2.pump_get_pressure(pressure); } int32_t PipetteModule::pipette_read_capacitance(int32_t *capacitance) { return m_smtp2.pump_get_capacitance(capacitance); } -int32_t PipetteModule::pipette_get_platinfo_max_cpyid(int32_t *cpyid) { - *cpyid = ARRARY_SIZE(m_platinfo) - 1; - return 0; -} -int32_t PipetteModule::pipette_get_zmvcfg_max_cpyid(int32_t *cpyid) { - *cpyid = ARRARY_SIZE(m_zm_vcfg) - 1; - return 0; -} - -int32_t PipetteModule::pipette_get_pmvcfg_max_cpyid(int32_t *cpyid) { - *cpyid = ARRARY_SIZE(m_pm_vcfg) - 1; - return 0; -} - -int32_t PipetteModule::pipette_get_container_info_max_cpyid(int32_t *cpyid) { - *cpyid = ARRARY_SIZE(m_container_info) - 1; - return 0; -} - -int32_t PipetteModule::pipette_get_liquid_info_max_cpyid(int32_t *cpyid) { - *cpyid = ARRARY_SIZE(m_liquid_info) - 1; - return 0; -} - int32_t PipetteModule::module_set_reg(int32_t regindex, int32_t val) { return 0; } int32_t PipetteModule::module_get_reg(int32_t regindex, int32_t *val) { return 0; } @@ -515,107 +130,6 @@ int32_t PipetteModule::module_reset_reg() { ZLOGI(TAG, "module_reset_reg"); return 0; } -zm_vcfg_t *PipetteModule::get_zm_vcfg(int32_t index) { - if (index < 0 || index >= ARRARY_SIZE(m_zm_vcfg)) { - ZLOGE(TAG, "get_zm_vcfg index %d out of range", index); - return &m_zm_vcfg[0]; - } - return &m_zm_vcfg[index]; -} - -pm_vcfg_t *PipetteModule::get_pm_vcfg(int32_t index) { - if (index < 0 || index >= ARRARY_SIZE(m_pm_vcfg)) { - ZLOGE(TAG, "get_pm_vcfg index %d out of range", index); - return &m_pm_vcfg[0]; - } - return &m_pm_vcfg[index]; -} - -container_info_t *PipetteModule::get_container_info(int32_t index) { - if (index < 0 || index >= ARRARY_SIZE(m_container_info)) { - ZLOGE(TAG, "get_container_info index %d out of range", index); - return &m_container_info[0]; - } - return &m_container_info[index]; -} -liquid_info_t *PipetteModule::get_liquid_info(int32_t index) { - if (index < 0 || index >= ARRARY_SIZE(m_liquid_info)) { - ZLOGE(TAG, "get_liquid_info index %d out of range", index); - return &m_liquid_info[0]; - } - return &m_liquid_info[index]; -} -platinfo_t *PipetteModule::get_platinfo(int32_t index) { - if (index < 0 || index >= ARRARY_SIZE(m_platinfo)) { - ZLOGE(TAG, "get_platinfo index %d out of range", index); - return &m_platinfo[0]; - } - return &m_platinfo[index]; -} - -void PipetteModule::get_cfg_smart(int32_t index, zm_vcfg_t *cfg) { // - zm_vcfg_t *cfg0 = get_zm_vcfg(0); - zm_vcfg_t *cfgx = get_zm_vcfg(index); - static_assert(sizeof(zm_vcfg_t) % sizeof(int32_t) == 0, "zm_vcfg_t size is not multiple of int32_t"); - assign_cfg_smart((int32_t *)cfg, (int32_t *)cfgx, (int32_t *)cfg0, sizeof(zm_vcfg_t) / sizeof(int32_t)); - return; -} -void PipetteModule::get_cfg_smart(int32_t index, pm_vcfg_t *cfg) { - /** - * @brief 当配置项的值为负数时,使用默认配置项的值 - */ - pm_vcfg_t *cfg0 = get_pm_vcfg(0); - pm_vcfg_t *cfgx = get_pm_vcfg(index); - static_assert(sizeof(pm_vcfg_t) % sizeof(int32_t) == 0, "pm_vcfg_t size is not multiple of int32_t"); - assign_cfg_smart((int32_t *)cfg, (int32_t *)cfgx, (int32_t *)cfg0, sizeof(pm_vcfg_t) / sizeof(int32_t)); - return; -} - -container_info_t *PipetteModule::get_container_info_smart(int32_t index, container_info_t *val) { - container_info_t *cfg = get_container_info(index); - container_info_t *cfg0 = get_container_info(0); - static_assert(sizeof(container_info_t) % sizeof(int32_t) == 0, "container_info_t size is not multiple of int32_t"); - assign_cfg_smart((int32_t *)val, (int32_t *)cfg, (int32_t *)cfg0, sizeof(container_info_t) / sizeof(int32_t)); - return val; -} -platinfo_t *PipetteModule::get_platinfo_smart(int32_t index, platinfo_t *val) { - platinfo_t *cfg = get_platinfo(index); - platinfo_t *cfg0 = get_platinfo(0); - static_assert(sizeof(platinfo_t) % sizeof(int32_t) == 0, "platinfo_t size is not multiple of int32_t"); - assign_cfg_smart((int32_t *)val, (int32_t *)cfg, (int32_t *)cfg0, sizeof(platinfo_t) / sizeof(int32_t)); - return val; -} - -liquid_info_t *PipetteModule::get_liquid_info_smart(int32_t index, liquid_info_t *val) { - liquid_info_t *cfg = get_liquid_info(index); - liquid_info_t *cfg0 = get_liquid_info(0); - static_assert(sizeof(liquid_info_t) % sizeof(int32_t) == 0, "liquid_info_t size is not multiple of int32_t"); - assign_cfg_smart((int32_t *)val, (int32_t *)cfg, (int32_t *)cfg0, sizeof(liquid_info_t) / sizeof(int32_t)); - return val; -} - -void PipetteModule::assign_cfg_smart(int32_t *dest, int32_t *src, int32_t *defaultcfg, int32_t num) { - for (int i = 0; i < num; i++) { - if (src[i] >= 0) { - dest[i] = src[i]; - } else { - dest[i] = defaultcfg[i]; - } - } -} -void PipetteModule::memset_int32_t(int32_t *table, int32_t val, int32_t num) { - for (int i = 0; i < num; i++) { - table[i] = val; - } -} - -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.001; - if (zmval == 0) zmval = 1; - return zmval; -} /*********************************************************************************************************************** * EXT_API * @@ -714,11 +228,14 @@ int32_t PipetteModule::pipette_pump_init_device(int32_t platinfo_cpyid) { m_state.platinfo_cpyid = platinfo_cpyid; platinfo_t *platform_info = get_platinfo_smart(m_state.platinfo_cpyid, &m_now_platinfo); + clearPipetteGunState(); }); return 0; } int32_t PipetteModule::pipette_pump_take_tip() { thread_start_work(__FUNCTION__, [this]() { + clearPipetteGunState(); + /** * @brief * @@ -765,6 +282,8 @@ int32_t PipetteModule::pipette_pump_take_tip() { } int32_t PipetteModule::pipette_pump_putbak_tip() { thread_start_work(__FUNCTION__, [this]() { + clearPipetteGunState(); + /** * @brief * @@ -790,7 +309,10 @@ int32_t PipetteModule::pipette_pump_putbak_tip() { int32_t PipetteModule::pipette_pump_deposit_tip() { thread_start_work(__FUNCTION__, [this]() { + clearPipetteGunState(); + /** + * * @brief * * -> 移动到tip_deposit_pos @@ -828,32 +350,13 @@ int32_t PipetteModule::pipette_pump_pierce_through(int32_t container_info_index, } int32_t PipetteModule::pipette_pump_aspirate_set_param(aspiration_paramid_t param, int32_t val) { -#define CASE_ITEM(param, item, val) \ - case param: { \ - ZLOGI(TAG, "pipette_pump_aspirate_set_param set %s %d", #item, val); \ - m_aspiration_param.item = val; \ - break; \ - } - - switch (param) { - CASE_ITEM(kaspiration_paramid_volume, volumeX100nl, val); - CASE_ITEM(kaspiration_paramid_container_pos, container_pos, val); - CASE_ITEM(kaspiration_paramid_container_info_index, container_info_index, val); - CASE_ITEM(kaspiration_paramid_liquid_cfg_index, liquid_cfg_index, val); - CASE_ITEM(kaspiration_paramid_aspiration_mode, aspiration_mode, val); - CASE_ITEM(kaspiration_paramid_lld_enable, lld_enable, val); - CASE_ITEM(kaspiration_paramid_lld_type, lld_type, val); - CASE_ITEM(kaspiration_paramid_lld_enable_protect, lld_enable_protect, val); - CASE_ITEM(kaspiration_paramid_mix_llf_enable, mix_llf_enable, val); - CASE_ITEM(kaspiration_paramid_llf_enable, llf_enable, val); - CASE_ITEM(kaspiration_paramid_mix_volume, mix_volume, val); - CASE_ITEM(kaspiration_paramid_mix_times, mix_times, val); - default: { - ZLOGE(TAG, "pipette_pump_aspirate_set_param fail,paramid == %d not support", param); - return err::kparam_out_of_range; - } + if (param < 0 || param >= kaspiration_paramid_max) { + ZLOGE(TAG, "pipette_pump_aspirate_set_param fail,paramid == %d not support", param); + return err::kparam_out_of_range; } -#undef CASE_ITEM + int32_t *settadd = ((int32_t *)&m_aspiration_param) + param; + *settadd = val; + ZLOGI(TAG, "pipette_pump_aspirate_set_param paramid:%s val:%d", aspiration_paramid_to_string(param), val); return 0; } @@ -901,69 +404,16 @@ 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, &m_now_aspirate_liquid_info); + liquid_info_t *liquidinfo = get_liquid_info_smart(acfg->liquid_cfg_index, &m_now_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); - ZLOGI(TAG, "- container_pos :%d", acfg->container_pos); - ZLOGI(TAG, "- container_info_index :%d", acfg->container_info_index); - ZLOGI(TAG, "- liquid_cfg_index :%d", acfg->liquid_cfg_index); - ZLOGI(TAG, "- aspiration_mode :%d", acfg->aspiration_mode); - ZLOGI(TAG, "- lld_enable :%d", acfg->lld_enable); - ZLOGI(TAG, "- lld_type :%d", acfg->lld_type); - ZLOGI(TAG, "- lld_enable_protect :%d", acfg->lld_enable_protect); - ZLOGI(TAG, "- mix_llf_enable :%d", acfg->mix_llf_enable); - ZLOGI(TAG, "- llf_enable :%d", acfg->llf_enable); - ZLOGI(TAG, "- mix_volume :%d", acfg->mix_volume); - ZLOGI(TAG, "- mix_times :%d", acfg->mix_times); - ZLOGI(TAG, "-"); - - ZLOGI(TAG, "-------------------------- platform_info --------------------------"); - ZLOGI(TAG, "- tip_type :%d", platform_info->tip_type); - ZLOGI(TAG, "- tip_length :%d", platform_info->tip_length); - ZLOGI(TAG, "-"); - - ZLOGI(TAG, "-------------------------- liquid_info --------------------------"); - ZLOGI(TAG, "- plld_pm_vindex :%d", liquidinfo->plld_pm_vcpyid); - ZLOGI(TAG, "- plld_threshold :%d", liquidinfo->plld_threshold); - ZLOGI(TAG, "- plld_zm_vel :%d", liquidinfo->plld_zm_vel); - ZLOGI(TAG, "- empty_tip_pm_vindex :%d", liquidinfo->empty_tip_pm_vcpyid); - ZLOGI(TAG, "- blowout_air_volume :%d", liquidinfo->blowout_air_volume); - ZLOGI(TAG, "- blowout_air_pm_vindex :%d", liquidinfo->blowout_air_pm_vcpyid); - ZLOGI(TAG, "- over_aspirated_volume :%d", liquidinfo->over_aspirated_volume); - ZLOGI(TAG, "- over_aspirated_pm_vindex :%d", liquidinfo->over_aspirated_pm_vcpyid); - ZLOGI(TAG, "- aspiration_pm_vindex_low :%d", liquidinfo->aspiration_pm_vindex_low); - ZLOGI(TAG, "- aspiration_pm_vindex_high :%d", liquidinfo->aspiration_pm_vindex_high); - ZLOGI(TAG, "- aspiration_volume_break_val :%d", liquidinfo->aspiration_volume_break_val); - ZLOGI(TAG, "- volume_calibration_coefficient_b :%d", liquidinfo->volume_calibration_coefficient_b); - ZLOGI(TAG, "- volume_calibration_coefficient_k :%d", liquidinfo->volume_calibration_coefficient_k); - ZLOGI(TAG, "- settling_time :%d", liquidinfo->settling_time); - ZLOGI(TAG, "- transport_volume :%d", liquidinfo->transport_volume); - ZLOGI(TAG, "- transport_volume_pm_vindex :%d", liquidinfo->transport_volume_pm_vcpyid); - ZLOGI(TAG, "- mix_pm_vindex :%d", liquidinfo->mix_pm_vcpyid); - ZLOGI(TAG, "- mark :%d", liquidinfo->mark); - ZLOGI(TAG, "-"); - - ZLOGI(TAG, "-------------------------- container_info --------------------------"); - ZLOGI(TAG, "- container_type :%d", container_cfg->container_type); - ZLOGI(TAG, "- container_neck_pos :%d", container_cfg->_container_neck_pos); - ZLOGI(TAG, "- container_depth :%d", container_cfg->container_depth); - ZLOGI(TAG, "- container_round :%d", container_cfg->container_round); - ZLOGI(TAG, "- container_bottom_section_height :%d", container_cfg->container_bottom_section_height); - ZLOGI(TAG, "- immersion_depth :%d", container_cfg->immersion_depth); - 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_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); - ZLOGI(TAG, "-"); - - /*********************************************************************************************************************** - * LLD * - ***********************************************************************************************************************/ + dump("aspiration_param", acfg); + dump("platform_info", platform_info); + dump("container_info", container_cfg); + dump("liquid_info", liquidinfo); + + clearPipetteGunState(); + if (acfg->lld_enable) { _do_lld(acfg->container_pos, platform_info, container_cfg, liquidinfo); // 液面探测 } else { @@ -971,13 +421,19 @@ int32_t PipetteModule::pipette_pump_aspirate() { } if (acfg->volumeX100nl != 0) { - DO_IN_THREAD(m_smtp2.pump_set_tip_type((smtp2::TipSize_t)platform_info->tip_type)); + //! WARNING: 这里强制设置tip类型为200ul + DO_IN_THREAD(m_smtp2.pump_set_tip_type(smtp2::TS200UL)); _do_sapirate(platform_info, container_cfg, liquidinfo, acfg); } else { ZLOGI(TAG, "aspiration volume == 0,skip aspirate", acfg->volumeX100nl); } // z轴移动transform_pos + m_pump_gun_state.is_has_liquid = 1; // 设置移液枪状态为有液体 + m_pump_gun_state.liquid_type_cpyidx = acfg->liquid_cfg_index; + m_pump_gun_state.transport_volume = liquidinfo->transport_volume; // 设置转移过程中多吸入的量 + m_pump_gun_state.blowout_air_volume = liquidinfo->blowout_air_volume; // 设置预先吸入的空气体积 + m_pump_gun_state.liquid_volume = acfg->volumeX100nl; // 设置吸取的液体体积 zm_move_to_zero_quick_block(); }); return 0; @@ -1000,14 +456,14 @@ void PipetteModule::_do_lld(int32_t container_pos, platinfo_t *platform_info, co // 启动lld 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 + DO_IN_THREAD(m_smtp2.pump_set_io1_mode(1)); // lld输入高 + //! WARNING: 这里强制设置tip类型为200ul + DO_IN_THREAD(m_smtp2.pump_set_tip_type(smtp2::TS200UL)); // 设置tip大小 + pump_do_lld(liquidinfo->plld_threshold, 200, liquidinfo->plld_pm_vcpyid); // lld延时200ms,速度为plld_zm_vel // 快速移动到瓶口 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); + zm_move_to_lld_start_search_pos_block(container_pos, container_cfg, kzm_v_default, 0); // lld,zm移动到瓶底 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); @@ -1071,10 +527,10 @@ void PipetteModule::_do_sapirate(platinfo_t *platform_info, container_info_t *co 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); // + zm_move_to_leaving_height_pos_block(-1, m_state.water_level, container_cfg, kzm_v_swap_out, 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); // + zm_move_to_leaving_height_pos_block(-1, m_state.water_level, container_cfg, kzm_v_default, 0); } // 清空tip @@ -1083,15 +539,25 @@ void PipetteModule::_do_sapirate(platinfo_t *platform_info, container_info_t *co // 吸入过量的空气 if (liquidinfo->blowout_air_volume > 0) { - ZLOGI(TAG, "--> aspirate blowout_air_volume volume=%d, pm_vcpyid=%d", liquidinfo->blowout_air_volume); - pump_move_to_x100nl_block(liquidinfo->blowout_air_volume, liquidinfo->blowout_air_pm_vcpyid); + int32_t blowout_air_volume = liquidinfo->blowout_air_volume; + int32_t blowout_air_max_vol0 = 2500 - calibrate_liquid_volume(liquidinfo, acfg->volumeX100nl) - liquidinfo->transport_volume - 100 /*100为了单位换算提供余量 */; + int32_t blowout_air_max_vol1 = 2500 - acfg->mix_volume - 100 /*100为了单位换算提供余量 */; + if (blowout_air_volume > blowout_air_max_vol0) { + blowout_air_volume = blowout_air_max_vol0; + } + if (blowout_air_volume > blowout_air_max_vol1) { + blowout_air_volume = blowout_air_max_vol1; + } + + ZLOGI(TAG, "--> aspirate blowout_air_volume volume=%d, pm_vcpyid=%d", blowout_air_volume); + pump_move_to_x100nl_block(blowout_air_volume, liquidinfo->blowout_air_pm_vcpyid); } else { ZLOGI(TAG, "--> aspirate blowout_air_volume volume=0,skip"); } // Z轴移动到液面之下 ZLOGI(TAG, "--> move below the liquid surface"); - zm_move_to_block(m_state.water_level + container_cfg->immersion_depth, kzm_v_swap, 0); + zm_move_to_immersion_pos_block(-1, m_state.water_level, container_cfg, kzm_v_swap_in, 0); // 移动到液面下 // 吸入润湿TIP的溶液 if (liquidinfo->over_aspirated_volume > 0) { @@ -1105,14 +571,14 @@ void PipetteModule::_do_sapirate(platinfo_t *platform_info, container_info_t *co ZLOGI(TAG, "--> aspirate mix_volume volume=%d, pm_vcpyid=%d", acfg->mix_volume, liquidinfo->mix_pm_vcpyid); int32_t mix_start_pos = zm_get_now_pos(); for (size_t i = 0; i < acfg->mix_times; i++) { + // 移动到瓶底 if (acfg->mix_llf_enable > 0) { - zm_move_to(acfg->container_pos + container_cfg->container_depth, // 瓶底 - kzm_v_llf, // 基础速度配置 - compute_zm_llf_vel(liquidinfo->mix_pm_vcpyid, container_cfg)); // 计算llf速度 + zm_move_to(acfg->container_pos + container_cfg->container_depth, kzm_v_llf, compute_zm_llf_vel(liquidinfo->mix_pm_vcpyid, container_cfg)); } pump_move_by_x100nl_block(acfg->mix_volume, liquidinfo->mix_pm_vcpyid); if (acfg->mix_llf_enable > 0) zm_stop(); + // 移动到初始位置 if (acfg->mix_llf_enable > 0) { zm_move_to(mix_start_pos, kzm_v_llf, compute_zm_llf_vel(liquidinfo->mix_pm_vcpyid, container_cfg)); } @@ -1131,15 +597,10 @@ void PipetteModule::_do_sapirate(platinfo_t *platform_info, container_info_t *co aspiration_pm_index = liquidinfo->aspiration_pm_vindex_high; } - int32_t x100nl = acfg->volumeX100nl * liquidinfo->volume_calibration_coefficient_k * 0.001 + // - liquidinfo->volume_calibration_coefficient_b * 0.001; + int32_t x100nl = calibrate_liquid_volume(liquidinfo, acfg->volumeX100nl); if (acfg->llf_enable > 0) { - zm_move_to( // - acfg->container_pos + container_cfg->container_depth, // 瓶底 - kzm_v_llf, // - compute_zm_llf_vel(aspiration_pm_index, container_cfg) // - ); + zm_move_to(acfg->container_pos + container_cfg->container_depth, kzm_v_llf, compute_zm_llf_vel(aspiration_pm_index, container_cfg)); } pump_move_by_x100nl_block(x100nl, aspiration_pm_index); if (acfg->llf_enable > 0) zm_stop(); @@ -1151,7 +612,7 @@ void PipetteModule::_do_sapirate(platinfo_t *platform_info, container_info_t *co // 离开液面 ZLOGI(TAG, "--> leave liquid surface"); - zm_move_to_block(m_state.water_level - container_cfg->leaving_height, kzm_v_swap, 0); // + zm_move_to_leaving_height_pos_block(-1, m_state.water_level, container_cfg, kzm_v_swap_out, 0); // 移动到液面之上 // 吸入过量的空气 if (liquidinfo->transport_volume > 0) { @@ -1159,6 +620,16 @@ void PipetteModule::_do_sapirate(platinfo_t *platform_info, container_info_t *co pump_move_by_x100nl_block(liquidinfo->transport_volume, liquidinfo->transport_volume_pm_vcpyid); } } +int32_t PipetteModule::pipette_pump_distribu_all_set_param(distribu_all_paramid_t param, int32_t val) { + if (param < 0 || param >= kdistribu_all_paramid_max) { + ZLOGE(TAG, "pipette_pump_distribu_all_set_param fail,paramid == %d not support", param); + return err::kparam_out_of_range; + } + int32_t *settadd = ((int32_t *)&m_distribu_all_param) + param; + *settadd = val; + ZLOGI(TAG, "pipette_pump_distribu_all_set_param paramid %s val %d", distribu_all_paramid_to_string(param), val); + return 0; +} int32_t PipetteModule::pipette_pump_distribu_all() { thread_start_work(__FUNCTION__, [this]() { @@ -1167,54 +638,118 @@ int32_t PipetteModule::pipette_pump_distribu_all() { throw zapp_exception(err::kpipette_error_TipDrop); } + if (m_pump_gun_state.is_has_liquid == 0) { + ZLOGE(TAG, "pipette_pump_distribu_all fail, is_has_liquid == 0"); + throw zapp_exception(err::kpipette_no_liquid_in_it); + } + /** + * @brief 分液 + * + * + * 如果是jet模式 + * 1. 移动到jet位置 + * 2. 快速喷射出所有液体(使用jet速度) + * 3. 移动到液面之下,混匀 + * + * 如果是液面下分配模式 + * 1. 移动到swap位置 + * 2. 清空transport volume + * 3. 缓慢移动到液面之下 + * 4. 分液 + * 5. 移动到swap位置,快速清空tip,使用(emptyTip速度) + * 6. 缓慢移动到液面之下 + * 7. 吸吐混匀 + * + */ + auto *dcfg = &m_distribu_all_param; + + check_liquid_info_cpyid(dcfg->dest_liquid_cfg_index); + check_liquid_info_cpyid(m_pump_gun_state.liquid_type_cpyidx); + check_container_info_cpyid(dcfg->dest_container_cpyid); + check_platinfo_cpyid(m_state.platinfo_cpyid); + + platinfo_t *platform_info = get_platinfo_smart(m_state.platinfo_cpyid, &m_now_platinfo); + liquid_info_t *liquidinfo = get_liquid_info_smart(dcfg->dest_liquid_cfg_index, &m_now_liquid_info); + container_info_t *container_cfg = get_container_info_smart(dcfg->dest_container_cpyid, &m_now_container_info); + liquid_info_t *liquidInGun_info = get_liquid_info_smart(m_pump_gun_state.liquid_type_cpyidx, &m_now_liquid_in_gun_info); + + dump("distribu_all_param", dcfg); + dump("platform_info", platform_info); + dump("container_info", container_cfg); + dump("liquid_info", liquidinfo); + dump("liquid_in_gun_info", liquidInGun_info); + + int32_t container_pos = dcfg->container_pos; + + if (dcfg->distribu_type == 0) { + // jet模式 + ZLOGI(TAG, "-->jet mode distribu"); + ZLOGI(TAG, "-->move to jet position"); + zm_move_to_jet_pos_block(container_pos, -1, container_cfg, kzm_v_default, 0); // 移动到jet位置 + pump_move_to_x100nl_block(0, liquidInGun_info->jet_pm_vcpyid); // 快速喷射出所有液体(使用jet速度) + } else { + ZLOGI(TAG, "-->under liquid distribu"); + // 移动到swap位置 + ZLOGI(TAG, "-->move to swap position"); + zm_move_to_leaving_height_pos_block(container_pos, -1, container_cfg, kzm_v_default, 0); // 移动到swap位置 + // 清空transport volume + if (liquidInGun_info->transport_volume != 0) { + ZLOGI(TAG, "-->clean transport volume"); + pump_move_to_x100nl_block(liquidInGun_info->transport_volume, liquidInGun_info->transport_volume_pm_vcpyid); // 清空transport volume + } else { + ZLOGI(TAG, "-->clean transport volume,skip"); + } + // 缓慢移动到液面之下 + ZLOGI(TAG, "-->move to below the liquid surface"); + zm_move_to_immersion_pos_block(container_pos, -1, container_cfg, kzm_v_swap_in, 0); // 缓慢移动到液面之下 + // 分液 + ZLOGI(TAG, "-->distribu liquid"); + int32_t distribu_volume = calibrate_liquid_volume(liquidInGun_info, m_pump_gun_state.liquid_volume); + pump_move_by_x100nl_block(distribu_volume, liquidInGun_info->distribu_pm_vpyid); // 分液 - }); - - return 0; -} + // 移动到swap位置,快速清空tip,使用(emptyTip速度) + ZLOGI(TAG, "-->move to swap position and clean tip"); + zm_move_to_leaving_height_pos_block(container_pos, -1, container_cfg, kzm_v_swap_out, 0); // 移动到swap位置 -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); + pump_move_to_x100nl_block(0, liquidInGun_info->empty_tip_pm_vcpyid); // 快速清空tip,使用(emptyTip速度) } - // 移液枪部分参数初始化 - 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输入高 + // + // 如果需要混匀,则移动到液面之下 + // + if (dcfg->mix_volume > 0) { + ZLOGI(TAG, "-->move to below the liquid surface for mixing"); + zm_move_to_immersion_pos_block(container_pos, -1, container_cfg, kzm_v_swap_in, 0); // 缓慢移动到液面之下 - 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输入高 + ZLOGI(TAG, "-->mix"); + for (size_t i = 0; i < dcfg->mix_times; i++) { + pump_move_by_x100nl_block(dcfg->mix_volume, liquidinfo->mix_pm_vcpyid); // 混匀 + pump_move_by_x100nl_block(-dcfg->mix_volume, liquidinfo->mix_pm_vcpyid); // 吸出混匀液体 + } - 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); + zm_move_to_leaving_height_pos_block(container_pos, -1, container_cfg, kzm_v_swap_out, 0); // 离开液面 + } else { + ZLOGI(TAG, "-->skip mixing"); + } - _do_lld(container_pos, platform_info, container_cfg, liquidinfo); + // 吸入10ul过量的空气,防挂液 + pump_move_by_x100nl_block(100, liquidInGun_info->transport_volume_pm_vcpyid); + // + // 如果需要归零,则移动到transform_pos + // + if (dcfg->zm_auto_move_to_zero) { + ZLOGI(TAG, "-->move to zero pos"); + zm_move_to_zero_quick_block(); + } else { + ZLOGI(TAG, "-->skip move to zero pos"); + } }); + return 0; } - /*********************************************************************************************************************** * EXT_API_UTILS * ***********************************************************************************************************************/ @@ -1238,334 +773,6 @@ int32_t PipetteModule::pipette_zmotor_read_enc_pos(int32_t *pos) { return 0; } -/*********************************************************************************************************************** - * ZM_UTILS * - ***********************************************************************************************************************/ - -void PipetteModule::do_zm_move_0p() { - bool is_trigger = false; - if (!zm0p_is_trigger()) { - ZLOGI(TAG, "move to zero"); - zm_move_to_end(-1, kzm_v_move_to_zero); - zm_waitfor_zm0p_trigger_and_stop_motor(&is_trigger); - if (!is_trigger) throw zapp_exception(err::kstep_motor_not_found_point_edge); - } - - // leave from zero - if (zm0p_is_trigger()) { - ZLOGI(TAG, "leave from zero"); - zm_move_by(500 /*50mm */, kzm_v_look_zero_edge, 0); - zm_waitfor_zm0p_not_trigger_and_stop_motor(&is_trigger); - if (!is_trigger) throw zapp_exception(err::kstep_motor_not_found_point_edge); - } - - if (!zm0p_is_trigger()) { - ZLOGI(TAG, "move to zero edge again"); - zm_move_by(-100 /*10mm */, kzm_v_look_zero_edge, 0); - zm_waitfor_zm0p_trigger_and_stop_motor(&is_trigger); - if (!is_trigger) throw zapp_exception(err::kstep_motor_not_found_point_edge); - } - zm_waitfor_stop(); -} - -int32_t PipetteModule::zm_get_now_pos() { - if (zmbcfg.enable_enc == 0) { - return m_zm->getXACTUAL(); - } - return m_zm->read_enc_val(); -} -void PipetteModule::zm_set_now_pos(int32_t x) { - m_zm->setXACTUAL(x); - m_zm->set_enc_val(x); -} -void PipetteModule::zm_move_to_zero_quick_block() { - // 期望偏差 - int32_t expectation_dpos = -zmbcfg.io_trigger_append_distance + 0 + zmbcfg.dzero - zm_get_now_pos(); - int32_t startpos = zm_get_now_pos(); - if (!zm0p_is_trigger()) { - // 快速移动到零点 - // moveTo(0 + zmbcfg.dzero, zmbcfg.default_velocity); - zm_move_to(0 + zmbcfg.dzero, kzm_v_default, 0); - zm_waitfor_zm0p_trigger_and_stop_motor(NULL); - } else { - // 快速移动到零点 - zm_move_to(0 + zmbcfg.dzero, kzm_v_default, 0); - zm_waitfor_zm0p_not_trigger_and_stop_motor(NULL); - } - // 移动到零点 - do_zm_move_0p(); - - // 校验偏差 - int32_t dpos = zm_get_now_pos() - startpos; - // 设置零点 - zm_set_now_pos(0 + zmbcfg.dzero - zmbcfg.io_trigger_append_distance); - m_state.zm_has_move_zero = 1; - - if (zmbcfg.pos_devi_tolerance != 0 && (abs(expectation_dpos - dpos) > zmbcfg.pos_devi_tolerance)) { - throw zapp_exception(err::kstep_motor_lost_step); - } -} - -void PipetteModule::zm_move_to(int32_t x, int32_t vbaseindex, int32_t vel) { - /** - * @brief 以电机的参考位置为基准,向下为正向,向上为负向 - */ - ZLOGI(TAG, "zm_move_to %d", x); - if (zmbcfg.enable_enc != 0) { - m_zm->setXACTUAL(m_zm->read_enc_val()); - } - - zm_apply_vcfg(vbaseindex, vel); - m_zm->moveTo(x); -} -void PipetteModule::zm_move_to_block(int32_t x, int32_t vbaseindex, int32_t vel) { - zm_move_to(x, vbaseindex, vel); - zm_waitfor_stop(); -} -void PipetteModule::zm_move_by(int32_t dx, int32_t vindex, int32_t vel) { - ZLOGI(TAG, "zm_move_by %d %d", dx); - if (zmbcfg.enable_enc != 0) { - m_zm->setXACTUAL(m_zm->read_enc_val()); - } - zm_apply_vcfg(vindex, vel); - m_zm->moveBy(dx); -} -void PipetteModule::zm_move_by_block(int32_t dx, int32_t vindex, int32_t vel) { - zm_move_by(dx, vindex, vel); - zm_waitfor_stop(); -} - -void PipetteModule::zm_move_to_end(int32_t direction, int32_t vindex) { - if (zmbcfg.enable_enc != 0) { - m_zm->setXACTUAL(m_zm->read_enc_val()); - } - zm_apply_vcfg(vindex, 0); - m_zm->moveToEnd(direction); -} - -void PipetteModule::zm_update_dzero(int32_t dzero) { - int32_t nowabs = zm_get_now_pos() - zmbcfg.dzero; - zmbcfg.dzero = dzero; - zm_set_now_pos(nowabs + zmbcfg.dzero); -} -bool PipetteModule::zm0p_is_trigger() { return m_zm0p->getState(); } - -void PipetteModule::zm_apply_vcfg(int32_t vbasecfgindex, int32_t vel) { - ZLOGI(TAG, "zm_apply_vcfg %s", get_zm_vcpyid_name((zm_vcpyid_t)vbasecfgindex)); - /** - * @brief 当配置项的值为负数时,使用默认配置项的值 - */ - - 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); - - 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() { - m_zm->enable(false); - m_zm->setMRES((mres_type_t)zmbcfg.mres); - m_zm->setIHOLD_IRUN(zmbcfg.ihold, zmbcfg.irun, zmbcfg.iholddelay); - m_zm->setScale(zmbcfg.one_circle_pulse); - m_zm->setScaleDenominator(zmbcfg.one_circle_pulse_denominator); - m_zm->setMotorShaft(zmbcfg.shaft); - m_zm->setGlobalScale(zmbcfg.iglobalscaler); - 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); - } -} - -void PipetteModule::zm_waitfor_zm0p_trigger_and_stop_motor(bool *triggerEdge) { - if (triggerEdge) *triggerEdge = true; - while (!zm0p_is_trigger()) { - if (m_zm->isStoped()) { - ZLOGI(TAG, "motor stop first....."); - if (triggerEdge) *triggerEdge = false; - break; - } - thread_delay(1); - } - - // 停止电机 - m_zm->stop(); - // 等待电机停止 - while (!m_zm->isStoped()) { - thread_delay(10); - } -} - -void PipetteModule::zm_waitfor_zm0p_not_trigger_and_stop_motor(bool *triggerEdge) { - // 等待触发 - if (triggerEdge) *triggerEdge = true; - while (zm0p_is_trigger()) { - if (m_zm->isStoped()) { - ZLOGI(TAG, "motor stop first....."); - if (triggerEdge) *triggerEdge = false; - } - thread_delay(1); - } - - // 停止电机 - m_zm->stop(); - // 等待电机停止 - while (!m_zm->isStoped()) thread_delay(2); -} -void PipetteModule::zm_stop() { - // 停止电机 - m_zm->stop(); - // 等待电机停止 - while (!m_zm->isStoped()) thread_delay(2); -} - -void PipetteModule::pump_waitfor_stop() { - while (true) { - int32_t isbusy = 0; - DO_IN_THREAD(m_smtp2.pump_get_state(&isbusy)); - if (isbusy == 0) break; - thread_delay(10); - } -} - -void PipetteModule::pump_waitfor_lld_is_ready(int32_t *zpos) { - m_smtp2.pump_set_io1_mode(0); // lld输入高 - while (true) { - int32_t isbusy = 0; - if (m_piette_gun_io1.getState()) { - } - } -} - -void PipetteModule::pump_get_vcfg(int32_t vcfgcpyid, smtp2::VelCfg *cfg) { - pm_vcfg_t cfg2 = {0}; - get_cfg_smart(vcfgcpyid, &cfg2); - cfg->acc = cfg2.acc; - cfg->dec = cfg2.dec; - cfg->vstart = cfg2.vstart; - cfg->vstop = cfg2.vstop; - cfg->vmax = cfg2.vmax; -} - -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(vcfgcpyid, &vcfg); - - DO_IN_THREAD(m_smtp2.pump_set_vcfg(&vcfg)); - m_state.pm_now_vcfg_index = vcfgcpyid; -} -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(vcfgcpyid, &vcfg); - m_state.pm_now_vcfg_index = vcfgcpyid; // 更新当前配置索引 - DO_IN_THREAD(m_smtp2.pump_move_to_nl(&vcfg, x100nl * 100)); -} -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(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(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(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) { - // - // *val = m_state.load_val_ul; - // *val = pum - // pump_read_pos_nl(val); - DO_IN_THREAD(m_smtp2.pump_get_nl(val)); -} -int32_t PipetteModule::pump_read_pos_nl() { - int32_t val = 0; - DO_IN_THREAD(m_smtp2.pump_get_nl(&val)); - return val; -} -int32_t PipetteModule::pump_read_capactitance() { - int32_t val = 0; - DO_IN_THREAD(m_smtp2.pump_get_capacitance(&val)); - return val; -} -int32_t PipetteModule::pump_read_tip_state() { - int32_t val = 0; - DO_IN_THREAD(m_smtp2.pump_get_tip_state(&val)); - return val; -} - -void PipetteModule::zm_waitfor_stop() { - while (!m_zm->isStoped()) thread_delay(1); -} - -void PipetteModule::push_pressure_sample_data(int32_t motor_pos, int32_t pressure_val) { - if (capturedata_num >= PIPETTEMODULE_SAMPLE_BUF_SIZE) { - ZLOGW(TAG, "capturedata_buf overflow"); - return; - } - - ZLOGI(TAG, "sample %2d mpos:%2d pressure_val:%4d", capturedata_num, motor_pos, pressure_val); - capturedata_buf[capturedata_num].motor_pos = motor_pos; - capturedata_buf[capturedata_num].pressure_val = pressure_val; - capturedata_num++; -} - int32_t PipetteModule::pipette_get_sensor_sample_data(int32_t index, int32_t *motor_pos, int32_t *pval) { if (index > capturedata_num) return err::kparam_out_of_range; *motor_pos = capturedata_buf[index].motor_pos; @@ -1751,174 +958,3 @@ void PipetteModule::thread_start_work(const char *fnname, function fn) { ZLOGI(TAG, "<- end work"); }); } - -void PipetteModule::check_platinfo_cpyid(int32_t cpyid) { - if (cpyid < 0 || cpyid >= ARRARY_SIZE(m_platinfo)) { - ZLOGE(TAG, "pipette_get_container_info cpyid %d out of range", cpyid); - throw zapp_exception(err::kparam_out_of_range); - } -} -void PipetteModule::check_zmvcfg_cpyid(int32_t cpyid) { - if (cpyid < 0 || cpyid >= ARRARY_SIZE(m_zm_vcfg)) { - ZLOGE(TAG, "pipette_get_zmvcfg cpyid %d out of range", cpyid); - throw zapp_exception(err::kparam_out_of_range); - } -} -void PipetteModule::check_pmvcfg_cpyid(int32_t cpyid) { - if (cpyid < 0 || cpyid >= ARRARY_SIZE(m_pm_vcfg)) { - ZLOGE(TAG, "pipette_get_pmvcfg cpyid %d out of range", cpyid); - throw zapp_exception(err::kparam_out_of_range); - } -} -void PipetteModule::check_container_info_cpyid(int32_t cpyid) { - if (cpyid < 0 || cpyid >= ARRARY_SIZE(m_container_info)) { - ZLOGE(TAG, "pipette_get_container_info cpyid %d out of range", cpyid); - throw zapp_exception(err::kparam_out_of_range); - } -} -void PipetteModule::check_liquid_info_cpyid(int32_t cpyid) { - if (cpyid < 0 || cpyid >= ARRARY_SIZE(m_liquid_info)) { - ZLOGE(TAG, "pipette_get_liquid_info cpyid %d out of range", cpyid); - throw zapp_exception(err::kparam_out_of_range); - } -} -void PipetteModule::check_zmotor_is_enable() { - if (!m_zm->isMotorIcInitOk()) { - ZLOGE(TAG, "motor is not init"); - throw zapp_exception(err::kstep_motor_subic_init_fail); - } - if (!m_zm->isOnline()) { - ZLOGE(TAG, "motor is offline"); - throw zapp_exception(err::kstep_motor_subic_offline); - } - if (!m_state.enable) { - ZLOGE(TAG, "motor is not enable"); - throw zapp_exception(err::kstep_motor_not_enable); - } -} - -void PipetteModule::check_pipette_pump_aspirate_params() { - aspiration_param_t *acfg = &m_aspiration_param; - - if (acfg->volumeX100nl < 0) { - ZLOGE(TAG, "pipette_pump_aspirate_set_param x100nl %d out of range", acfg->volumeX100nl); - throw zapp_exception(err::kparam_out_of_range); - } - check_platinfo_cpyid(m_state.platinfo_cpyid); - check_container_info_cpyid(acfg->container_info_index); - check_liquid_info_cpyid(acfg->liquid_cfg_index); -} - -void PipetteModule::parameter_init() { - /*********************************************************************************************************************** - * zmbcfg * - ***********************************************************************************************************************/ - zmbcfg.shaft = 0; // Z轴电机运动方向调整 - zmbcfg.one_circle_pulse = 80; // 电子齿轮比-分子 - zmbcfg.one_circle_pulse_denominator = 1; // 电子齿轮比-分母 - zmbcfg.ihold = 7; // - zmbcfg.irun = 7; // - zmbcfg.iholddelay = 10; // - zmbcfg.iglobalscaler = 0; // - zmbcfg.min_d = 0; // - zmbcfg.max_d = 0; // - zmbcfg.tzerowait = 0; // - zmbcfg.enc_resolution = 0; // - zmbcfg.enable_enc = 0; // - zmbcfg.dzero = 92; // - zmbcfg.io_trigger_append_distance = 20; // - zmbcfg.pos_devi_tolerance = 20; // - zmbcfg.mres = 0; // - zmbcfg.mark = 9973; // - /*********************************************************************************************************************** - * pm_base_cfg * - ***********************************************************************************************************************/ - pm_base_cfg.pad = 0; - pm_base_cfg.mark = 9973; - - /*********************************************************************************************************************** - * m_platinfo * - ***********************************************************************************************************************/ - memset_int32_t((int32_t *)&m_platinfo[0], -1, sizeof(m_platinfo) / 4); - memset_int32_t((int32_t *)&m_platinfo[0], 0, sizeof(m_platinfo[0]) / 4); - m_platinfo[0].tip_type = smtp2::TS200UL; - m_platinfo[0].tip_length = 500; // 50mm - m_platinfo[0].mark = 9973; // - - /*********************************************************************************************************************** - * m_zm_vcfg * - ***********************************************************************************************************************/ - memset_int32_t((int32_t *)&m_zm_vcfg[0], -1, sizeof(m_zm_vcfg) / 4); - memset_int32_t((int32_t *)&m_zm_vcfg[0], 0, sizeof(m_zm_vcfg[0]) / 4); - m_zm_vcfg[kzm_v_default].vstart = 100; - m_zm_vcfg[kzm_v_default].a1 = 50; - m_zm_vcfg[kzm_v_default].amax = 100; - m_zm_vcfg[kzm_v_default].v1 = 100; - m_zm_vcfg[kzm_v_default].dmax = 100; - m_zm_vcfg[kzm_v_default].d1 = 200; - m_zm_vcfg[kzm_v_default].vstop = 400; - m_zm_vcfg[kzm_v_default].vmax = 1200; - m_zm_vcfg[kzm_v_default].mark = 9973; - - m_zm_vcfg[kzm_v_move_to_zero].vmax = 600; - m_zm_vcfg[kzm_v_look_zero_edge].vmax = 100; - m_zm_vcfg[kzm_v_lld].vmax = 600; - m_zm_vcfg[kzm_v_swap].vmax = 300; - m_zm_vcfg[kzm_v_llf].vmax = 500; - - /*********************************************************************************************************************** - * m_pm_vcfg * - ***********************************************************************************************************************/ - - memset_int32_t((int32_t *)&m_pm_vcfg[0], -1, sizeof(m_pm_vcfg) / 4); - memset_int32_t((int32_t *)&m_pm_vcfg[0], 0, sizeof(m_pm_vcfg[0]) / 4); - m_pm_vcfg[kpm_v_default].acc = 1; - m_pm_vcfg[kpm_v_default].dec = 1; - m_pm_vcfg[kpm_v_default].vstart = 100; - m_pm_vcfg[kpm_v_default].vstop = 50; - m_pm_vcfg[kpm_v_default].mark = 9973; - - // - m_pm_vcfg[kpm_v_default].vmax = 2500; - m_pm_vcfg[kpm_v_slow_lv1].vmax = 5; - m_pm_vcfg[kpm_v_slow_lv2].vmax = 10; - m_pm_vcfg[kpm_v_slow_lv3].vmax = 50; - m_pm_vcfg[kpm_v_mid].vmax = 1000; - m_pm_vcfg[kpm_v_quick].vmax = 2000; - m_pm_vcfg[kpm_v_max].vmax = 2500; - m_pm_vcfg[kpm_v_lld].vmax = 100; - - /*********************************************************************************************************************** - * m_container_info * - ***********************************************************************************************************************/ - memset_int32_t((int32_t *)&m_container_info[0], -1, sizeof(m_container_info) / 4); - memset_int32_t((int32_t *)&m_container_info[0], 0, sizeof(m_container_info[0]) / 4); - m_container_info[0].leaving_height = 150; - m_container_info[0].mark = 9973; - - /*********************************************************************************************************************** - * m_liquid_info * - ***********************************************************************************************************************/ - - memset_int32_t((int32_t *)&m_liquid_info[0], -1, sizeof(m_liquid_info) / 4); - memset_int32_t((int32_t *)&m_liquid_info[0], 0, sizeof(m_liquid_info[0]) / 4); - - m_liquid_info[0].plld_pm_vcpyid = kpm_v_lld; - m_liquid_info[0].plld_threshold = 30; - m_liquid_info[0].plld_zm_vel = 50; - m_liquid_info[0].empty_tip_pm_vcpyid = kpm_v_max; - m_liquid_info[0].blowout_air_volume = 0; - m_liquid_info[0].blowout_air_pm_vcpyid = kpm_v_quick; - m_liquid_info[0].over_aspirated_volume = 100; // 100(x100nl) == 10ul - m_liquid_info[0].over_aspirated_pm_vcpyid = kpm_v_slow_lv2; - m_liquid_info[0].aspiration_pm_vindex_low = kpm_v_slow_lv1; - m_liquid_info[0].aspiration_pm_vindex_high = kpm_v_slow_lv3; - m_liquid_info[0].aspiration_volume_break_val = 500; // 500(x100nl) == 50ul - m_liquid_info[0].volume_calibration_coefficient_b = 1.0f; - m_liquid_info[0].volume_calibration_coefficient_k = 1.0f; - m_liquid_info[0].settling_time = 1000; // ms - m_liquid_info[0].transport_volume = 50; // 50(x100nl) == 5ul - m_liquid_info[0].transport_volume_pm_vcpyid = kpm_v_slow_lv2; - m_liquid_info[0].mix_pm_vcpyid = kpm_v_max; - m_liquid_info[0].mark = 9973; -} diff --git a/sdk/components/pipette_module/pipette_ctrl_module.hpp b/sdk/components/pipette_module/pipette_ctrl_module.hpp index 51b9b1e..d2be5a5 100644 --- a/sdk/components/pipette_module/pipette_ctrl_module.hpp +++ b/sdk/components/pipette_module/pipette_ctrl_module.hpp @@ -72,10 +72,13 @@ class PipetteModule : public ZIModule { /*********************************************************************************************************************** * state * ***********************************************************************************************************************/ - pipette_state_t m_state = {0}; + pipette_state_t m_state = {0}; + pump_gun_state_t m_pump_gun_state = {0}; + platinfo_t m_now_platinfo; container_info_t m_now_container_info; - liquid_info_t m_now_aspirate_liquid_info; + liquid_info_t m_now_liquid_info; // 当前液体信息 + liquid_info_t m_now_liquid_in_gun_info; // 当前枪内液体信息 /*********************************************************************************************************************** * Config * @@ -92,8 +95,8 @@ class PipetteModule : public ZIModule { container_info_t m_container_info[CONTAINER_INFO_CPY_NUM]; liquid_info_t m_liquid_info[LIQUID_INFO_CPY_NUM]; - aspiration_param_t m_aspiration_param; - + aspiration_param_t m_aspiration_param; + distribu_all_param_t m_distribu_all_param; /*********************************************************************************************************************** * datacache * ***********************************************************************************************************************/ @@ -115,6 +118,7 @@ class PipetteModule : public ZIModule { virtual int32_t module_reset_reg() override; virtual int32_t module_stop() override; + public: /*********************************************************************************************************************** * Config * ***********************************************************************************************************************/ @@ -145,64 +149,26 @@ class PipetteModule : public ZIModule { virtual int32_t pipette_get_liquid_info(int32_t cpyid, liquid_info_index_t index, int32_t *val); virtual int32_t pipette_get_liquid_info_max_cpyid(int32_t *cpyid); - /*********************************************************************************************************************** - * Z轴控制 * - ***********************************************************************************************************************/ - virtual int32_t pipette_zmotor_enable(int32_t enable); - virtual int32_t pipette_zmotor_move_zero(); - virtual int32_t pipette_zmotor_move_to_zero_point_quick(); - virtual int32_t pipette_zmotor_measure_distance(); - virtual int32_t pipette_zmotor_read_measure_distance_result(int32_t *result0); - virtual int32_t pipette_zmotor_move_by(int32_t distance); - virtual int32_t pipette_zmotor_move_to(int32_t position); - - virtual int32_t pipette_zmotor_read_zero_point_state(int32_t *state); - virtual int32_t pipette_zmotor_read_dev_status_cache(int32_t *devStatus); - virtual int32_t pipette_zmotor_read_pos(int32_t *pos); - virtual int32_t pipette_zmotor_read_enc_pos(int32_t *pos); - - /*********************************************************************************************************************** - * PUMP * - ***********************************************************************************************************************/ - virtual int32_t pipette_pump_init_device(int32_t platinfo_cpyid); - virtual int32_t pipette_pump_take_tip(); - virtual int32_t pipette_pump_putbak_tip(); - virtual int32_t pipette_pump_deposit_tip(); - virtual int32_t pipette_pump_pierce_through(int32_t container_info_index, int32_t container_pos); - - virtual int32_t pipette_pump_aspirate_set_param(aspiration_paramid_t param, int32_t val); - virtual int32_t pipette_pump_aspirate(); - 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_all(); + private: + zm_vcfg_t *get_zm_vcfg(int32_t index); + pm_vcfg_t *get_pm_vcfg(int32_t index); + container_info_t *get_container_info(int32_t index); + liquid_info_t *get_liquid_info(int32_t index); + platinfo_t *get_platinfo(int32_t index); - 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); - virtual int32_t pipette_read_state(pipette_state_index_t stateindex, int32_t *val); - virtual int32_t pipette_read_tip_state(int32_t *tipstate); - virtual int32_t pipette_read_pressure(int32_t *pressure); - virtual int32_t pipette_read_capacitance(int32_t *capacitance); + void get_cfg_smart(int32_t index, zm_vcfg_t *cfg); + void get_cfg_smart(int32_t index, pm_vcfg_t *cfg); + container_info_t *get_container_info_smart(int32_t index, container_info_t *val); + liquid_info_t *get_liquid_info_smart(int32_t index, liquid_info_t *val); + platinfo_t *get_platinfo_smart(int32_t index, platinfo_t *val); - // 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); + void parameter_init(); private: /*********************************************************************************************************************** - * MOTOR * - ***********************************************************************************************************************/ - private: - /*********************************************************************************************************************** - * Scirpt * + * zm_ctrl * ***********************************************************************************************************************/ - void do_zm_move_0p(); - void do_pipette_zmotor_move_to_zero_point_quick(); - - /*********************************************************************************************************************** - * zmotor_simple_scirpt * - ***********************************************************************************************************************/ void zm_move_to(int32_t x, int32_t vbaseindex, int32_t vel); void zm_move_to_block(int32_t x, int32_t vbaseindex, int32_t vel); @@ -213,6 +179,16 @@ class PipetteModule : public ZIModule { void zm_update_dzero(int32_t dzero); void zm_move_to_zero_quick_block(); + void zm_move_to_container_bottom_block(int32_t container_pos, container_info_t *containInfo, int32_t vbcpyid, int32_t vel); + void zm_move_to_container_bottom_section_begin_block(int32_t container_pos, container_info_t *containInfo, int32_t vbcpyid, int32_t vel); + void zm_move_to_lld_start_search_pos_block(int32_t container_pos, container_info_t *containInfo, int32_t vbcpyid, int32_t vel); + void zm_move_to_pierce_pos_block(int32_t container_pos, container_info_t *containInfo, int32_t vbcpyid, int32_t vel); + + void zm_move_to_fix_water_level_pos_block(int32_t container_pos, container_info_t *containInfo, int32_t vbcpyid, int32_t vel); + void zm_move_to_immersion_pos_block(int32_t container_pos, int32_t waterlevel, container_info_t *containInfo, int32_t vbcpyid, int32_t vel); + void zm_move_to_leaving_height_pos_block(int32_t container_pos, int32_t waterlevel, container_info_t *containInfo, int32_t vbcpyid, int32_t vel); + void zm_move_to_jet_pos_block(int32_t container_pos, int32_t waterlevel, container_info_t *containInfo, int32_t vbcpyid, int32_t vel); + int32_t zm_get_now_pos(); void zm_set_now_pos(int32_t x); bool zm0p_is_trigger(); @@ -224,6 +200,7 @@ class PipetteModule : public ZIModule { void zm_waitfor_zm0p_not_trigger_and_stop_motor(bool *triggerEdge); void zm_waitfor_stop(); + private: /*********************************************************************************************************************** * pump_simple_script * ***********************************************************************************************************************/ @@ -241,53 +218,101 @@ class PipetteModule : public ZIModule { 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); - /*********************************************************************************************************************** - * Utils * + * UTILS * ***********************************************************************************************************************/ - zm_vcfg_t *get_zm_vcfg(int32_t index); - pm_vcfg_t *get_pm_vcfg(int32_t index); - container_info_t *get_container_info(int32_t index); - liquid_info_t *get_liquid_info(int32_t index); - platinfo_t *get_platinfo(int32_t index); - - void get_cfg_smart(int32_t index, zm_vcfg_t *cfg); - void get_cfg_smart(int32_t index, pm_vcfg_t *cfg); - container_info_t *get_container_info_smart(int32_t index, container_info_t *val); - liquid_info_t *get_liquid_info_smart(int32_t index, liquid_info_t *val); - platinfo_t *get_platinfo_smart(int32_t index, platinfo_t *val); - + private: void assign_cfg_smart(int32_t *dest, int32_t *src, int32_t *defaultcfg, int32_t num); void memset_int32_t(int32_t *table, int32_t val, int32_t num); + void check_platinfo_cpyid(int32_t cpyid); + void check_zmvcfg_cpyid(int32_t cpyid); + void check_pmvcfg_cpyid(int32_t cpyid); + void check_container_info_cpyid(int32_t cpyid); + void check_liquid_info_cpyid(int32_t cpyid); + void check_zmotor_is_enable(); + void check_pipette_pump_aspirate_params(); int32_t compute_zm_llf_vel(int32_t pm_vindex, container_info_t *container_info); + void push_pressure_sample_data(int32_t motor_pos, int32_t pressure_val); + int32_t calibrate_liquid_volume(liquid_info_t *liquidinfo, int32_t volumex100nl); + + void dump(const char *title, platinfo_t *info); + void dump(const char *title, liquid_info_t *info); + void dump(const char *title, container_info_t *info); + void dump(const char *title, aspiration_param_t *param); + void dump(const char *title, distribu_all_param_t *param); + + private: + /*********************************************************************************************************************** + * STATE * + ***********************************************************************************************************************/ + void clearPipetteGunState() { memset(&m_pump_gun_state, 0, sizeof(m_pump_gun_state)); } public: /*********************************************************************************************************************** - * SLICE * + * Z轴控制 * ***********************************************************************************************************************/ - virtual int32_t bfcall(int32_t cmdid, uint8_t *param, int32_t len) override; - virtual void aftercall(int32_t cmdid, uint8_t *param, int32_t len, uint8_t *ack, int32_t acklen, int32_t ret); - void runingcheck(); - void thread_delay(int32_t delayms); - void thread_start_work(const char *fnname, function fn); + virtual int32_t pipette_zmotor_enable(int32_t enable); + virtual int32_t pipette_zmotor_move_zero(); + virtual int32_t pipette_zmotor_move_to_zero_point_quick(); + virtual int32_t pipette_zmotor_measure_distance(); + virtual int32_t pipette_zmotor_read_measure_distance_result(int32_t *result0); + virtual int32_t pipette_zmotor_move_by(int32_t distance); + virtual int32_t pipette_zmotor_move_to(int32_t position); + + virtual int32_t pipette_zmotor_read_zero_point_state(int32_t *state); + virtual int32_t pipette_zmotor_read_dev_status_cache(int32_t *devStatus); + virtual int32_t pipette_zmotor_read_pos(int32_t *pos); + virtual int32_t pipette_zmotor_read_enc_pos(int32_t *pos); /*********************************************************************************************************************** - * CHECK * + * PUMP * ***********************************************************************************************************************/ + virtual int32_t pipette_pump_init_device(int32_t platinfo_cpyid); + virtual int32_t pipette_pump_take_tip(); + virtual int32_t pipette_pump_putbak_tip(); + virtual int32_t pipette_pump_deposit_tip(); + virtual int32_t pipette_pump_pierce_through(int32_t container_info_index, int32_t container_pos); - void check_platinfo_cpyid(int32_t cpyid); - void check_zmvcfg_cpyid(int32_t cpyid); - void check_pmvcfg_cpyid(int32_t cpyid); - void check_container_info_cpyid(int32_t cpyid); - void check_liquid_info_cpyid(int32_t cpyid); + virtual int32_t pipette_pump_aspirate_set_param(aspiration_paramid_t param, int32_t val); + virtual int32_t pipette_pump_aspirate(); + 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); - void check_zmotor_is_enable(); + virtual int32_t pipette_pump_distribu_all_set_param(distribu_all_paramid_t param, int32_t val); + virtual int32_t pipette_pump_distribu_all(); - void check_pipette_pump_aspirate_params(); + 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); + virtual int32_t pipette_read_state(pipette_state_index_t stateindex, int32_t *val); + virtual int32_t pipette_read_tip_state(int32_t *tipstate); + virtual int32_t pipette_read_pressure(int32_t *pressure); + virtual int32_t pipette_read_capacitance(int32_t *capacitance); - void parameter_init(); + // 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); + virtual int32_t pipette_test_move_to_container_bottom(int32_t container_pos, int32_t container_cpyid); + virtual int32_t pipette_test_move_to_container_bottom_section_begin(int32_t container_pos, int32_t container_cpyid); + virtual int32_t pipette_test_move_to_immersion_pos(int32_t container_pos, int32_t container_cpyid); + virtual int32_t pipette_test_move_to_leaving_height_pos(int32_t container_pos, int32_t container_cpyid); + virtual int32_t pipette_test_move_to_jet_pos(int32_t container_pos, int32_t container_cpyid); + virtual int32_t pipette_test_move_to_lld_start_search_pos(int32_t container_pos, int32_t container_cpyid); + virtual int32_t pipette_test_move_to_fix_water_level_pos(int32_t container_pos, int32_t container_cpyid); + virtual int32_t pipette_test_move_to_pierce_pos(int32_t container_pos, int32_t container_cpyid); + + /*********************************************************************************************************************** + * Utils * + ***********************************************************************************************************************/ + + public: + /*********************************************************************************************************************** + * SLICE * + ***********************************************************************************************************************/ + virtual int32_t bfcall(int32_t cmdid, uint8_t *param, int32_t len) override; + virtual void aftercall(int32_t cmdid, uint8_t *param, int32_t len, uint8_t *ack, int32_t acklen, int32_t ret); + void runingcheck(); + void thread_delay(int32_t delayms); + void thread_start_work(const char *fnname, function fn); }; } // namespace iflytop diff --git a/sdk/components/pipette_module/pipette_ctrl_module_config_function_impl.cpp b/sdk/components/pipette_module/pipette_ctrl_module_config_function_impl.cpp new file mode 100644 index 0000000..116624a --- /dev/null +++ b/sdk/components/pipette_module/pipette_ctrl_module_config_function_impl.cpp @@ -0,0 +1,477 @@ +#include + +#include "pipette_ctrl_module.hpp" +#include "sdk\components\zcancmder\protocol_event_bus_sender.hpp" +// +#include "base/pipette_marco_utils.hpp" +#include "sdk/chip/exhal/stm32_exhal_uart.hpp" +#include "sdk\components\exception\zapp_exception.hpp" +#include "sdk\components\exception\zapp_thread_stoped_exception.hpp" +#define TAG "PipetteModule" + +using namespace iflytop; +int32_t PipetteModule::pipette_set_pmbcfg(pm_bcfg_index_t index, int32_t val) { + switch (index) { + SET_CFG(kpm_bcfg_pad, pm_base_cfg.pad, val); + SET_CFG(kpm_bcfg_mark, pm_base_cfg.mark, val); + default: { + ZLOGE(TAG, "pipette_set_pmbcfg index %d out of range", index); + return err::kparam_out_of_range; + } + } + return 0; +} +int32_t PipetteModule::pipette_get_pmbcfg(pm_bcfg_index_t index, int32_t *val) { + switch (index) { + GET_CFG(kpm_bcfg_pad, pm_base_cfg.pad, val); + GET_CFG(kpm_bcfg_mark, pm_base_cfg.mark, val); + default: { + ZLOGE(TAG, "pipette_get_pmbcfg index %d out of range", index); + return err::kparam_out_of_range; + } + } + return 0; +} + +int32_t PipetteModule::pipette_set_liquid_info(int32_t cpyid, liquid_info_index_t index, int32_t val) { + if (cpyid < 0 || cpyid >= ARRARY_SIZE(m_liquid_info)) { + ZLOGE(TAG, "pipette_set_liquid_info cpyid %d out of range", cpyid); + return err::kparam_out_of_range; + } + + liquid_info_t *cfg = &m_liquid_info[cpyid]; + if (index < 0 || index > kliquid_info_mark) { + ZLOGE(TAG, "pipette_set_liquid_info index %d out of range", index); + return err::kparam_out_of_range; + } + + int32_t *settadd = ((int32_t *)cfg) + index; + *settadd = val; // 直接设置值 + ZLOGI(TAG, "pipette_set_liquid_info cpyid %d index %s val %d", cpyid, liquid_info_index_to_string(index), val); + return 0; +} +int32_t PipetteModule::pipette_get_liquid_info(int32_t cpyid, liquid_info_index_t index, int32_t *val) { + if (cpyid < 0 || cpyid >= ARRARY_SIZE(m_liquid_info)) { + ZLOGE(TAG, "pipette_get_liquid_info cpyid %d out of range", cpyid); + return err::kparam_out_of_range; + } + + if (index < 0 || index > kliquid_info_mark) { + ZLOGE(TAG, "pipette_get_liquid_info index %d out of range", index); + return err::kparam_out_of_range; + } + + liquid_info_t *cfg = &m_liquid_info[cpyid]; + int32_t *settadd = ((int32_t *)cfg) + index; + + *val = *settadd; // 直接获取值 + ZLOGI(TAG, "pipette_get_liquid_info cpyid %d index %s val %d", cpyid, liquid_info_index_to_string(index), *val); + + return 0; +} + +int32_t PipetteModule::pipette_set_zmbcfg(zm_bcfg_index_t index, int32_t val) { + if (index < 0 || index > kzm_bcfg_max) { + ZLOGE(TAG, "pipette_set_zmbcfg index %d out of range", index); + return err::kparam_out_of_range; + } + + int32_t *settadd = ((int32_t *)&zmbcfg) + index; + *settadd = val; // 直接设置值 + + ZLOGI(TAG, "pipette_set_zmbcfg index %s val %d", zm_bcfg_index_to_string(index), val); + + zm_sync_base_cfg(); + return 0; +} +int32_t PipetteModule::pipette_get_zmbcfg(zm_bcfg_index_t index, int32_t *val) { + if (index < 0 || index > kzm_bcfg_max) { + ZLOGE(TAG, "pipette_get_zmbcfg index %d out of range", index); + return err::kparam_out_of_range; + } + + int32_t *settadd = ((int32_t *)&zmbcfg) + index; + *val = *settadd; // 直接获取值 + ZLOGI(TAG, "pipette_get_zmbcfg index %s val %d", zm_bcfg_index_to_string(index), *val); + + return 0; +} + +int32_t PipetteModule::pipette_set_platinfo(int32_t cpyid, platinfo_index_t index, int32_t val) { + if (cpyid < 0 || cpyid >= ARRARY_SIZE(m_platinfo)) { + ZLOGE(TAG, "pipette_set_platinfo cpyid %d out of range", cpyid); + return err::kparam_out_of_range; + } + + if (index < 0 || index > kplatinfo_mark) { + ZLOGE(TAG, "pipette_set_platinfo index %d out of range", index); + return err::kparam_out_of_range; + } + + platinfo_t *platinfo = &m_platinfo[cpyid]; + int32_t *settadd = ((int32_t *)platinfo) + index; + *settadd = val; // 直接设置值 + + ZLOGI(TAG, "pipette_set_platinfo cpyid %d index %s val %d", cpyid, platinfo_index_to_string(index), val); + + return 0; +} +int32_t PipetteModule::pipette_get_platinfo(int32_t cpyid, platinfo_index_t index, int32_t *val) { + if (cpyid < 0 || cpyid >= ARRARY_SIZE(m_platinfo)) { + ZLOGE(TAG, "pipette_get_platinfo cpyid %d out of range", cpyid); + return err::kparam_out_of_range; + } + + if (index < 0 || index > kplatinfo_mark) { + ZLOGE(TAG, "pipette_get_platinfo index %d out of range", index); + return err::kparam_out_of_range; + } + + platinfo_t *platinfo = &m_platinfo[cpyid]; + int32_t *settadd = ((int32_t *)platinfo) + index; + *val = *settadd; // 直接获取值 + + ZLOGI(TAG, "pipette_get_platinfo cpyid %d index %s val %d", cpyid, platinfo_index_to_string(index), *val); + return 0; +} + +int32_t PipetteModule::pipette_set_zmvcfg(int32_t cpyid, zm_vcfg_index_t index, int32_t val) { + if (cpyid < 0 || cpyid >= ARRARY_SIZE(m_zm_vcfg)) { + ZLOGE(TAG, "pipette_set_zmvcfg cpyid %d out of range", cpyid); + return err::kparam_out_of_range; + } + if (index < 0 || index > kzm_vcfg_max) { + ZLOGE(TAG, "pipette_set_zmvcfg index %d out of range", index); + return err::kparam_out_of_range; + } + + zm_vcfg_t *cfg = &m_zm_vcfg[cpyid]; + int32_t *settadd = ((int32_t *)cfg) + index; + *settadd = val; // 直接设置值 + return 0; +} +int32_t PipetteModule::pipette_get_zmvcfg(int32_t cpyid, zm_vcfg_index_t index, int32_t *val) { + if (cpyid < 0 || cpyid >= ARRARY_SIZE(m_zm_vcfg)) { + ZLOGE(TAG, "pipette_get_zmvcfg cpyid %d out of range", cpyid); + return err::kparam_out_of_range; + } + + if (index < 0 || index > kzm_vcfg_max) { + ZLOGE(TAG, "pipette_get_zmvcfg index %d out of range", index); + return err::kparam_out_of_range; + } + + zm_vcfg_t *cfg = &m_zm_vcfg[cpyid]; + int32_t *settadd = ((int32_t *)cfg) + index; + *val = *settadd; // 直接获取值 + + ZLOGI(TAG, "pipette_get_zmvcfg cpyid %d index %s val %d", cpyid, zm_vcfg_index_to_string(index), *val); + + return 0; +} + +int32_t PipetteModule::pipette_set_pmvcfg(int32_t cpyid, pm_vcfg_index_t index, int32_t val) { + if (cpyid < 0 || cpyid >= ARRARY_SIZE(m_pm_vcfg)) { + ZLOGE(TAG, "pipette_set_pmvcfg cpyid %d out of range", cpyid); + return err::kparam_out_of_range; + } + + if (index < 0 || index > kpm_vcfg_max) { + ZLOGE(TAG, "pipette_set_pmvcfg index %d out of range", index); + return err::kparam_out_of_range; + } + + pm_vcfg_t *cfg = &m_pm_vcfg[cpyid]; + int32_t *settadd = ((int32_t *)cfg) + index; + *settadd = val; // 直接设置值 + + ZLOGI(TAG, "pipette_set_pmvcfg cpyid %d index %s val %d", cpyid, pm_vcfg_index_to_string(index), val); + + return 0; +} +int32_t PipetteModule::pipette_get_pmvcfg(int32_t cpyid, pm_vcfg_index_t index, int32_t *val) { + if (cpyid < 0 || cpyid >= ARRARY_SIZE(m_pm_vcfg)) { + ZLOGE(TAG, "pipette_get_pmvcfg cpyid %d out of range", cpyid); + return err::kparam_out_of_range; + } + + if (index < 0 || index > kpm_vcfg_max) { + ZLOGE(TAG, "pipette_get_pmvcfg index %d out of range", index); + return err::kparam_out_of_range; + } + + pm_vcfg_t *cfg = &m_pm_vcfg[cpyid]; + int32_t *settadd = ((int32_t *)cfg) + index; + *val = *settadd; // 直接获取值 + + ZLOGI(TAG, "pipette_get_pmvcfg cpyid %d index %s val %d", cpyid, pm_vcfg_index_to_string(index), *val); + return 0; +} +int32_t PipetteModule::pipette_set_container_info(int32_t cpyid, container_info_index_t index, int32_t val) { + if (cpyid < 0 || cpyid >= ARRARY_SIZE(m_container_info)) { + ZLOGE(TAG, "pipette_set_container_info cpyid %d out of range", cpyid); + return err::kparam_out_of_range; + } + + if (index < 0 || index > kcontainer_info_mark) { + ZLOGE(TAG, "pipette_set_container_info index %d out of range", index); + return err::kparam_out_of_range; + } + + container_info_t *cfg = &m_container_info[cpyid]; + int32_t *settadd = ((int32_t *)cfg) + index; + + *settadd = val; // 直接设置值 + ZLOGI(TAG, "pipette_set_container_info cpyid %d index %s val %d", cpyid, container_info_index_to_string(index), val); + + return 0; +} +int32_t PipetteModule::pipette_get_container_info(int32_t cpyid, container_info_index_t index, int32_t *val) { + if (cpyid < 0 || cpyid >= ARRARY_SIZE(m_container_info)) { + ZLOGE(TAG, "pipette_get_container_info cpyid %d out of range", cpyid); + return err::kparam_out_of_range; + } + + if (index < 0 || index > kcontainer_info_mark) { + ZLOGE(TAG, "pipette_get_container_info index %d out of range", index); + return err::kparam_out_of_range; + } + + container_info_t *cfg = &m_container_info[cpyid]; + int32_t *settadd = ((int32_t *)cfg) + index; + *val = *settadd; // 直接获取值 + + ZLOGI(TAG, "pipette_get_container_info cpyid %d index %s val %d", cpyid, container_info_index_to_string(index), *val); + + return 0; +} + +int32_t PipetteModule::pipette_read_state(pipette_state_index_t stateindex, int32_t *val) { + static_assert(kpipette_state_max == sizeof(m_state) / 4); + int32_t off = (int32_t)stateindex; + if (off < 0 || off >= (int32_t)kpipette_state_max) { + ZLOGE(TAG, "pipette_read_state index %d out of range", stateindex); + return err::kparam_out_of_range; + } + *val = *(((int32_t *)&m_state) + off); + ZLOGI(TAG, "pipette_read_state index %d val %d", stateindex, *val); + return 0; +} + +int32_t PipetteModule::pipette_get_platinfo_max_cpyid(int32_t *cpyid) { + *cpyid = ARRARY_SIZE(m_platinfo) - 1; + return 0; +} +int32_t PipetteModule::pipette_get_zmvcfg_max_cpyid(int32_t *cpyid) { + *cpyid = ARRARY_SIZE(m_zm_vcfg) - 1; + return 0; +} + +int32_t PipetteModule::pipette_get_pmvcfg_max_cpyid(int32_t *cpyid) { + *cpyid = ARRARY_SIZE(m_pm_vcfg) - 1; + return 0; +} + +int32_t PipetteModule::pipette_get_container_info_max_cpyid(int32_t *cpyid) { + *cpyid = ARRARY_SIZE(m_container_info) - 1; + return 0; +} + +int32_t PipetteModule::pipette_get_liquid_info_max_cpyid(int32_t *cpyid) { + *cpyid = ARRARY_SIZE(m_liquid_info) - 1; + return 0; +} + +zm_vcfg_t *PipetteModule::get_zm_vcfg(int32_t index) { + if (index < 0 || index >= ARRARY_SIZE(m_zm_vcfg)) { + ZLOGE(TAG, "get_zm_vcfg index %d out of range", index); + return &m_zm_vcfg[0]; + } + return &m_zm_vcfg[index]; +} + +pm_vcfg_t *PipetteModule::get_pm_vcfg(int32_t index) { + if (index < 0 || index >= ARRARY_SIZE(m_pm_vcfg)) { + ZLOGE(TAG, "get_pm_vcfg index %d out of range", index); + return &m_pm_vcfg[0]; + } + return &m_pm_vcfg[index]; +} + +container_info_t *PipetteModule::get_container_info(int32_t index) { + if (index < 0 || index >= ARRARY_SIZE(m_container_info)) { + ZLOGE(TAG, "get_container_info index %d out of range", index); + return &m_container_info[0]; + } + return &m_container_info[index]; +} +liquid_info_t *PipetteModule::get_liquid_info(int32_t index) { + if (index < 0 || index >= ARRARY_SIZE(m_liquid_info)) { + ZLOGE(TAG, "get_liquid_info index %d out of range", index); + return &m_liquid_info[0]; + } + return &m_liquid_info[index]; +} +platinfo_t *PipetteModule::get_platinfo(int32_t index) { + if (index < 0 || index >= ARRARY_SIZE(m_platinfo)) { + ZLOGE(TAG, "get_platinfo index %d out of range", index); + return &m_platinfo[0]; + } + return &m_platinfo[index]; +} + +void PipetteModule::get_cfg_smart(int32_t index, zm_vcfg_t *cfg) { // + zm_vcfg_t *cfg0 = get_zm_vcfg(0); + zm_vcfg_t *cfgx = get_zm_vcfg(index); + static_assert(sizeof(zm_vcfg_t) % sizeof(int32_t) == 0, "zm_vcfg_t size is not multiple of int32_t"); + assign_cfg_smart((int32_t *)cfg, (int32_t *)cfgx, (int32_t *)cfg0, sizeof(zm_vcfg_t) / sizeof(int32_t)); + return; +} +void PipetteModule::get_cfg_smart(int32_t index, pm_vcfg_t *cfg) { + /** + * @brief 当配置项的值为负数时,使用默认配置项的值 + */ + pm_vcfg_t *cfg0 = get_pm_vcfg(0); + pm_vcfg_t *cfgx = get_pm_vcfg(index); + static_assert(sizeof(pm_vcfg_t) % sizeof(int32_t) == 0, "pm_vcfg_t size is not multiple of int32_t"); + assign_cfg_smart((int32_t *)cfg, (int32_t *)cfgx, (int32_t *)cfg0, sizeof(pm_vcfg_t) / sizeof(int32_t)); + return; +} + +container_info_t *PipetteModule::get_container_info_smart(int32_t index, container_info_t *val) { + container_info_t *cfg = get_container_info(index); + container_info_t *cfg0 = get_container_info(0); + static_assert(sizeof(container_info_t) % sizeof(int32_t) == 0, "container_info_t size is not multiple of int32_t"); + assign_cfg_smart((int32_t *)val, (int32_t *)cfg, (int32_t *)cfg0, sizeof(container_info_t) / sizeof(int32_t)); + return val; +} +platinfo_t *PipetteModule::get_platinfo_smart(int32_t index, platinfo_t *val) { + platinfo_t *cfg = get_platinfo(index); + platinfo_t *cfg0 = get_platinfo(0); + static_assert(sizeof(platinfo_t) % sizeof(int32_t) == 0, "platinfo_t size is not multiple of int32_t"); + assign_cfg_smart((int32_t *)val, (int32_t *)cfg, (int32_t *)cfg0, sizeof(platinfo_t) / sizeof(int32_t)); + return val; +} + +liquid_info_t *PipetteModule::get_liquid_info_smart(int32_t index, liquid_info_t *val) { + liquid_info_t *cfg = get_liquid_info(index); + liquid_info_t *cfg0 = get_liquid_info(0); + static_assert(sizeof(liquid_info_t) % sizeof(int32_t) == 0, "liquid_info_t size is not multiple of int32_t"); + assign_cfg_smart((int32_t *)val, (int32_t *)cfg, (int32_t *)cfg0, sizeof(liquid_info_t) / sizeof(int32_t)); + return val; +} + +void PipetteModule::parameter_init() { + /*********************************************************************************************************************** + * zmbcfg * + ***********************************************************************************************************************/ + zmbcfg.shaft = 0; // Z轴电机运动方向调整 + zmbcfg.one_circle_pulse = 80; // 电子齿轮比-分子 + zmbcfg.one_circle_pulse_denominator = 1; // 电子齿轮比-分母 + zmbcfg.ihold = 7; // + zmbcfg.irun = 7; // + zmbcfg.iholddelay = 10; // + zmbcfg.iglobalscaler = 0; // + zmbcfg.min_d = 0; // + zmbcfg.max_d = 0; // + zmbcfg.tzerowait = 0; // + zmbcfg.enc_resolution = 0; // + zmbcfg.enable_enc = 0; // + zmbcfg.dzero = 92; // + zmbcfg.io_trigger_append_distance = 20; // + zmbcfg.pos_devi_tolerance = 20; // + zmbcfg.mres = 0; // + zmbcfg.mark = 9973; // + /*********************************************************************************************************************** + * pm_base_cfg * + ***********************************************************************************************************************/ + pm_base_cfg.pad = 0; + pm_base_cfg.mark = 9973; + + /*********************************************************************************************************************** + * m_platinfo * + ***********************************************************************************************************************/ + memset_int32_t((int32_t *)&m_platinfo[0], -1, sizeof(m_platinfo) / 4); + memset_int32_t((int32_t *)&m_platinfo[0], 0, sizeof(m_platinfo[0]) / 4); + m_platinfo[0].tip_type = smtp2::TS200UL; + m_platinfo[0].tip_length = 500; // 50mm + m_platinfo[0].mark = 9973; // + + /*********************************************************************************************************************** + * m_zm_vcfg * + ***********************************************************************************************************************/ + memset_int32_t((int32_t *)&m_zm_vcfg[0], -1, sizeof(m_zm_vcfg) / 4); + memset_int32_t((int32_t *)&m_zm_vcfg[0], 0, sizeof(m_zm_vcfg[0]) / 4); + m_zm_vcfg[kzm_v_default].vstart = 100; + m_zm_vcfg[kzm_v_default].a1 = 50; + m_zm_vcfg[kzm_v_default].amax = 100; + m_zm_vcfg[kzm_v_default].v1 = 100; + m_zm_vcfg[kzm_v_default].dmax = 100; + m_zm_vcfg[kzm_v_default].d1 = 200; + m_zm_vcfg[kzm_v_default].vstop = 400; + m_zm_vcfg[kzm_v_default].vmax = 1200; + m_zm_vcfg[kzm_v_default].mark = 9973; + + m_zm_vcfg[kzm_v_move_to_zero].vmax = 600; + m_zm_vcfg[kzm_v_look_zero_edge].vmax = 100; + m_zm_vcfg[kzm_v_lld].vmax = 100; + m_zm_vcfg[kzm_v_swap_in].vmax = 300; + m_zm_vcfg[kzm_v_swap_out].vmax = 300; + m_zm_vcfg[kzm_v_llf].vmax = 500; + + /*********************************************************************************************************************** + * m_pm_vcfg * + ***********************************************************************************************************************/ + + memset_int32_t((int32_t *)&m_pm_vcfg[0], -1, sizeof(m_pm_vcfg) / 4); + memset_int32_t((int32_t *)&m_pm_vcfg[0], 0, sizeof(m_pm_vcfg[0]) / 4); + m_pm_vcfg[kpm_v_default].acc = 1; + m_pm_vcfg[kpm_v_default].dec = 1; + m_pm_vcfg[kpm_v_default].vstart = 100; + m_pm_vcfg[kpm_v_default].vstop = 50; + m_pm_vcfg[kpm_v_default].mark = 9973; + + // + m_pm_vcfg[kpm_v_default].vmax = 2500; + m_pm_vcfg[kpm_v_slow_lv1].vmax = 5; + m_pm_vcfg[kpm_v_slow_lv2].vmax = 10; + m_pm_vcfg[kpm_v_slow_lv3].vmax = 50; + m_pm_vcfg[kpm_v_mid].vmax = 1000; + m_pm_vcfg[kpm_v_quick].vmax = 2000; + m_pm_vcfg[kpm_v_max].vmax = 2500; + m_pm_vcfg[kpm_v_lld].vmax = 100; + + /*********************************************************************************************************************** + * m_container_info * + ***********************************************************************************************************************/ + memset_int32_t((int32_t *)&m_container_info[0], -1, sizeof(m_container_info) / 4); + memset_int32_t((int32_t *)&m_container_info[0], 0, sizeof(m_container_info[0]) / 4); + m_container_info[0].leaving_height = 150; + m_container_info[0].mark = 9973; + + /*********************************************************************************************************************** + * m_liquid_info * + ***********************************************************************************************************************/ + + memset_int32_t((int32_t *)&m_liquid_info[0], -1, sizeof(m_liquid_info) / 4); + memset_int32_t((int32_t *)&m_liquid_info[0], 0, sizeof(m_liquid_info[0]) / 4); + + m_liquid_info[0].plld_pm_vcpyid = kpm_v_lld; + m_liquid_info[0].plld_threshold = 30; + m_liquid_info[0].plld_zm_vel = 50; + m_liquid_info[0].empty_tip_pm_vcpyid = kpm_v_max; + m_liquid_info[0].blowout_air_volume = 0; + m_liquid_info[0].blowout_air_pm_vcpyid = kpm_v_quick; + m_liquid_info[0].over_aspirated_volume = 100; // 100(x100nl) == 10ul + m_liquid_info[0].over_aspirated_pm_vcpyid = kpm_v_slow_lv2; + m_liquid_info[0].aspiration_pm_vindex_low = kpm_v_slow_lv1; + m_liquid_info[0].aspiration_pm_vindex_high = kpm_v_slow_lv3; + m_liquid_info[0].aspiration_volume_break_val = 500; // 500(x100nl) == 50ul + m_liquid_info[0].volume_calibration_coefficient_b = 1.0f; + m_liquid_info[0].volume_calibration_coefficient_k = 1.0f; + m_liquid_info[0].settling_time = 1000; // ms + m_liquid_info[0].transport_volume = 50; // 50(x100nl) == 5ul + m_liquid_info[0].transport_volume_pm_vcpyid = kpm_v_slow_lv2; + m_liquid_info[0].mix_pm_vcpyid = kpm_v_max; + m_liquid_info[0].mark = 9973; +} diff --git a/sdk/components/pipette_module/pipette_ctrl_module_pm_ctrl.cpp b/sdk/components/pipette_module/pipette_ctrl_module_pm_ctrl.cpp new file mode 100644 index 0000000..33fd804 --- /dev/null +++ b/sdk/components/pipette_module/pipette_ctrl_module_pm_ctrl.cpp @@ -0,0 +1,124 @@ +#include + +#include "pipette_ctrl_module.hpp" +#include "sdk\components\zcancmder\protocol_event_bus_sender.hpp" +// +#include "base/pipette_marco_utils.hpp" +#include "sdk/chip/exhal/stm32_exhal_uart.hpp" +#include "sdk\components\exception\zapp_exception.hpp" +#include "sdk\components\exception\zapp_thread_stoped_exception.hpp" +#define TAG "PipetteModule" + +using namespace iflytop; + +void PipetteModule::pump_get_vcfg(int32_t vcfgcpyid, smtp2::VelCfg *cfg) { + pm_vcfg_t cfg2 = {0}; + get_cfg_smart(vcfgcpyid, &cfg2); + cfg->acc = cfg2.acc; + cfg->dec = cfg2.dec; + cfg->vstart = cfg2.vstart; + cfg->vstop = cfg2.vstop; + cfg->vmax = cfg2.vmax; +} + +void PipetteModule::pump_apply_vcfg(int32_t vcfgcpyid, bool force) { + ZLOGI(TAG, "pump_apply_vcfg %s", get_pm_vcpyid_name((pm_vcpyid_t)vcfgcpyid)); + + smtp2::VelCfg vcfg; + pump_get_vcfg(vcfgcpyid, &vcfg); + + DO_IN_THREAD(m_smtp2.pump_set_vcfg(&vcfg)); +} +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(vcfgcpyid, &vcfg); + DO_IN_THREAD(m_smtp2.pump_move_to_nl(&vcfg, x100nl * 100)); +} +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(vcfgidx, &vcfg); + DO_IN_THREAD(m_smtp2.pump_aspirate_plld(pressure_threshold, &vcfg)); +} + +void PipetteModule::pump_move_to_x100nl_block(double x100nl, int32_t vcfgcpyid, int32_t *diff) { + ZLOGI(TAG, "pump_move_to_x100nl_block %f nl, in %s", x100nl, get_pm_vcpyid_name((pm_vcpyid_t)vcfgcpyid)); + + 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(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) { + // + // *val = m_state.load_val_ul; + // *val = pum + // pump_read_pos_nl(val); + DO_IN_THREAD(m_smtp2.pump_get_nl(val)); +} +int32_t PipetteModule::pump_read_pos_nl() { + int32_t val = 0; + DO_IN_THREAD(m_smtp2.pump_get_nl(&val)); + return val; +} +int32_t PipetteModule::pump_read_capactitance() { + int32_t val = 0; + DO_IN_THREAD(m_smtp2.pump_get_capacitance(&val)); + return val; +} +int32_t PipetteModule::pump_read_tip_state() { + int32_t val = 0; + DO_IN_THREAD(m_smtp2.pump_get_tip_state(&val)); + return val; +} + + +void PipetteModule::pump_waitfor_stop() { + while (true) { + int32_t isbusy = 0; + DO_IN_THREAD(m_smtp2.pump_get_state(&isbusy)); + if (isbusy == 0) break; + thread_delay(10); + } +} + +void PipetteModule::pump_waitfor_lld_is_ready(int32_t *zpos) { + m_smtp2.pump_set_io1_mode(0); // lld输入高 + while (true) { + int32_t isbusy = 0; + if (m_piette_gun_io1.getState()) { + } + } +} diff --git a/sdk/components/pipette_module/pipette_ctrl_module_test.cpp b/sdk/components/pipette_module/pipette_ctrl_module_test.cpp new file mode 100644 index 0000000..47dfcb6 --- /dev/null +++ b/sdk/components/pipette_module/pipette_ctrl_module_test.cpp @@ -0,0 +1,116 @@ +#include "pipette_ctrl_module.hpp" + +#include + +#include "sdk\components\zcancmder\protocol_event_bus_sender.hpp" +// +#include "base/pipette_marco_utils.hpp" +#include "sdk/chip/exhal/stm32_exhal_uart.hpp" +#include "sdk\components\exception\zapp_exception.hpp" +#include "sdk\components\exception\zapp_thread_stoped_exception.hpp" +#define TAG "PipetteModule" + +using namespace iflytop; +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_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; +} + +int32_t PipetteModule::pipette_test_move_to_container_bottom(int32_t container_pos, int32_t container_cpyid) { + thread_start_work(__FUNCTION__, [this, container_pos, container_cpyid]() { + container_info_t *container_info = get_container_info_smart(container_cpyid, &m_now_container_info); + check_container_info_cpyid(container_cpyid); + zm_move_to_container_bottom_block(container_pos, container_info, kzm_v_default, 0); // 移动到容器底部 + }); + return 0; +} +int32_t PipetteModule::pipette_test_move_to_container_bottom_section_begin(int32_t container_pos, int32_t container_cpyid) { + thread_start_work(__FUNCTION__, [this, container_pos, container_cpyid]() { + container_info_t *container_info = get_container_info_smart(container_cpyid, &m_now_container_info); + check_container_info_cpyid(container_cpyid); + zm_move_to_container_bottom_section_begin_block(container_pos, container_info, kzm_v_default, 0); // 移动到容器底部 + }); + return 0; +} +int32_t PipetteModule::pipette_test_move_to_immersion_pos(int32_t container_pos, int32_t container_cpyid) { + thread_start_work(__FUNCTION__, [this, container_pos, container_cpyid]() { + container_info_t *container_info = get_container_info_smart(container_cpyid, &m_now_container_info); + check_container_info_cpyid(container_cpyid); + zm_move_to_immersion_pos_block(container_pos, -1, container_info, kzm_v_default, 0); // 移动到液面下 + }); + return 0; +} +int32_t PipetteModule::pipette_test_move_to_leaving_height_pos(int32_t container_pos, int32_t container_cpyid) { + thread_start_work(__FUNCTION__, [this, container_pos, container_cpyid]() { + container_info_t *container_info = get_container_info_smart(container_cpyid, &m_now_container_info); + check_container_info_cpyid(container_cpyid); + zm_move_to_leaving_height_pos_block(container_pos, -1, container_info, kzm_v_default, 0); // 移动到液面上方 + }); + return 0; +} +int32_t PipetteModule::pipette_test_move_to_jet_pos(int32_t container_pos, int32_t container_cpyid) { + thread_start_work(__FUNCTION__, [this, container_pos, container_cpyid]() { + container_info_t *container_info = get_container_info_smart(container_cpyid, &m_now_container_info); + check_container_info_cpyid(container_cpyid); + zm_move_to_jet_pos_block(container_pos, -1, container_info, kzm_v_default, 0); // 移动到jet位置 + }); + return 0; +} +int32_t PipetteModule::pipette_test_move_to_lld_start_search_pos(int32_t container_pos, int32_t container_cpyid) { + thread_start_work(__FUNCTION__, [this, container_pos, container_cpyid]() { + container_info_t *container_info = get_container_info_smart(container_cpyid, &m_now_container_info); + check_container_info_cpyid(container_cpyid); + zm_move_to_lld_start_search_pos_block(container_pos, container_info, kzm_v_default, 0); // 移动到lld开始搜索位置 + }); + return 0; +} +int32_t PipetteModule::pipette_test_move_to_fix_water_level_pos(int32_t container_pos, int32_t container_cpyid) { + thread_start_work(__FUNCTION__, [this, container_pos, container_cpyid]() { + container_info_t *container_info = get_container_info_smart(container_cpyid, &m_now_container_info); + check_container_info_cpyid(container_cpyid); + zm_move_to_fix_water_level_pos_block(container_pos, container_info, kzm_v_default, 0); // 移动到固定水位位置 + }); + return 0; +} +int32_t PipetteModule::pipette_test_move_to_pierce_pos(int32_t container_pos, int32_t container_cpyid) { + thread_start_work(__FUNCTION__, [this, container_pos, container_cpyid]() { + container_info_t *container_info = get_container_info_smart(container_cpyid, &m_now_container_info); + check_container_info_cpyid(container_cpyid); + zm_move_to_pierce_pos_block(container_pos, container_info, kzm_v_default, 0); // 移动到穿刺位置 + }); + return 0; +} \ No newline at end of file diff --git a/sdk/components/pipette_module/pipette_ctrl_module_utils.cpp b/sdk/components/pipette_module/pipette_ctrl_module_utils.cpp new file mode 100644 index 0000000..e204271 --- /dev/null +++ b/sdk/components/pipette_module/pipette_ctrl_module_utils.cpp @@ -0,0 +1,194 @@ +#include + +#include "pipette_ctrl_module.hpp" +#include "sdk\components\zcancmder\protocol_event_bus_sender.hpp" +// +#include "base/pipette_marco_utils.hpp" +#include "sdk/chip/exhal/stm32_exhal_uart.hpp" +#include "sdk\components\exception\zapp_exception.hpp" +#include "sdk\components\exception\zapp_thread_stoped_exception.hpp" +#define TAG "PipetteModule" + +using namespace iflytop; + +void PipetteModule::assign_cfg_smart(int32_t *dest, int32_t *src, int32_t *defaultcfg, int32_t num) { + for (int i = 0; i < num; i++) { + if (src[i] >= 0) { + dest[i] = src[i]; + } else { + dest[i] = defaultcfg[i]; + } + } +} +void PipetteModule::memset_int32_t(int32_t *table, int32_t val, int32_t num) { + for (int i = 0; i < num; i++) { + table[i] = val; + } +} + +void PipetteModule::check_platinfo_cpyid(int32_t cpyid) { + if (cpyid < 0 || cpyid >= ARRARY_SIZE(m_platinfo)) { + ZLOGE(TAG, "pipette_get_container_info cpyid %d out of range", cpyid); + throw zapp_exception(err::kparam_out_of_range); + } +} +void PipetteModule::check_zmvcfg_cpyid(int32_t cpyid) { + if (cpyid < 0 || cpyid >= ARRARY_SIZE(m_zm_vcfg)) { + ZLOGE(TAG, "pipette_get_zmvcfg cpyid %d out of range", cpyid); + throw zapp_exception(err::kparam_out_of_range); + } +} +void PipetteModule::check_pmvcfg_cpyid(int32_t cpyid) { + if (cpyid < 0 || cpyid >= ARRARY_SIZE(m_pm_vcfg)) { + ZLOGE(TAG, "pipette_get_pmvcfg cpyid %d out of range", cpyid); + throw zapp_exception(err::kparam_out_of_range); + } +} +void PipetteModule::check_container_info_cpyid(int32_t cpyid) { + if (cpyid < 0 || cpyid >= ARRARY_SIZE(m_container_info)) { + ZLOGE(TAG, "pipette_get_container_info cpyid %d out of range", cpyid); + throw zapp_exception(err::kparam_out_of_range); + } +} +void PipetteModule::check_liquid_info_cpyid(int32_t cpyid) { + if (cpyid < 0 || cpyid >= ARRARY_SIZE(m_liquid_info)) { + ZLOGE(TAG, "pipette_get_liquid_info cpyid %d out of range", cpyid); + throw zapp_exception(err::kparam_out_of_range); + } +} +void PipetteModule::check_zmotor_is_enable() { + if (!m_zm->isMotorIcInitOk()) { + ZLOGE(TAG, "motor is not init"); + throw zapp_exception(err::kstep_motor_subic_init_fail); + } + if (!m_zm->isOnline()) { + ZLOGE(TAG, "motor is offline"); + throw zapp_exception(err::kstep_motor_subic_offline); + } + if (!m_state.enable) { + ZLOGE(TAG, "motor is not enable"); + throw zapp_exception(err::kstep_motor_not_enable); + } +} + +void PipetteModule::check_pipette_pump_aspirate_params() { + aspiration_param_t *acfg = &m_aspiration_param; + + if (acfg->volumeX100nl < 0) { + ZLOGE(TAG, "pipette_pump_aspirate_set_param x100nl %d out of range", acfg->volumeX100nl); + throw zapp_exception(err::kparam_out_of_range); + } + check_platinfo_cpyid(m_state.platinfo_cpyid); + check_container_info_cpyid(acfg->container_info_index); + check_liquid_info_cpyid(acfg->liquid_cfg_index); +} + +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.001; + if (zmval == 0) zmval = 1; + return zmval; +} + +void PipetteModule::push_pressure_sample_data(int32_t motor_pos, int32_t pressure_val) { + if (capturedata_num >= PIPETTEMODULE_SAMPLE_BUF_SIZE) { + ZLOGW(TAG, "capturedata_buf overflow"); + return; + } + + ZLOGI(TAG, "sample %2d mpos:%2d pressure_val:%4d", capturedata_num, motor_pos, pressure_val); + capturedata_buf[capturedata_num].motor_pos = motor_pos; + capturedata_buf[capturedata_num].pressure_val = pressure_val; + capturedata_num++; +} + +void PipetteModule::dump(const char *title, platinfo_t *info) { + ZLOGI(TAG, "-------------------------- %s --------------------------", title); + ZLOGI(TAG, "work_ref_pos: %d", info->work_ref_pos); + ZLOGI(TAG, "tip_picking_pos: %d", info->tip_picking_pos); + ZLOGI(TAG, "tip_picking_search_range: %d", info->tip_picking_search_range); + ZLOGI(TAG, "tip_picking_append_distance: %d", info->tip_picking_append_distance); + ZLOGI(TAG, "tip_deposit_pos: %d", info->tip_deposit_pos); + ZLOGI(TAG, "_transform_pos: %d", info->_transform_pos); + ZLOGI(TAG, "tip_type: %d", info->tip_type); + ZLOGI(TAG, "tip_length: %d", info->tip_length); + ZLOGI(TAG, "mark: %d", info->mark); + ZLOGI(TAG, "-") +} +void PipetteModule::dump(const char *title, liquid_info_t *liquidinfo) { + ZLOGI(TAG, "-------------------------- %s --------------------------", title); + ZLOGI(TAG, "- plld_pm_vindex :%d", liquidinfo->plld_pm_vcpyid); + ZLOGI(TAG, "- plld_threshold :%d", liquidinfo->plld_threshold); + ZLOGI(TAG, "- plld_zm_vel :%d", liquidinfo->plld_zm_vel); + ZLOGI(TAG, "- empty_tip_pm_vindex :%d", liquidinfo->empty_tip_pm_vcpyid); + ZLOGI(TAG, "- blowout_air_volume :%d", liquidinfo->blowout_air_volume); + ZLOGI(TAG, "- blowout_air_pm_vindex :%d", liquidinfo->blowout_air_pm_vcpyid); + ZLOGI(TAG, "- over_aspirated_volume :%d", liquidinfo->over_aspirated_volume); + ZLOGI(TAG, "- over_aspirated_pm_vindex :%d", liquidinfo->over_aspirated_pm_vcpyid); + ZLOGI(TAG, "- aspiration_pm_vindex_low :%d", liquidinfo->aspiration_pm_vindex_low); + ZLOGI(TAG, "- aspiration_pm_vindex_high :%d", liquidinfo->aspiration_pm_vindex_high); + ZLOGI(TAG, "- aspiration_volume_break_val :%d", liquidinfo->aspiration_volume_break_val); + ZLOGI(TAG, "- volume_calibration_coefficient_b :%d", liquidinfo->volume_calibration_coefficient_b); + ZLOGI(TAG, "- volume_calibration_coefficient_k :%d", liquidinfo->volume_calibration_coefficient_k); + ZLOGI(TAG, "- settling_time :%d", liquidinfo->settling_time); + ZLOGI(TAG, "- transport_volume :%d", liquidinfo->transport_volume); + ZLOGI(TAG, "- transport_volume_pm_vindex :%d", liquidinfo->transport_volume_pm_vcpyid); + ZLOGI(TAG, "- mix_pm_vindex :%d", liquidinfo->mix_pm_vcpyid); + ZLOGI(TAG, "- mark :%d", liquidinfo->mark); + ZLOGI(TAG, "-"); +} +void PipetteModule::dump(const char *title, container_info_t *container_cfg) { + ZLOGI(TAG, "-------------------------- %s --------------------------", title); + ZLOGI(TAG, "- container_type :%d", container_cfg->container_type); + ZLOGI(TAG, "- container_neck_pos :%d", container_cfg->_container_neck_pos); + ZLOGI(TAG, "- container_depth :%d", container_cfg->container_depth); + ZLOGI(TAG, "- container_round :%d", container_cfg->container_round); + ZLOGI(TAG, "- container_bottom_section_height :%d", container_cfg->container_bottom_section_height); + ZLOGI(TAG, "- immersion_depth :%d", container_cfg->immersion_depth); + 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_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); + ZLOGI(TAG, "-"); +} + +void PipetteModule::dump(const char *title, aspiration_param_t *param) { + ZLOGI(TAG, "-------------------------- %s --------------------------", title); + ZLOGI(TAG, "- volumeX100nl: %d", param->volumeX100nl); + ZLOGI(TAG, "- container_pos: %d", param->container_pos); + ZLOGI(TAG, "- container_info_index: %d", param->container_info_index); + ZLOGI(TAG, "- liquid_cfg_index: %d", param->liquid_cfg_index); + ZLOGI(TAG, "- aspiration_mode: %d", param->aspiration_mode); + ZLOGI(TAG, "- lld_enable: %d", param->lld_enable); + ZLOGI(TAG, "- lld_type: %d", param->lld_type); + ZLOGI(TAG, "- lld_enable_protect: %d", param->lld_enable_protect); + ZLOGI(TAG, "- mix_llf_enable: %d", param->mix_llf_enable); + ZLOGI(TAG, "- llf_enable: %d", param->llf_enable); + ZLOGI(TAG, "- mix_volume: %d", param->mix_volume); + ZLOGI(TAG, "- mix_times: %d", param->mix_times); + ZLOGI(TAG, "- max: %d", param->max); + ZLOGI(TAG, "-"); +} +void PipetteModule::dump(const char *title, distribu_all_param_t *param) { + ZLOGI(TAG, "-------------------------- %s --------------------------", title); + ZLOGI(TAG, "- container_pos: %d", param->container_pos); + ZLOGI(TAG, "- dest_container_cpyid: %d", param->dest_container_cpyid); + ZLOGI(TAG, "- dest_container_is_empty: %d", param->dest_container_is_empty); + ZLOGI(TAG, "- dest_liquid_cfg_index: %d", param->dest_liquid_cfg_index); + ZLOGI(TAG, "- distribu_type: %d", param->distribu_type); + ZLOGI(TAG, "- mix_volume: %d", param->mix_volume); + ZLOGI(TAG, "- mix_times: %d", param->mix_times); + ZLOGI(TAG, "- zm_auto_move_to_zero: %d", param->zm_auto_move_to_zero); + ZLOGI(TAG, "- max: %d", param->max); + ZLOGI(TAG, "-"); +} + +int32_t PipetteModule::calibrate_liquid_volume(liquid_info_t *liquidinfo, int32_t volumex100nl) { + int32_t x100nl = volumex100nl * liquidinfo->volume_calibration_coefficient_k * 0.001 + // + liquidinfo->volume_calibration_coefficient_b * 0.001; + return x100nl; +} diff --git a/sdk/components/pipette_module/pipette_ctrl_module_zm_ctrl.cpp b/sdk/components/pipette_module/pipette_ctrl_module_zm_ctrl.cpp new file mode 100644 index 0000000..9aade2c --- /dev/null +++ b/sdk/components/pipette_module/pipette_ctrl_module_zm_ctrl.cpp @@ -0,0 +1,242 @@ +#include + +#include "pipette_ctrl_module.hpp" +#include "sdk\components\zcancmder\protocol_event_bus_sender.hpp" +// +#include "base/pipette_marco_utils.hpp" +#include "sdk/chip/exhal/stm32_exhal_uart.hpp" +#include "sdk\components\exception\zapp_exception.hpp" +#include "sdk\components\exception\zapp_thread_stoped_exception.hpp" +#define TAG "PipetteModule" + +using namespace iflytop; + +void PipetteModule::zm_move_to_container_bottom_block(int32_t container_pos, container_info_t *containInfo, int32_t vbcpyid, int32_t vel) { // + zm_move_to_block(container_pos + containInfo->container_depth, vbcpyid, vel); +} +void PipetteModule::zm_move_to_container_bottom_section_begin_block(int32_t container_pos, container_info_t *containInfo, int32_t vbcpyid, int32_t vel) { // + zm_move_to_block(container_pos + containInfo->container_depth - containInfo->container_bottom_section_height, vbcpyid, vel); +} +void PipetteModule::zm_move_to_immersion_pos_block(int32_t container_pos, int32_t waterlevel, container_info_t *containInfo, int32_t vbcpyid, int32_t vel) { // + if (waterlevel == -1) + zm_move_to_block(container_pos + containInfo->fix_water_level_depth + containInfo->immersion_depth, vbcpyid, vel); + else + zm_move_to_block(waterlevel + containInfo->immersion_depth, vbcpyid, vel); +} +void PipetteModule::zm_move_to_leaving_height_pos_block(int32_t container_pos, int32_t waterlevel, container_info_t *containInfo, int32_t vbcpyid, int32_t vel) { // + if (waterlevel == -1) + zm_move_to_block(container_pos + containInfo->fix_water_level_depth - containInfo->leaving_height, vbcpyid, vel); + else + zm_move_to_block(waterlevel - containInfo->leaving_height, vbcpyid, vel); +} +void PipetteModule::zm_move_to_jet_pos_block(int32_t container_pos, int32_t waterlevel, container_info_t *containInfo, int32_t vbcpyid, int32_t vel) { // + if (waterlevel == -1) + zm_move_to_block(container_pos + containInfo->fix_water_level_depth - containInfo->jet_height, vbcpyid, vel); + else + zm_move_to_block(waterlevel - containInfo->jet_height, vbcpyid, vel); +} +void PipetteModule::zm_move_to_lld_start_search_pos_block(int32_t container_pos, container_info_t *containInfo, int32_t vbcpyid, int32_t vel) { // + zm_move_to_block(container_pos + containInfo->lld_start_search_depth, vbcpyid, vel); +} +void PipetteModule::zm_move_to_fix_water_level_pos_block(int32_t container_pos, container_info_t *containInfo, int32_t vbcpyid, int32_t vel) { // + zm_move_to_block(container_pos + containInfo->fix_water_level_depth, vbcpyid, vel); +} +void PipetteModule::zm_move_to_pierce_pos_block(int32_t container_pos, container_info_t *containInfo, int32_t vbcpyid, int32_t vel) { // + zm_move_to_block(container_pos + containInfo->pierce_depth, vbcpyid, vel); +} + +void PipetteModule::do_zm_move_0p() { + bool is_trigger = false; + if (!zm0p_is_trigger()) { + ZLOGI(TAG, "move to zero"); + zm_move_to_end(-1, kzm_v_move_to_zero); + zm_waitfor_zm0p_trigger_and_stop_motor(&is_trigger); + if (!is_trigger) throw zapp_exception(err::kstep_motor_not_found_point_edge); + } + + // leave from zero + if (zm0p_is_trigger()) { + ZLOGI(TAG, "leave from zero"); + zm_move_by(500 /*50mm */, kzm_v_look_zero_edge, 0); + zm_waitfor_zm0p_not_trigger_and_stop_motor(&is_trigger); + if (!is_trigger) throw zapp_exception(err::kstep_motor_not_found_point_edge); + } + + if (!zm0p_is_trigger()) { + ZLOGI(TAG, "move to zero edge again"); + zm_move_by(-100 /*10mm */, kzm_v_look_zero_edge, 0); + zm_waitfor_zm0p_trigger_and_stop_motor(&is_trigger); + if (!is_trigger) throw zapp_exception(err::kstep_motor_not_found_point_edge); + } + zm_waitfor_stop(); +} + +int32_t PipetteModule::zm_get_now_pos() { + if (zmbcfg.enable_enc == 0) { + return m_zm->getXACTUAL(); + } + return m_zm->read_enc_val(); +} +void PipetteModule::zm_set_now_pos(int32_t x) { + m_zm->setXACTUAL(x); + m_zm->set_enc_val(x); +} +void PipetteModule::zm_move_to_zero_quick_block() { + // 期望偏差 + int32_t expectation_dpos = -zmbcfg.io_trigger_append_distance + 0 + zmbcfg.dzero - zm_get_now_pos(); + int32_t startpos = zm_get_now_pos(); + if (!zm0p_is_trigger()) { + // 快速移动到零点 + // moveTo(0 + zmbcfg.dzero, zmbcfg.default_velocity); + zm_move_to(0 + zmbcfg.dzero, kzm_v_default, 0); + zm_waitfor_zm0p_trigger_and_stop_motor(NULL); + } else { + // 快速移动到零点 + zm_move_to(0 + zmbcfg.dzero, kzm_v_default, 0); + zm_waitfor_zm0p_not_trigger_and_stop_motor(NULL); + } + // 移动到零点 + do_zm_move_0p(); + + // 校验偏差 + int32_t dpos = zm_get_now_pos() - startpos; + // 设置零点 + zm_set_now_pos(0 + zmbcfg.dzero - zmbcfg.io_trigger_append_distance); + m_state.zm_has_move_zero = 1; + + if (zmbcfg.pos_devi_tolerance != 0 && (abs(expectation_dpos - dpos) > zmbcfg.pos_devi_tolerance)) { + throw zapp_exception(err::kstep_motor_lost_step); + } +} + +void PipetteModule::zm_move_to(int32_t x, int32_t vbaseindex, int32_t vel) { + /** + * @brief 以电机的参考位置为基准,向下为正向,向上为负向 + */ + ZLOGI(TAG, "zm_move_to %d", x); + if (zmbcfg.enable_enc != 0) { + m_zm->setXACTUAL(m_zm->read_enc_val()); + } + + zm_apply_vcfg(vbaseindex, vel); + m_zm->moveTo(x); +} +void PipetteModule::zm_move_to_block(int32_t x, int32_t vbaseindex, int32_t vel) { + zm_move_to(x, vbaseindex, vel); + zm_waitfor_stop(); +} +void PipetteModule::zm_move_by(int32_t dx, int32_t vindex, int32_t vel) { + ZLOGI(TAG, "zm_move_by %d %d", dx); + if (zmbcfg.enable_enc != 0) { + m_zm->setXACTUAL(m_zm->read_enc_val()); + } + zm_apply_vcfg(vindex, vel); + m_zm->moveBy(dx); +} +void PipetteModule::zm_move_by_block(int32_t dx, int32_t vindex, int32_t vel) { + zm_move_by(dx, vindex, vel); + zm_waitfor_stop(); +} + +void PipetteModule::zm_move_to_end(int32_t direction, int32_t vindex) { + if (zmbcfg.enable_enc != 0) { + m_zm->setXACTUAL(m_zm->read_enc_val()); + } + zm_apply_vcfg(vindex, 0); + m_zm->moveToEnd(direction); +} + +void PipetteModule::zm_update_dzero(int32_t dzero) { + int32_t nowabs = zm_get_now_pos() - zmbcfg.dzero; + zmbcfg.dzero = dzero; + zm_set_now_pos(nowabs + zmbcfg.dzero); +} +bool PipetteModule::zm0p_is_trigger() { return m_zm0p->getState(); } + +void PipetteModule::zm_apply_vcfg(int32_t vbasecfgindex, int32_t vel) { + ZLOGI(TAG, "zm_apply_vcfg %s", get_zm_vcpyid_name((zm_vcpyid_t)vbasecfgindex)); + /** + * @brief 当配置项的值为负数时,使用默认配置项的值 + */ + + 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); + + 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() { + m_zm->enable(false); + m_zm->setMRES((mres_type_t)zmbcfg.mres); + m_zm->setIHOLD_IRUN(zmbcfg.ihold, zmbcfg.irun, zmbcfg.iholddelay); + m_zm->setScale(zmbcfg.one_circle_pulse); + m_zm->setScaleDenominator(zmbcfg.one_circle_pulse_denominator); + m_zm->setMotorShaft(zmbcfg.shaft); + m_zm->setGlobalScale(zmbcfg.iglobalscaler); + 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); + } +} + +void PipetteModule::zm_waitfor_zm0p_trigger_and_stop_motor(bool *triggerEdge) { + if (triggerEdge) *triggerEdge = true; + while (!zm0p_is_trigger()) { + if (m_zm->isStoped()) { + ZLOGI(TAG, "motor stop first....."); + if (triggerEdge) *triggerEdge = false; + break; + } + thread_delay(1); + } + + // 停止电机 + m_zm->stop(); + // 等待电机停止 + while (!m_zm->isStoped()) { + thread_delay(10); + } +} + +void PipetteModule::zm_waitfor_zm0p_not_trigger_and_stop_motor(bool *triggerEdge) { + // 等待触发 + if (triggerEdge) *triggerEdge = true; + while (zm0p_is_trigger()) { + if (m_zm->isStoped()) { + ZLOGI(TAG, "motor stop first....."); + if (triggerEdge) *triggerEdge = false; + } + thread_delay(1); + } + + // 停止电机 + m_zm->stop(); + // 等待电机停止 + while (!m_zm->isStoped()) thread_delay(2); +} +void PipetteModule::zm_stop() { + // 停止电机 + m_zm->stop(); + // 等待电机停止 + while (!m_zm->isStoped()) thread_delay(2); +} + +void PipetteModule::zm_waitfor_stop() { + while (!m_zm->isStoped()) thread_delay(1); +} \ No newline at end of file diff --git a/sdk/components/zcan_protocol_parser/zcan_protocol_parser.cpp b/sdk/components/zcan_protocol_parser/zcan_protocol_parser.cpp index a5f13b7..3ae87d7 100644 --- a/sdk/components/zcan_protocol_parser/zcan_protocol_parser.cpp +++ b/sdk/components/zcan_protocol_parser/zcan_protocol_parser.cpp @@ -189,6 +189,8 @@ void ZCanProtocolParser::initialize(ZCanReceiver* cancmder) { REGFN(pipette_get_sensor_sample_data); REGFN(pipette_get_sensor_sample_data_num); REGFN(pipette_read_state); + REGFN(pipette_pump_distribu_all_set_param); + REGFN(pipette_pump_distribu_all); REGFN(pipette_zmotor_read_pos); REGFN(pipette_zmotor_read_enc_pos); @@ -199,6 +201,14 @@ void ZCanProtocolParser::initialize(ZCanReceiver* cancmder) { REGFN(pipette_test_pump_move_to_x100nl); REGFN(pipette_test_lld); + REGFN(pipette_test_move_to_container_bottom); + REGFN(pipette_test_move_to_container_bottom_section_begin); + REGFN(pipette_test_move_to_immersion_pos); + REGFN(pipette_test_move_to_leaving_height_pos); + REGFN(pipette_test_move_to_jet_pos); + REGFN(pipette_test_move_to_lld_start_search_pos); + REGFN(pipette_test_move_to_fix_water_level_pos); + REGFN(pipette_test_move_to_pierce_pos); } void ZCanProtocolParser::_registerModule(uint16_t id, ZIModule* module) { m_modulers[id] = module; } void ZCanProtocolParser::registerModule(ZIModule* module) { _registerModule(module->getid(), module); } @@ -1168,7 +1178,15 @@ int32_t ZCanProtocolParser::pipette_read_capacitance(cmdcontxt_t* cxt) { cxt->acklen = 4; return module->pipette_read_capacitance(&ack[0]); } +int32_t ZCanProtocolParser::pipette_pump_distribu_all_set_param(cmdcontxt_t* cxt) { + CHECK_AND_GET_MODULE(2); + return module->pipette_pump_distribu_all_set_param((distribu_all_paramid_t)cxt->params[0], cxt->params[1]); +} +int32_t ZCanProtocolParser::pipette_pump_distribu_all(cmdcontxt_t* cxt) { + CHECK_AND_GET_MODULE(0); + return module->pipette_pump_distribu_all(); +} // 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 @@ -1182,4 +1200,44 @@ int32_t ZCanProtocolParser::pipette_test_lld(cmdcontxt_t* cxt) { return module->pipette_test_lld(cxt->params[0], cxt->params[1], cxt->params[2]); } +int32_t ZCanProtocolParser::pipette_test_move_to_container_bottom(cmdcontxt_t* cxt) { + CHECK_AND_GET_MODULE(2); + return module->pipette_test_move_to_container_bottom(cxt->params[0], cxt->params[1]); +} + +int32_t ZCanProtocolParser::pipette_test_move_to_container_bottom_section_begin(cmdcontxt_t* cxt) { + CHECK_AND_GET_MODULE(2); + return module->pipette_test_move_to_container_bottom_section_begin(cxt->params[0], cxt->params[1]); +} + +int32_t ZCanProtocolParser::pipette_test_move_to_immersion_pos(cmdcontxt_t* cxt) { + CHECK_AND_GET_MODULE(2); + return module->pipette_test_move_to_immersion_pos(cxt->params[0], cxt->params[1]); +} + +int32_t ZCanProtocolParser::pipette_test_move_to_leaving_height_pos(cmdcontxt_t* cxt) { + CHECK_AND_GET_MODULE(2); + return module->pipette_test_move_to_leaving_height_pos(cxt->params[0], cxt->params[1]); +} + +int32_t ZCanProtocolParser::pipette_test_move_to_jet_pos(cmdcontxt_t* cxt) { + CHECK_AND_GET_MODULE(2); + return module->pipette_test_move_to_jet_pos(cxt->params[0], cxt->params[1]); +} + +int32_t ZCanProtocolParser::pipette_test_move_to_lld_start_search_pos(cmdcontxt_t* cxt) { + CHECK_AND_GET_MODULE(2); + return module->pipette_test_move_to_lld_start_search_pos(cxt->params[0], cxt->params[1]); +} + +int32_t ZCanProtocolParser::pipette_test_move_to_fix_water_level_pos(cmdcontxt_t* cxt) { + CHECK_AND_GET_MODULE(2); + return module->pipette_test_move_to_fix_water_level_pos(cxt->params[0], cxt->params[1]); +} + +int32_t ZCanProtocolParser::pipette_test_move_to_pierce_pos(cmdcontxt_t* cxt) { + CHECK_AND_GET_MODULE(2); + return module->pipette_test_move_to_pierce_pos(cxt->params[0], cxt->params[1]); +} + #undef MODULE_CLASS \ No newline at end of file diff --git a/sdk/components/zcan_protocol_parser/zcan_protocol_parser.hpp b/sdk/components/zcan_protocol_parser/zcan_protocol_parser.hpp index 906bfab..587557c 100644 --- a/sdk/components/zcan_protocol_parser/zcan_protocol_parser.hpp +++ b/sdk/components/zcan_protocol_parser/zcan_protocol_parser.hpp @@ -218,8 +218,19 @@ class ZCanProtocolParser : public IZCanRxProcesser { CMDFN(pipette_read_pressure); CMDFN(pipette_read_capacitance); + CMDFN(pipette_pump_distribu_all_set_param); + CMDFN(pipette_pump_distribu_all); + CMDFN(pipette_test_pump_move_to_x100nl); CMDFN(pipette_test_lld); + CMDFN(pipette_test_move_to_container_bottom); + CMDFN(pipette_test_move_to_container_bottom_section_begin); + CMDFN(pipette_test_move_to_immersion_pos); + CMDFN(pipette_test_move_to_leaving_height_pos); + CMDFN(pipette_test_move_to_jet_pos); + CMDFN(pipette_test_move_to_lld_start_search_pos); + CMDFN(pipette_test_move_to_fix_water_level_pos); + CMDFN(pipette_test_move_to_pierce_pos); }; } // namespace iflytop \ No newline at end of file diff --git a/usrc/a8000_protocol/protocol/cmdid.cpp b/usrc/a8000_protocol/protocol/cmdid.cpp index 95b04f1..5aba2c7 100644 --- a/usrc/a8000_protocol/protocol/cmdid.cpp +++ b/usrc/a8000_protocol/protocol/cmdid.cpp @@ -163,9 +163,19 @@ static cmdinfo_t table[] = { CMD_ITERM(kpipette_read_tip_state), CMD_ITERM(kpipette_read_pressure), CMD_ITERM(kpipette_read_capacitance), + CMD_ITERM(kpipette_pump_distribu_all_set_param), + CMD_ITERM(kpipette_pump_distribu_all), CMD_ITERM(kpipette_test_pump_move_to_x100nl), CMD_ITERM(kpipette_test_lld), + CMD_ITERM(kpipette_test_move_to_container_bottom), + CMD_ITERM(kpipette_test_move_to_container_bottom_section_begin), + CMD_ITERM(kpipette_test_move_to_immersion_pos), + CMD_ITERM(kpipette_test_move_to_leaving_height_pos), + CMD_ITERM(kpipette_test_move_to_jet_pos), + CMD_ITERM(kpipette_test_move_to_lld_start_search_pos), + CMD_ITERM(kpipette_test_move_to_fix_water_level_pos), + CMD_ITERM(kpipette_test_move_to_pierce_pos), }; const char* cmdid2str(int32_t code) { diff --git a/usrc/a8000_protocol/protocol/cmdid.hpp b/usrc/a8000_protocol/protocol/cmdid.hpp index 15e018d..05905db 100644 --- a/usrc/a8000_protocol/protocol/cmdid.hpp +++ b/usrc/a8000_protocol/protocol/cmdid.hpp @@ -161,23 +161,33 @@ typedef enum { kpipette_zmotor_read_pos = 0x7509, kpipette_zmotor_read_enc_pos = 0x750A, - kpipette_pump_init_device = 0x7580, - kpipette_pump_take_tip = 0x7581, - kpipette_pump_deposit_tip = 0x7582, - kpipette_pump_pierce_through = 0x7583, - kpipette_pump_aspirate_set_param = 0x7584, - kpipette_pump_aspirate = 0x7585, - kpipette_pump_distribu = 0x7586, - kpipette_get_sensor_sample_data = 0x7587, - kpipette_get_sensor_sample_data_num = 0x7588, - kpipette_read_state = 0x7589, // {index}, ack:{state} - kpipette_pump_putbak_tip = 0x758A, // - kpipette_read_tip_state = 0x758B, // ack:{state} - 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 + kpipette_pump_init_device = 0x7580, + kpipette_pump_take_tip = 0x7581, + kpipette_pump_deposit_tip = 0x7582, + kpipette_pump_pierce_through = 0x7583, + kpipette_pump_aspirate_set_param = 0x7584, + kpipette_pump_aspirate = 0x7585, + kpipette_pump_distribu = 0x7586, + kpipette_get_sensor_sample_data = 0x7587, + kpipette_get_sensor_sample_data_num = 0x7588, + kpipette_read_state = 0x7589, // {index}, ack:{state} + kpipette_pump_putbak_tip = 0x758A, // + kpipette_read_tip_state = 0x758B, // ack:{state} + kpipette_read_pressure = 0x758C, // ack:{state} + kpipette_read_capacitance = 0x758D, // ack:{state} + kpipette_pump_distribu_all_set_param = 0x758E, // {paramid,val}, ack:{} + kpipette_pump_distribu_all = 0x758F, // {}, ack:{} + + 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 + kpipette_test_move_to_container_bottom = 0x7602, // int32_t container_pos, int32_t container_cpyid, + kpipette_test_move_to_container_bottom_section_begin = 0x7603, // int32_t container_pos, int32_t container_cpyid, + kpipette_test_move_to_immersion_pos = 0x7604, // int32_t container_pos, int32_t container_cpyid, + kpipette_test_move_to_leaving_height_pos = 0x7605, // int32_t container_pos, int32_t container_cpyid, + kpipette_test_move_to_jet_pos = 0x7606, // int32_t container_pos, int32_t container_cpyid, + kpipette_test_move_to_lld_start_search_pos = 0x7607, // int32_t container_pos, int32_t container_cpyid, + kpipette_test_move_to_fix_water_level_pos = 0x7608, // int32_t container_pos, int32_t container_cpyid, + kpipette_test_move_to_pierce_pos = 0x7609, // int32_t container_pos, int32_t container_cpyid, } cmdid_t; diff --git a/usrc/a8000_protocol/protocol/errorcode.cpp b/usrc/a8000_protocol/protocol/errorcode.cpp index 397e919..a0439d5 100644 --- a/usrc/a8000_protocol/protocol/errorcode.cpp +++ b/usrc/a8000_protocol/protocol/errorcode.cpp @@ -93,6 +93,8 @@ static ecode_table_item_t table[] = { ERR_ITERM(kstep_motor_subic_init_fail), ERR_ITERM(kstep_motor_subic_offline), ERR_ITERM(kpipette_pm_positioning_abnormality), + ERR_ITERM(kpipette_no_liquid_in_it), + }; diff --git a/usrc/a8000_protocol/protocol/errorcode.hpp b/usrc/a8000_protocol/protocol/errorcode.hpp index 81ff19e..136c630 100644 --- a/usrc/a8000_protocol/protocol/errorcode.hpp +++ b/usrc/a8000_protocol/protocol/errorcode.hpp @@ -71,6 +71,7 @@ typedef enum { kpipette_lld_error_no_liquid_detected = 1504, kpipette_lld_error_pump_reach_max_pos = 1505, kpipette_pm_positioning_abnormality = 1506, // 电机定位异常 + kpipette_no_liquid_in_it = 1507, // 泵内无液体 kstep_motor_not_found_zero_point = 1600, kstep_motor_not_go_zero = 1601,