|
|
@ -5,9 +5,9 @@ |
|
|
|
#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; |
|
|
@ -22,27 +22,71 @@ void PipetteModule::initialize(int32_t id, hardward_config_t *hardwaredcfg) { / |
|
|
|
m_zm = hardwaredcfg->zmotor; |
|
|
|
m_zm0p = hardwaredcfg->zmotor_0point; |
|
|
|
|
|
|
|
// m_smtp2.pump_init(zm_default_cfg.pump_vmax);
|
|
|
|
// osDelay(3000);
|
|
|
|
// m_smtp2.write_cmd("/1?23R\r");
|
|
|
|
|
|
|
|
m_zm->getGState(); // 读取状态,清空下复位标识
|
|
|
|
m_piette_gun_io1.initAsInput(hardwaredcfg->IO1, ZGPIO::kMode_pullup, ZGPIO::kIRQ_noIrq, hardwaredcfg->IO1Mirror); |
|
|
|
|
|
|
|
// ZASSERT(hardwaredcfg->uart232);
|
|
|
|
// EXHAL_UART_BindUart("pipette-uart232", hardwaredcfg->uart232);
|
|
|
|
// EXHAL_UART_RegListener(hardwaredcfg->uart232, [this](UART_HandleTypeDef *huart, uint8_t *data, size_t len) {
|
|
|
|
// printf("!rx(%d): ", len);
|
|
|
|
// if (len > 0) {
|
|
|
|
// printf("%c", data[0]);
|
|
|
|
// }
|
|
|
|
// printf("\n");
|
|
|
|
// });
|
|
|
|
// EXHAL_UART_ITStartAutoRead(hardwaredcfg->uart232);
|
|
|
|
m_smtp2.pump_set_pressure_data_stream_port(0); //
|
|
|
|
// EXHAL_UART_BindUart("pipette-uart", hardwaredcfg->uart);
|
|
|
|
// EXHAL_UART_RegListener(hardwaredcfg->uart, [this](UART_HandleTypeDef *huart, uint8_t *data, size_t len) {
|
|
|
|
// printf("!rx(%d): ", len);
|
|
|
|
// for (size_t i = 0; i < len; i++) {
|
|
|
|
// printf("%c", data[i]);
|
|
|
|
// }
|
|
|
|
// printf("\n");
|
|
|
|
// });
|
|
|
|
// EXHAL_UART_DMAStartAutoRead(hardwaredcfg->uart);
|
|
|
|
// EXHAL_UART_TransmitStringBlock(hardwaredcfg->uart, "/1QR\r");
|
|
|
|
// HAL_Delay(1000);
|
|
|
|
// EXHAL_UART_TransmitStringBlock(hardwaredcfg->uart232, "/1QR\r");
|
|
|
|
|
|
|
|
test_connectivity(); |
|
|
|
parameter_init(); |
|
|
|
} |
|
|
|
|
|
|
|
void PipetteModule::test_connectivity() { |
|
|
|
bool io1_connected = false; |
|
|
|
bool io1_reverse = false; |
|
|
|
bool uart485_connected = false; |
|
|
|
bool uart232_connected = false; |
|
|
|
|
|
|
|
//! TODO: 将初始化代码移动到模块外部
|
|
|
|
m_piette_gun_io1.initAsInput(PB1, ZGPIO::kMode_pullup, ZGPIO::kIRQ_noIrq, true); // lld输入高
|
|
|
|
uart485_connected = m_smtp2.pump_ping(); |
|
|
|
|
|
|
|
//! 测试IO1是否联通
|
|
|
|
m_smtp2.pump_set_io1_mode(2); // lld输入高
|
|
|
|
m_smtp2.pump_set_io1_state(0); |
|
|
|
osDelay(100); |
|
|
|
ZLOGI(TAG, "read io1 state:%d", m_piette_gun_io1.getState()); |
|
|
|
|
|
|
|
m_smtp2.pump_set_io1_state(1); // lld输入高
|
|
|
|
osDelay(100); |
|
|
|
ZLOGI(TAG, "read io1 state:%d", m_piette_gun_io1.getState()); |
|
|
|
m_smtp2.pump_set_io1_mode(0); // lld输入高
|
|
|
|
if (uart485_connected) { |
|
|
|
// 设置IO1为通用输出模式
|
|
|
|
m_smtp2.pump_set_io1_mode(2); |
|
|
|
|
|
|
|
parameter_init(); |
|
|
|
// 设置IO1为低电平
|
|
|
|
m_smtp2.pump_set_io1_state(0); |
|
|
|
osDelay(2); |
|
|
|
bool io1_state1 = m_piette_gun_io1.getState(); |
|
|
|
|
|
|
|
// 设置IO1为高电平
|
|
|
|
m_smtp2.pump_set_io1_state(1); // lld输入高
|
|
|
|
osDelay(2); |
|
|
|
bool io1_state2 = m_piette_gun_io1.getState(); |
|
|
|
io1_connected = (!io1_state1 && io1_state2) || (io1_state1 && !io1_state2); |
|
|
|
io1_reverse = io1_state1 && !io1_state2; |
|
|
|
} |
|
|
|
|
|
|
|
//! 测试232是否联通
|
|
|
|
uart232_connected = false; |
|
|
|
|
|
|
|
ZLOGI(TAG, "===================== connectivity test report =========================="); |
|
|
|
ZLOGI(TAG, "= uart485_connected :%d", uart485_connected); |
|
|
|
ZLOGI(TAG, "= io1_connected :%d(%s)", io1_connected, io1_reverse ? "Err:Reverse" : ""); |
|
|
|
ZLOGI(TAG, "= uart232_connected :%d", uart232_connected); |
|
|
|
ZLOGI(TAG, "="); |
|
|
|
} |
|
|
|
|
|
|
|
int32_t PipetteModule::module_stop() { |
|
|
@ -129,11 +173,11 @@ int32_t PipetteModule::pipette_set_platinfo(int32_t cpyid, platinfo_index_t inde |
|
|
|
platinfo_t *platinfo = &m_platinfo[cpyid]; |
|
|
|
|
|
|
|
switch (index) { |
|
|
|
SET_CFG(kplatinfo_work_ref_plane, platinfo->work_ref_plane, val); |
|
|
|
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_deposit_pos, platinfo->tip_deposit_pos, val); |
|
|
|
// SET_CFG(kplatinfo_transform_pos, platinfo->transform_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); |
|
|
|
default: { |
|
|
@ -151,11 +195,11 @@ int32_t PipetteModule::pipette_get_platinfo(int32_t cpyid, platinfo_index_t inde |
|
|
|
|
|
|
|
platinfo_t *platinfo = &m_platinfo[cpyid]; |
|
|
|
switch (index) { |
|
|
|
GET_CFG(kplatinfo_work_ref_plane, platinfo->work_ref_plane, val); |
|
|
|
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_deposit_pos, platinfo->tip_deposit_pos, val); |
|
|
|
// GET_CFG(kplatinfo_transform_pos, platinfo->transform_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); |
|
|
|
default: { |
|
|
@ -311,6 +355,7 @@ int32_t PipetteModule::pipette_set_liquid_info(int32_t cpyid, liquid_info_index_ |
|
|
|
switch (index) { |
|
|
|
SET_CFG(kliquid_info_plld_pm_vindex, cfg->plld_pm_vindex, 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_vindex, cfg->empty_tip_pm_vindex, val); |
|
|
|
SET_CFG(kliquid_info_blowout_air_volume, cfg->blowout_air_volume, val); |
|
|
|
SET_CFG(kliquid_info_blowout_air_pm_vindex, cfg->blowout_air_pm_vindex, val); |
|
|
@ -343,6 +388,7 @@ int32_t PipetteModule::pipette_get_liquid_info(int32_t cpyid, liquid_info_index_ |
|
|
|
switch (index) { |
|
|
|
GET_CFG(kliquid_info_plld_pm_vindex, cfg->plld_pm_vindex, 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_vindex, cfg->empty_tip_pm_vindex, val); |
|
|
|
GET_CFG(kliquid_info_blowout_air_volume, cfg->blowout_air_volume, val); |
|
|
|
GET_CFG(kliquid_info_blowout_air_pm_vindex, cfg->blowout_air_pm_vindex, val); |
|
|
@ -658,7 +704,7 @@ int32_t PipetteModule::pipette_pump_aspirate() { |
|
|
|
if (acfg->lld_type != 0) { |
|
|
|
_do_lld(platform_info, container_cfg, liquidinfo, acfg); |
|
|
|
} else { |
|
|
|
m_state.water_level = platform_info->work_ref_plane - container_cfg->container_neck_pos + container_cfg->fix_aspiration_depth; |
|
|
|
m_state.water_level = container_cfg->container_neck_pos + container_cfg->fix_aspiration_depth; |
|
|
|
ZLOGI(TAG, "lld isn't enable,use fix depth %d", m_state.water_level); |
|
|
|
zm_move_to_block(m_state.water_level - 150, kzm_v_default, 0); //
|
|
|
|
pump_move_to_x100nl_block(0, liquidinfo->empty_tip_pm_vindex); // 清空tip
|
|
|
@ -680,8 +726,8 @@ void PipetteModule::_do_lld(platinfo_t *platform_info, container_info_t *contain |
|
|
|
pump_move_to_x100nl_block(0, liquidinfo->empty_tip_pm_vindex); |
|
|
|
|
|
|
|
// 移动到瓶口
|
|
|
|
zm_wp_move_to_block(platform_info, container_cfg->container_neck_pos + 50 /*5mm*/, //
|
|
|
|
kzm_v_default, 0); |
|
|
|
zm_move_to_block(container_cfg->container_neck_pos + 50 /*5mm*/, //
|
|
|
|
kzm_v_default, 0); |
|
|
|
pump_move_to_x100nl_block(0, kpm_v_default); // 回转一下,消除齿轮间隙
|
|
|
|
|
|
|
|
// 启动lld
|
|
|
@ -691,10 +737,10 @@ void PipetteModule::_do_lld(platinfo_t *platform_info, container_info_t *contain |
|
|
|
DO_IN_THREAD(m_smtp2.pump_aspirate_plld(liquidinfo->plld_threshold)); |
|
|
|
|
|
|
|
// 快速移动到瓶口
|
|
|
|
zm_wp_move_to_block(platform_info, container_cfg->container_neck_pos + container_cfg->lld_start_search_depth, //
|
|
|
|
kzm_v_default, 0); |
|
|
|
zm_move_to_block(container_cfg->container_neck_pos + container_cfg->lld_start_search_depth, //
|
|
|
|
kzm_v_default, 0); |
|
|
|
// lld,zm移动到瓶底
|
|
|
|
zm_wp_move_to(platform_info, container_cfg->container_neck_pos - container_cfg->container_depth, kzm_v_lld, 0); |
|
|
|
zm_move_to(container_cfg->container_neck_pos + container_cfg->container_depth, kzm_v_lld, liquidinfo->plld_zm_vel); |
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief 等待压力大于阈值 |
|
|
@ -770,10 +816,9 @@ void PipetteModule::_do_sapirate(platinfo_t *platform_info, container_info_t *co |
|
|
|
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_wp_move_to(platform_info, |
|
|
|
container_cfg->container_neck_pos - container_cfg->container_depth, // 瓶底
|
|
|
|
kzm_v_llf, // 基础速度配置
|
|
|
|
compute_zm_llf_vel(liquidinfo->mix_pm_vindex, container_cfg)); // 计算llf速度
|
|
|
|
zm_move_to(container_cfg->container_neck_pos + container_cfg->container_depth, // 瓶底
|
|
|
|
kzm_v_llf, // 基础速度配置
|
|
|
|
compute_zm_llf_vel(liquidinfo->mix_pm_vindex, container_cfg)); // 计算llf速度
|
|
|
|
} |
|
|
|
pump_move_by_x100nl_block(acfg->mix_volume, liquidinfo->mix_pm_vindex); |
|
|
|
if (acfg->mix_llf_enable > 0) zm_stop(); |
|
|
@ -796,10 +841,10 @@ void PipetteModule::_do_sapirate(platinfo_t *platform_info, container_info_t *co |
|
|
|
int32_t x100nl = acfg->x100nl * liquidinfo->volume_calibration_coefficient_k * 0.0001 + liquidinfo->volume_calibration_coefficient_b * 0.0001; |
|
|
|
|
|
|
|
if (acfg->llf_enable > 0) { |
|
|
|
zm_wp_move_to(platform_info, //
|
|
|
|
container_cfg->container_neck_pos - container_cfg->container_depth, // 瓶底
|
|
|
|
kzm_v_llf, //
|
|
|
|
compute_zm_llf_vel(aspiration_pm_index, container_cfg) //
|
|
|
|
zm_move_to( //
|
|
|
|
container_cfg->container_neck_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); |
|
|
@ -890,18 +935,6 @@ 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_wp_move_to(platinfo_t *platform, int32_t x, int32_t vbaseindex, int32_t vel) { |
|
|
|
/**
|
|
|
|
* @brief 以平台的参考位置为基准,向上为正向,向下为负向 |
|
|
|
*/ |
|
|
|
zm_move_to(platform->work_ref_plane - x, vbaseindex, vel); |
|
|
|
} |
|
|
|
|
|
|
|
void PipetteModule::zm_wp_move_to_block(platinfo_t *platform, int32_t x, int32_t vbaseindex, int32_t vel) { |
|
|
|
zm_wp_move_to(platform, 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 (zm_base_cfg.enable_enc != 0) { |
|
|
@ -1302,7 +1335,7 @@ void PipetteModule::parameter_init() { |
|
|
|
* m_platinfo * |
|
|
|
***********************************************************************************************************************/ |
|
|
|
for (int32_t i = 0; i < ARRARY_SIZE(m_platinfo); i++) { |
|
|
|
m_platinfo[i].work_ref_plane = 0; |
|
|
|
m_platinfo[i].work_ref_pos = 0; |
|
|
|
m_platinfo[i].tip_picking_pos = 0; |
|
|
|
m_platinfo[i].tip_picking_search_range = 0; |
|
|
|
m_platinfo[i].tip_deposit_pos = 0; |
|
|
@ -1383,6 +1416,7 @@ void PipetteModule::parameter_init() { |
|
|
|
for (int32_t i = 0; i < ARRARY_SIZE(m_liquid_info); i++) { |
|
|
|
m_liquid_info[i].plld_pm_vindex = kpm_v_lld; |
|
|
|
m_liquid_info[i].plld_threshold = 30; |
|
|
|
m_liquid_info[i].plld_zm_vel = 0; |
|
|
|
m_liquid_info[i].empty_tip_pm_vindex = kpm_v_max; |
|
|
|
m_liquid_info[i].blowout_air_volume = 0; |
|
|
|
m_liquid_info[i].blowout_air_pm_vindex = kpm_v_quick; |
|
|
|