/* ctrl_lz Task */ /* Includes ----------------------------------------------------------------- */ #include "task/user_task.h" /* USER INCLUDE BEGIN */ #include "bsp/can.h" #include "device/motor_lz.h" #include "device/motor_lk.h" #include "module/config.h" #include /* USER INCLUDE END */ /* Private typedef ---------------------------------------------------------- */ /* Private define ----------------------------------------------------------- */ /* Private macro ------------------------------------------------------------ */ /* Private variables -------------------------------------------------------- */ /* USER STRUCT BEGIN */ static bool command_received = false; /* USER STRUCT END */ /* Private function --------------------------------------------------------- */ /* Exported functions ------------------------------------------------------- */ void Task_ctrl_lz(void *argument) { (void)argument; /* 未使用argument,消除警告 */ /* 计算任务运行到指定频率需要等待的tick数 */ const uint32_t delay_tick = osKernelGetTickFreq() / CTRL_LZ_FREQ; osDelay(CTRL_LZ_INIT_DELAY); /* 延时一段时间再开启任务 */ uint32_t tick = osKernelGetTickCount(); /* 控制任务运行频率的计时 */ /* USER CODE INIT BEGIN */ BSP_CAN_Init(); MOTOR_LZ_Init(); for (int i = 0; i < 4; i++) { MOTOR_LZ_Register(&Config_GetRobotParam()->joint_param[i]); } // 注册CAN接收ID BSP_CAN_RegisterId(BSP_CAN_1, 121, 0); // 使能命令 BSP_CAN_RegisterId(BSP_CAN_1, 122, 0); // 力矩控制命令 /* USER CODE INIT END */ while (1) { tick += delay_tick; /* 计算下一个唤醒时刻 */ /* USER CODE BEGIN */ MOTOR_LZ_UpdateAll(); // 检查CAN接收消息 BSP_CAN_Message_t rx_msg; command_received = false; // 重置命令接收标志 // 检查ID 121 - 使能4个电机 if (BSP_CAN_GetMessage(BSP_CAN_1, 121, &rx_msg, BSP_CAN_TIMEOUT_IMMEDIATE) == BSP_OK) { command_received = true; for (int i = 0; i < 4; i++) { MOTOR_LZ_Enable(&Config_GetRobotParam()->joint_param[i]); } } // 检查ID 122 - 运控模式控制4个电机 if (BSP_CAN_GetMessage(BSP_CAN_1, 122, &rx_msg, BSP_CAN_TIMEOUT_IMMEDIATE) == BSP_OK) { command_received = true; // 8字节数据分别是4个电机的力矩 (每个电机2字节,有符号整数,精度0.01 Nm) for (int i = 0; i < 4; i++) { int16_t torque_raw; memcpy(&torque_raw, &rx_msg.data[i * 2], sizeof(int16_t)); float torque = (float)torque_raw / 100.0f; // 转换为浮点数力矩值 // 使用运控模式控制电机,只设置力矩,其他参数为0 MOTOR_LZ_MotionParam_t motion_param = { .target_angle = 0.0f, .target_velocity = 0.0f, .kp = 0.0f, .kd = 0.0f, .torque = torque }; MOTOR_LZ_MotionControl(&Config_GetRobotParam()->joint_param[i], &motion_param); } } // 如果没有收到任何控制命令,电机进入relax模式 if (!command_received) { for (int i = 0; i < 4; i++) { MOTOR_LZ_Relax(&Config_GetRobotParam()->joint_param[i]); } } // 发送4个电机的反馈数据,ID分别为124、125、126、127 for (int i = 0; i < 4; i++) { MOTOR_LZ_t* motor = MOTOR_LZ_GetMotor(&Config_GetRobotParam()->joint_param[i]); if (motor != NULL) { BSP_CAN_StdDataFrame_t motor_frame = { .id = 124 + i, // ID: 124, 125, 126, 127 .dlc = 8, .data = {0} }; // 数据重构:转矩电流(2字节) + 位置(3字节) + 速度(3字节) = 8字节 // 转矩电流 - 转换为16位整数 (精度0.01 Nm) int16_t torque_int = (int16_t)(motor->lz_feedback.current_torque * 100); memcpy(&motor_frame.data[0], &torque_int, sizeof(int16_t)); // 位置 - 转换为24位整数,使用3字节 (精度0.0001 rad) int32_t angle_int = (int32_t)(motor->lz_feedback.current_angle * 10000) & 0xFFFFFF; motor_frame.data[2] = (angle_int >> 16) & 0xFF; motor_frame.data[3] = (angle_int >> 8) & 0xFF; motor_frame.data[4] = angle_int & 0xFF; // 速度 - 转换为24位整数,使用3字节 (精度0.001 rad/s) int32_t velocity_int = (int32_t)(motor->lz_feedback.current_velocity * 1000) & 0xFFFFFF; motor_frame.data[5] = (velocity_int >> 16) & 0xFF; motor_frame.data[6] = (velocity_int >> 8) & 0xFF; motor_frame.data[7] = velocity_int & 0xFF; BSP_CAN_TransmitStdDataFrame(BSP_CAN_1, &motor_frame); } } /* USER CODE END */ osDelayUntil(tick); /* 运行结束,等待下一次唤醒 */ } }