From e37fe84bc723995cbf92f2c838b695060168a327 Mon Sep 17 00:00:00 2001 From: zhaohe Date: Tue, 11 Jun 2024 15:39:36 +0800 Subject: [PATCH] update --- .../pipette_module/pipette_ctrl_module_v2.cpp | 74 +++++---- .../pipette_module/pipette_ctrl_module_v2.hpp | 26 ++-- components/sensors/smtp2_v2/smtp2_v2.cpp | 99 ++++++++++++ components/sensors/smtp2_v2/smtp2_v2.hpp | 167 +++++++++++++++++++++ components/zcancmder/zcan_protocol_parser.cpp | 10 ++ components/zcancmder/zcan_protocol_parser.hpp | 1 + 6 files changed, 335 insertions(+), 42 deletions(-) create mode 100644 components/sensors/smtp2_v2/smtp2_v2.cpp create mode 100644 components/sensors/smtp2_v2/smtp2_v2.hpp diff --git a/components/pipette_module/pipette_ctrl_module_v2.cpp b/components/pipette_module/pipette_ctrl_module_v2.cpp index 88e21ab..05cd733 100644 --- a/components/pipette_module/pipette_ctrl_module_v2.cpp +++ b/components/pipette_module/pipette_ctrl_module_v2.cpp @@ -19,7 +19,7 @@ void PipetteModule::initialize(int32_t id, config_t *config, hardward_config_t * ZASSERT(hardwaredcfg != nullptr); m_id = id; m_config = *config; - m_smtp2.initialize(hardwaredcfg->uart, hardwaredcfg->hdma_rx, hardwaredcfg->hdma_tx); + m_smtp2.initialize(hardwaredcfg->uart, 0, hardwaredcfg->hdma_rx, hardwaredcfg->hdma_tx); m_thread.init("pipette_ctrl", 1024); } @@ -44,8 +44,6 @@ int32_t PipetteModule::module_break() { return 0; } - - int32_t PipetteModule::module_xxx_reg(int32_t param_id, bool read, int32_t &val) { switch (param_id) { MODULE_COMMON_PROCESS_REG_CB(); @@ -66,7 +64,7 @@ int32_t PipetteModule::module_get_status(int32_t *status) { if (ecode != 0) { creg.module_errorcode = ecode; - *status = 3; + *status = 3; m_thread.stop(); return 0; } @@ -84,16 +82,16 @@ int32_t PipetteModule::module_get_status(int32_t *status) { int32_t PipetteModule::pipette_ctrl_init_device() { ZLOGI(TAG, "pipette_ctrl_init_device"); - if (!m_smtp2.isOnline()) return err::kdevice_offline; - m_thread.stop(); - m_thread.start([this]() { DO("init_device_block", m_smtp2.init_device_block()); }); + // if (!m_smtp2.isOnline()) return err::kdevice_offline; + // m_thread.stop(); + // m_thread.start([this]() { DO("init_device_block", m_smtp2.init_device_block()); }); return 0; }; int32_t PipetteModule::pipette_ctrl_put_tip() { ZLOGI(TAG, "pipette_ctrl_put_tip"); - if (!m_smtp2.isOnline()) return err::kdevice_offline; - m_thread.stop(); - m_thread.start([this]() { DO("put_tip_block", m_smtp2.put_tip_block()); }); + // if (!m_smtp2.isOnline()) return err::kdevice_offline; + // m_thread.stop(); + // m_thread.start([this]() { DO("put_tip_block", m_smtp2.put_tip_block()); }); return 0; }; int32_t PipetteModule::pipette_ctrl_move_to_ul(int32_t ul) { @@ -102,33 +100,51 @@ int32_t PipetteModule::pipette_ctrl_move_to_ul(int32_t ul) { return err::kparam_out_of_range; } - if (!m_smtp2.isOnline()) return err::kdevice_offline; - m_thread.stop(); - m_thread.start([this, ul]() { DO("move_to_ul_block", m_smtp2.move_to_ul_block(ul)); }); + // if (!m_smtp2.isOnline()) return err::kdevice_offline; + // m_thread.stop(); + // m_thread.start([this, ul]() { DO("move_to_ul_block", m_smtp2.move_to_ul_block(ul)); }); return 0; }; +int32_t PipetteModule::pipette_write_cmd_direct(uint8_t *tx, int32_t len, uint8_t *rx, int32_t *rxlen) { + bool suc = m_smtp2.write_cmd((char *)tx); + if (!suc) { + return err::ksubdevice_overtime; + } + m_smtp2.getack((char *)rx, rxlen); + return 0; +} + /******************************************************************************* * PRIVATE * *******************************************************************************/ -int32_t PipetteModule::read_pos_ul(int32_t *val) { return m_smtp2.read_pos_ul(*val); } -int32_t PipetteModule::read_capactitance(int32_t *val) { return m_smtp2.read_capacitance_val(*val); } +int32_t PipetteModule::read_pos_ul(int32_t *val) { + return 0; + // return m_smtp2.read_pos_ul(*val); +} +int32_t PipetteModule::read_capactitance(int32_t *val) { + return 0; + // return m_smtp2.read_capacitance_val(*val); +} int32_t PipetteModule::read_tip_state(int32_t *val) { - bool tipstate = false; - int32_t ecode = m_smtp2.read_tip_state(tipstate); - *val = tipstate ? 1 : 0; - return ecode; + *val = 0; + return 0; + // bool tipstate = false; + // int32_t ecode = m_smtp2.read_tip_state(tipstate); + // *val = tipstate ? 1 : 0; + // return ecode; } int32_t PipetteModule::_read_error_status() { - bool isbusy = false; - err::error_t errorcode = err::ksucc; - int32_t retecode = m_smtp2.getState(isbusy, errorcode); - if (retecode != 0) { - return retecode; - } - if (errorcode != err::ksucc && errorcode != err::kSMTP2_NoError) { - return errorcode; - } - return 0; + // bool isbusy = false; + // err::error_t errorcode = err::ksucc; + // int32_t retecode = m_smtp2.getState(isbusy, errorcode); + // if (retecode != 0) { + // return retecode; + // } + // if (errorcode != err::ksucc && errorcode != err::kSMTP2_NoError) { + // return errorcode; + // } + + // return 0; } diff --git a/components/pipette_module/pipette_ctrl_module_v2.hpp b/components/pipette_module/pipette_ctrl_module_v2.hpp index e7b4821..25fc3c5 100644 --- a/components/pipette_module/pipette_ctrl_module_v2.hpp +++ b/components/pipette_module/pipette_ctrl_module_v2.hpp @@ -1,8 +1,8 @@ #pragma once // -#include "sdk/os/zos.hpp" -#include "sdk\components\sensors\smtp2\smtp2.hpp" #include "a8000_protocol\protocol.hpp" +#include "sdk/os/zos.hpp" +#include "sdk\components\sensors\smtp2_v2\smtp2_v2.hpp" // #include "StepMotorCtrlModule" /** @@ -14,7 +14,7 @@ namespace iflytop { class PipetteModule : public ZIModule, public ZIPipetteCtrlModule { - ENABLE_MODULE(PipetteModule, kpipette_ctrl_module,PC_VERSION); + ENABLE_MODULE(PipetteModule, kpipette_ctrl_module, PC_VERSION); public: typedef struct { @@ -28,10 +28,10 @@ class PipetteModule : public ZIModule, public ZIPipetteCtrlModule { } config_t; private: - SMTP2 m_smtp2; - ZThread m_thread; + smtp2::SMTP2V2 m_smtp2; + ZThread m_thread; - int32_t m_id = 0; + int32_t m_id = 0; config_t m_config; public: @@ -43,9 +43,9 @@ class PipetteModule : public ZIModule, public ZIPipetteCtrlModule { * Module * *******************************************************************************/ - virtual int32_t module_enable(int32_t enable) ; - virtual int32_t module_stop() ; - virtual int32_t module_break() ; + virtual int32_t module_enable(int32_t enable); + virtual int32_t module_stop(); + virtual int32_t module_break(); virtual int32_t module_get_status(int32_t *status) override; @@ -56,12 +56,12 @@ class PipetteModule : public ZIModule, public ZIPipetteCtrlModule { virtual int32_t pipette_ctrl_init_device() override; virtual int32_t pipette_ctrl_put_tip() override; virtual int32_t pipette_ctrl_move_to_ul(int32_t ul) override; + virtual int32_t pipette_write_cmd_direct(uint8_t *tx, int32_t len, uint8_t *rx, int32_t *rxlen) override; private: - - int32_t read_pos_ul(int32_t *val); - int32_t read_capactitance(int32_t *val); - int32_t read_tip_state(int32_t *val); + int32_t read_pos_ul(int32_t *val); + int32_t read_capactitance(int32_t *val); + int32_t read_tip_state(int32_t *val); virtual int32_t module_xxx_reg(int32_t param_id, bool read, int32_t &val) override; private: diff --git a/components/sensors/smtp2_v2/smtp2_v2.cpp b/components/sensors/smtp2_v2/smtp2_v2.cpp new file mode 100644 index 0000000..f98b6f9 --- /dev/null +++ b/components/sensors/smtp2_v2/smtp2_v2.cpp @@ -0,0 +1,99 @@ +#include "smtp2_v2.hpp" + +#include +#include +#include +#include + +#include "a8000_protocol\protocol.hpp" +using namespace iflytop; +using namespace smtp2; +#define TAG "SMTP2" + +#define OVERTIME 30 +#define DUMP_HEX 1 + +void SMTP2V2::initialize(UART_HandleTypeDef* uart, uint8_t id, DMA_HandleTypeDef* hdma_rx, DMA_HandleTypeDef* hdma_tx) { + m_uart = uart; + m_hdma_rx = hdma_rx; + m_hdma_tx = hdma_tx; + m_id = id; +} + +void SMTP2V2::pump_init_cfg() {} +void SMTP2V2::pump_ping() {} + +bool SMTP2V2::write_cmd(const char* cmd) { return sendcmd(cmd); } +void SMTP2V2::getack(char* rx, int32_t* rxbufsize) { + *rxbufsize = m_rxNum; + memcpy(rx, m_rxbuf, m_rxNum); +} +/*********************************************************************************************************************** + * BASIC * + ***********************************************************************************************************************/ +int32_t SMTP2V2::getAckEcode() { + if (m_rxNum < 3) { + return err::kdevice_is_offline; + } + uint8_t errorcode = (uint8_t)m_rxbuf[2]; + if (errorcode >= '`') { + errorcode = errorcode - '`'; + } else if (errorcode >= '@') { + errorcode = errorcode - '@'; + } + return (err::error_t)errorcode; +} + +bool SMTP2V2::sendcmd(const char* cmd) { + for (size_t i = 0; i < 5; i++) { + if (_sendcmd(cmd)) { + break; + } + m_rxNum = 0; + return false; + } + return true; +} +bool SMTP2V2::_sendcmd(const char* cmd) { +#ifdef DUMP_HEX + ZLOGI(TAG, "tx:%s", cmd); +#endif + + bool ret = _sendcmd_dma(cmd); + +#ifdef DUMP_HEX + ZLOGI(TAG, "rx:%s", m_rxbuf); +#endif + + return ret; +} + +bool SMTP2V2::_sendcmd_dma(const char* cmd) { + memset(m_rxbuf, 0, SMTP2_BUF_LEN); + uint8_t rxdata; + // clear rx buf + while (HAL_UART_Receive(m_uart, &rxdata, 1, 1) == HAL_OK) { + } + + uint32_t enter_ticket = HAL_GetTick(); + HAL_UARTEx_ReceiveToIdle_DMA(m_uart, (uint8_t*)m_rxbuf, SMTP2_BUF_LEN); + + HAL_UART_Transmit(m_uart, (uint8_t*)cmd, strlen(cmd), 1000); + + bool overtime_flag = false; + while (HAL_UART_GetState(m_uart) == HAL_UART_STATE_BUSY_RX || // + HAL_UART_GetState(m_uart) == HAL_UART_STATE_BUSY_TX_RX) { + osDelay(1); + if (zos_haspassedms(enter_ticket) > OVERTIME) { + // ZLOGW(TAG, "sendcmd_dma overtime"); + overtime_flag = true; + break; + } + } + HAL_UART_DMAStop(m_uart); + if (overtime_flag) { + return false; + } + m_rxNum = SMTP2_BUF_LEN - __HAL_DMA_GET_COUNTER(m_hdma_rx); + return true; +} \ No newline at end of file diff --git a/components/sensors/smtp2_v2/smtp2_v2.hpp b/components/sensors/smtp2_v2/smtp2_v2.hpp new file mode 100644 index 0000000..0a90490 --- /dev/null +++ b/components/sensors/smtp2_v2/smtp2_v2.hpp @@ -0,0 +1,167 @@ +#pragma once +#include "a8000_protocol\protocol.hpp" +#include "sdk\os\zos.hpp" +namespace iflytop { +using namespace std; + +/** + * @brief + * + * ref:https://iflytop1.feishu.cn/wiki/VNNRwUJCtiuRDHkD1uScGIA1nMf + * WARNING: + * 1,发送消息有一定概率失败,目前没有找到原因,暂时通过重发解决,一般重发一次,即可发送成功。 + */ + +namespace smtp2 { + +#define SMTP2_BUF_LEN 128 + +typedef enum { + kcmd_pump_init, // [Z]初始化 + kcmd_pump_move_to, // A + kcmd_pump_move_by_absorb, // P相对吸取 + kcmd_pump_move_by_distribut, // D相对分配 + kcmd_pump_set_acc_and_dec, // L,设置加速度,和减速度 + kcmd_pump_set_start_v, // v + kcmd_pump_set_max_v, // V + kcmd_pump_set_stop_v, // c + kcmd_pump_set_back_clearance_increment, // K背隙增量 + kcmd_pump_set_increment_mode, // N选择增量模式 0 正常模式,1 微增量模式 2 纳升 + kcmd_pump_stop, // H + kcmd_pump_clear_cmd_buf, // C 清除命令缓冲区 + kcmd_pump_pop_tip, // E弹出 Tip + kcmd_pump_pLLD, // t, + kcmd_pump_cLLD, // ^ + kcmd_pump_mixLLD, // B, + kcmd_pump_set_pressure_gain, //

设定压力传感器增益 + kcmd_pump_verify_operation, // q,操作验证 + kcmd_pump_reset, // "!0" + kcmd_pump_factory_reset, // "!22" +} cmd_t; + +typedef enum { + + kcfg_pump_limit_ul = 1, // 最大行程(Tip尺寸) 1...3500 default:3143 + kcfg_baudrate = 2, // 0:9600 1:38400 default:1 + kcfg_communication_protocol = 3, + kcfg_pressure_data_port_channel = 4, // 压力数据流端口 0=无 1=RS232 3=CAN + kcfg_can_enable = 5, // CAN总线使能 + kcfg_can_baudrate = 6, // CAN总线波特率 + kcfg_back_clearance_increment = 7, // 背隙增量 + kcfg_moving_average_window_size = 8, // 移动平均窗口大小 default:3 + kcfg_io1_mode = 9, // I/O 1 0=LLD输出高 1=LLD输出低 2=通用输出 default:0 + kcfg_io2_mode = 10, // I/O 2 0=通用输入 1=紧急制动 2=Tip脱落输出高 3=Tip脱落输出低 default:0 + kcfg_origin_offset = 12, // 原点偏移(往吸取方向)0...300 default:112 + kcfg_motor_hold_current = 13, // 电机保持电流(单位:0.01A)0...200 default:10 + kcfg_motor_run_current = 14, // 电机运行电流(单位:0.01A)0...200 default:25 + kcfg_pLLD_start_delay = 15, // pLLD启动延迟(毫秒)0...2000 default:100 + kcfg_nL_increment = 16, // 纳升/增量。此值用于将[N2]模式的nL 输入和输出转换为增量。 (当前系统中不使用) + kcfg_total_range = 17, // 用nL表示的总量程。当这个值被改变时,u1所设定的值也会按照这个公式自动变更:u1=u17/u16 同时,u1改变时,此值也会自动变更:u17=u1*u16 (当前系统中不使用) + kcfg_tip_size = 18, // Tip大小。对此值进行设置之后,u1和u17的值将会自动进行变更。 (当前系统中不使用) + kcfg_default_tolerance = 21, // [q] 命令默认容差 + kcfg_pressure_data_stream_time = 22, // 泵运动完成后保持压力数据流输出的时间(毫秒)。请参见[+]命令。 + kcfg_auto_temp_compensation = 24, // 自动使用温度补偿。 + kcfg_temp_compensation_rate = 25, // 温度补偿率,单位:增量/℃/mL 注意:[*]命令覆盖此设置。 + kcfg_temp_value = 26, // 环境温度*100(例如,24°C*100=2400)与温度补偿一起使用 注意:[*]命令覆盖此设置。 + kcfg_enable_tip_block_check = 32, // [q]命令的“Tip堵塞”检查功能 + kcfg_enable_operation_check = 33, // [q]命令的“操作量”检查功能 + kcfg_enable_air_inlet_check = 34, // [q]命令的“空气进液”检查功能 + kcfg_enable_bubble_foam_check = 35, // [q]命令的“气泡/泡沫”检查功能 +} cfg_t; + +typedef enum { + kstate_pump_pos = 0, // 泵位置 + kstate_pump_pos_mm = 2, // 泵位置(毫米) + kstate_pump_pos_nl = 3, // 泵位置(纳升) + kstate_back_clearance = 4, // 背隙[K],泵位置 + kstate_start_v = 6, // 启动速度[v] + kstate_max_v = 7, // 最高速度[V] + kstate_stop_v = 8, // 停止速度[c] + kstate_acc = 9, // 加速度的[L]值 + kstate_dec = 10, // 减速度的[L]值 + kstate_motor_irun = 11, // 泵电机运行电流,单位0.01A + kstate_motor_ihold = 12, // 泵电机保持电流,单位0.01A + kstate_total_range = 17, // 最大行程 + kstate_firmware = 23, // 固件版本 + kstate_cfg = 27, // [u]命令设置值 + kstate_pump_status = 29, // 泵状态 + kstate_io2 = 30, // I/O2输入状态 + kstate_tip_state = 31, // Tip装载状态 + kstate_moving_average = 38, // 压力检测值的移动平均窗口大小 + kstate_power_on_times = 41, // 自出厂以来,泵上电的总次数 + kstate_init_times = 42, // 自出厂以来,泵初始化总次数 + kstate_init_times_cur = 43, // 本次通电后的泵初始化次数 + kstate_moving_distance = 44, // 自出厂以来,泵的运动距离(单位:毫米) + kstate_piston_move_times = 45, // 自出厂以来,活塞移动次数 + kstate_piston_move_times_cur = 46, // 本次通电后的活塞移动次数 + kstate_pop_tip_times = 47, // 自出厂以来,弹出Tip的次数 + kstate_pop_tip_times_cur = 48, // 本次通电后Tip弹出的次数 + kstate_pump_temp = 53, // 当前泵体温度(摄氏度) + kstate_temp_max = 54, // 温度值最高记录 + kstate_temp_min = 55, // 温度值最低记录 + kstate_pressure_ad = 56, // 压力对应的AD值 + kstate_q_time = 57, // 获取[q]指令执行过程中的特征时间 + kstate_pressure_max = 58, // 自上次[f1]命令以来记录的最高压力值 + kstate_pressure_min = 59, // 自上次[f1]命令以来记录的最低压力值 + kstate_q_max_diff = 60, // 获取[q]指令执行过程中的最大差值 + kstate_cmd_buf = 99, // 缓冲区中的当前命令字符串 + kstate_p_cmd = 100, // 当前[p]命令设置 + kstate_n_cmd = 102, // 当前[N]命令设置 + kstate_io1 = 103, // I/O 1的电平状态 + kstate_temp_compensation = 149, // 自活塞上次处于原点(零)以来的温度补偿增量总数 +} state_t; + +typedef struct { + cmd_t cmd; + char cmdchar; + int paramnum; +} cmd_info_t; + +/** + * @brief + * 编码规则: + * 1. 泵机的所有参数均使用默认参数,不做任何设置 + * 2. 每次执行动作时,一次性传入所有必要的参数 + * 3. 增量模式单位为 0.319ul + */ + +class SMTP2V2 { + public: + private: + UART_HandleTypeDef* m_uart = nullptr; + uint8_t m_id = 0; + + DMA_HandleTypeDef* m_hdma_rx; + DMA_HandleTypeDef* m_hdma_tx; + + char m_rxbuf[SMTP2_BUF_LEN] = {0}; + char m_txbuf[SMTP2_BUF_LEN] = {0}; + int32_t m_rxNum = {0}; + + public: + void initialize(UART_HandleTypeDef* uart, uint8_t id, DMA_HandleTypeDef* hdma_rx, DMA_HandleTypeDef* hdma_tx); + + void pump_init_cfg(); + void pump_ping(); + + // 泵机复位(归零) + void pump_init(); + void pump_reset(); + + // + void pump_move_to(); + void pump_set_cfg(cfg_t cfgindex, int32_t val); + + bool write_cmd(const char* cmd); + void getack(char* rx, int32_t* rxbufsize); + + private: + bool sendcmd(const char* cmd); + bool _sendcmd(const char* cmd); + bool _sendcmd_dma(const char* cmd); + + int32_t getAckEcode(); +}; + +} // namespace smtp2 +} // namespace iflytop diff --git a/components/zcancmder/zcan_protocol_parser.cpp b/components/zcancmder/zcan_protocol_parser.cpp index e6f2dd1..589d51b 100644 --- a/components/zcancmder/zcan_protocol_parser.cpp +++ b/components/zcancmder/zcan_protocol_parser.cpp @@ -71,6 +71,7 @@ void ZCanProtocolParser::initialize(IZCanReceiver* cancmder) { REGFN(pipette_ctrl_init_device); REGFN(pipette_ctrl_put_tip); REGFN(pipette_ctrl_move_to_ul); + REGFN(pipette_write_cmd_direct); REGFN(temp_controler_start_hearting); REGFN(temp_controler_stop_hearting); @@ -482,6 +483,15 @@ int32_t ZCanProtocolParser::pipette_ctrl_move_to_ul(cmdcontxt_t* cxt) { CHECK_AND_GET_MODULE(1); return module->pipette_ctrl_move_to_ul(cxt->params[0]); } +int32_t ZCanProtocolParser::pipette_write_cmd_direct(cmdcontxt_t* cxt) { + GET_MODULE(); + cxt->acklen = ZCANCMD_READ_BUF_MAX_SIZE; + int32_t suc = module->pipette_write_cmd_direct(cxt->paramRaw, cxt->paramlen, cxt->ackbuf, &cxt->acklen); + if (suc != 0) { + cxt->acklen = 0; + } + return suc; +} #undef MODULE_CLASS diff --git a/components/zcancmder/zcan_protocol_parser.hpp b/components/zcancmder/zcan_protocol_parser.hpp index 9b8a793..769593c 100644 --- a/components/zcancmder/zcan_protocol_parser.hpp +++ b/components/zcancmder/zcan_protocol_parser.hpp @@ -104,6 +104,7 @@ class ZCanProtocolParser : public IZCanReceiverListener { static int32_t pipette_ctrl_init_device(cmdcontxt_t* cxt); static int32_t pipette_ctrl_put_tip(cmdcontxt_t* cxt); static int32_t pipette_ctrl_move_to_ul(cmdcontxt_t* cxt); + static int32_t pipette_write_cmd_direct(cmdcontxt_t* cxt); static int32_t temp_controler_start_hearting(cmdcontxt_t* cxt); static int32_t temp_controler_stop_hearting(cmdcontxt_t* cxt);