任意象限直线插补

1.任意象限直线插补原理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OrFMFnYC-1635666524162)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20211031152906299.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fHsjMMx8-1635666524171)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20211031153009004.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DkwAc7is-1635666524178)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20211031153034165.png)]

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函数中完成,剩下的直接按照第一象限直线进行插补即可。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言是一种强大的编程语言,可以用来实现各种算法和逻辑。要写第一象限直线插补,我们可以利用C语言的数学库函数和控制语句来实现。 首先,我们需要确定直线的起点和终点坐标。假设起点坐标为(x1, y1),终点坐标为(x2, y2)。我们可以通过用户输入或者硬编码来获取这些坐标。 然后,我们可以计算直线的斜率m和截距b。斜率m可以通过以下公式计算:m = (y2 - y1) / (x2 - x1)。 接下来,我们可以使用循环结构来迭代直线上的每个点。我们可以定义一个循环变量x,从起点坐标的x值开始,按照一定的步幅递增,直到达到终点坐标的x值。可以选择步幅为1或其他合适的值。在循环中,我们可以使用直线方程y = mx + b来计算相应的y值。 最后,我们可以在循环中输出每个点的坐标值(x, y)。可以使用C语言中的printf函数来实现输出。 下面是一个简单的示例代码: ```c #include <stdio.h> int main() { int x1, y1, x2, y2; float m, b; printf("请输入起点坐标:\n"); scanf("%d %d", &x1, &y1); printf("请输入终点坐标:\n"); scanf("%d %d", &x2, &y2); m = (float)(y2 - y1) / (x2 - x1); b = y1 - m * x1; printf("直线插补结果:\n"); for(int x = x1; x <= x2; x++) { int y = (int)(m * x + b); printf("(%d, %d)\n", x, y); } return 0; } ``` 通过以上代码,我们可以根据用户输入的起点和终点坐标,在第一象限上进行直线插补,并输出每个点的坐标。请注意,这只是一个简化的示例,实际应用中可能需要对输入进行验证和添加其他操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值