按照GRBL的结构图我们可以知道,从Gcode传递下来的结构体,下一步将通过PLANNER来进行步进电机的控制运算。
也就是说,直线插补,圆弧插补将通过PLANNER来进行处理。
先看一下PLANNER.H中包含的函数以及实现的功能。
voidplan_init(void);
//名称:初始化运动调度系统
//具体功能描述:策略器包含一个结构体,以及存放数据的缓存,将其全部清零。
voidplan_buffer_line(floatx,floaty,floatz,floatfeed_rate,uint8_tinvert_feed_rate);
//名称:直线插补
//具体功能描述:指令的格式为G1X25Y25Z25F,用到了一个结构体block_t
//结构体一共分三个区,一个是bresenham算法的参数,包括方向,XYZ移动坐标,以及总计步数
//一个给运动调度系统管理,主要是3个速度设置和3个标志FLAG
//一个是给梯形加速器用
voidplan_discard_current_block(void);
//名称:当前块清除
//具体功能描述:留出来给新的块进行操作
block_t*plan_get_current_block(void);
//名称:获取当前块
//具体功能描述:如果是空则返回NULL,主要用于调度器进行同步时用。
voidplan_set_current_position(int32_tx,int32_ty,int32_tz);
//名称:复位调度器的位置向量
//具体功能描述:用于同步所有的轴向量用。
voidplan_cycle_reinitialize(int32_tstep_events_remaining);
//名称:重新初始化
//具体功能描述:用于进行所有轴重新初始化用。
voidplan_reset_buffer(void);
//名称:调度器缓存清零
//具体功能描述:略
uint8_tplan_check_full_buffer(void);
//名称:调度器缓存检测
//具体功能描述:略
voidplan_synchronize(void);
//名称:调度器缓同步
//具体功能描述:略
那问题来了,圆弧插补哪里去了?
先看一下谁会调用voidplan_buffer_line(floatx,floaty,floatz,floatfeed_rate,uint8_tinvert_feed_rate);
直接往前找,可以发现调用直线插补函数的是mc_line,这个好理解,直线插补,在运动控制的源文件中进行调用。
可以看出,运动控制头文件MOTION_CONTROL.C里面,还有如下的函数:
MC_LINE:
MC_ARC
MC_DWELL
MC_GO_HOME
MC_RESET
函数名称简单易懂,都很好理解。
那这个MC_ARC呢?
发现里面循环调用了一个MC_LINE:
for(i=1;isegments;i++){//Increment(segments-1)
……
mc_line(target[X_AXIS],target[Y_AXIS],target[Z_AXIS],feed_rate,invert_feed_rate);
}
明白了,将圆弧离散为小线段进行执行。
问题的难点来了,小线段直线插补,用bresenham来进行处理。
现在要搞懂的问题如下:
bresenham是怎么实现的?
和DDA比,优势是啥
Bresenham直线算法是用来描绘由两点所决定的直线的算法,它会算出一条线段在n维光栅上最接近的点。这个算法只会用到较为快速的整数加法、减法和位元移位,常用于绘制电脑画面中的直线。是计算机图形学中最先发展出来的算法。
(引自wiki百科布雷森漢姆直線演算法)
具体的算法可以在我的图书馆中查看原理和编程流程图