任意象限直线插补
1.任意象限直线插补原理
2.任意象限例程
/* 直线插补参数结构体 */
typedef struct{
__IO uint32_t endpoint_x; //终点坐标X
__IO uint32_t endpoint_y; //终点坐标Y
__IO uint32_t endpoint_pulse; //到达终点位置需要的脉冲数
__IO uint32_t active_axis; //当前运动的轴
__IO int32_t deviation; //偏差参数
__IO uint8_t motionstatus : 1; //插补运动状态
__IO uint8_t dir_x : 1; //X轴运动方向
__IO uint8_t dir_y : 1; //Y轴运动方向
}LinearInterpolation_TypeDef;
/**
* @brief 任意直线插补运动
* @param coordi_x:终点坐标X的增量
* @param coordi_y:终点坐标Y的增量
* @param speed:进给速度,定时器计数值
* @retval 无
*/
void Linear_Interpolation(int32_t coordi_x, int32_t coordi_y, uint16_t speed)
{
/* 判断当前是否正在做插补运动 */
if(interpolation_para.motionstatus != 0)
return;
/* 判断坐标正负,以此决定各轴的运动方向 */
if(coordi_x < 0)
{
interpolation_para.dir_x = CCW;
coordi_x = -coordi_x;
MOTOR_DIR(step_motor[x_axis].dir_port, step_motor[x_axis].dir_pin, CCW);
}
else
{
interpolation_para.dir_x = CW;
MOTOR_DIR(step_motor[x_axis].dir_port, step_motor[x_axis].dir_pin, CW);
}
if(coordi_y < 0)
{
interpolation_para.dir_y = CCW;
coordi_y = -coordi_y;
MOTOR_DIR(step_motor[y_axis].dir_port, step_motor[y_axis].dir_pin, CCW);
}
else
{
interpolation_para.dir_y = CW;
MOTOR_DIR(step_motor[y_axis].dir_port, step_motor[y_axis].dir_pin, CW);
}
/* 开始插补运动 */
InterPolation_Move(coordi_x, coordi_y, speed);
}
/**
* @brief 定时器比较中断回调函数
* @param htim:定时器句柄指针
* @note 无
* @retval 无
*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
uint32_t last_axis = 0;
/* 记录上一步的进给活动轴 */
last_axis = interpolation_para.active_axis;
/* 根据上一步的偏差,判断的进给方向,并计算下一步的偏差 */
if(interpolation_para.deviation >= 0)
{
/* 偏差>0,在直线上方,进给X轴,计算偏差 */
interpolation_para.active_axis = x_axis;
interpolation_para.deviation -= interpolation_para.endpoint_y;
}
else
{
/* 偏差<0,在直线下方,进给Y轴,计算偏差 */
interpolation_para.active_axis = y_axis;
interpolation_para.deviation += interpolation_para.endpoint_x;
}
/* 下一步的活动轴与上一步的不一致时,需要换轴 */
if(last_axis != interpolation_para.active_axis)
{
TIM_CCxChannelCmd(htim->Instance, step_motor[last_axis].pul_channel, TIM_CCx_DISABLE);
TIM_CCxChannelCmd(htim->Instance, step_motor[interpolation_para.active_axis].pul_channel, TIM_CCx_ENABLE);
}
/* 进给总步数减1 */
interpolation_para.endpoint_pulse--;
/* 判断是否完成插补 */
if(interpolation_para.endpoint_pulse == 0)
{
/* 关闭定时器 */
TIM_CCxChannelCmd(htim->Instance, step_motor[last_axis].pul_channel, TIM_CCx_DISABLE);
TIM_CCxChannelCmd(htim->Instance, step_motor[interpolation_para.active_axis].pul_channel, TIM_CCx_DISABLE);
__HAL_TIM_MOE_DISABLE(htim);
HAL_TIM_Base_Stop_IT(htim);
interpolation_para.motionstatus = 0;
}
}
/**
* @brief 第一象限直线插补运动
* @param inc_x:终点坐标X的增量
* @param inc_y:终点坐标Y的增量
* @param speed:进给速度
* @retval 无
*/
static void InterPolation_Move(uint32_t inc_x, uint32_t inc_y, uint16_t speed)
{
/* 偏差清零 */
interpolation_para.deviation = 0;
/* 设置终点坐标 */
interpolation_para.endpoint_x = inc_x;
interpolation_para.endpoint_y = inc_y;
/* 所需脉冲数为X、Y坐标增量之和 */
interpolation_para.endpoint_pulse = inc_x + inc_y;
/* 第一步进给的活动轴为X轴 */
interpolation_para.active_axis = x_axis;
/* 计算偏差 */
interpolation_para.deviation -= interpolation_para.endpoint_y;
/* 设置速度 */
__HAL_TIM_SET_COMPARE(&TIM_StepperHandle, step_motor[x_axis].pul_channel, speed);
__HAL_TIM_SET_COMPARE(&TIM_StepperHandle, step_motor[y_axis].pul_channel, speed);
__HAL_TIM_SET_AUTORELOAD(&TIM_StepperHandle, speed * 2);
/* 使能主输出 */
__HAL_TIM_MOE_ENABLE(&TIM_StepperHandle);
/* 开启X轴比较通道输出 */
TIM_CCxChannelCmd(MOTOR_PUL_TIM, step_motor[interpolation_para.active_axis].pul_channel, TIM_CCx_ENABLE);
HAL_TIM_Base_Start_IT(&TIM_StepperHandle);
interpolation_para.motionstatus = 1;
}
可以看到,上述代码与第一象限直线插补完全相同,这是因为直线所在象限的判断和进给方向的处理已经在 Linear_Interpolation函数中完成,剩下的直接按照第一象限直线进行插补即可。