在笛卡尔打印机上的运动非常简单。如果我们假设打印机在每个轴上有 100 步/毫米,那么在一个轴上移动 10 毫米就是在该轴上移动 1000 步。
不与一个轴对齐的运动也很简单。从 x,y = 0,0 移动到 10,10 将是 x 和 y 上的 1000 步。
在 deltas 上,即使是简单的移动,也有不止一台电机需要移动。仅计算到达目的地所需的每个轴上的步数可能会产生曲线移动。
那么计算 delta 打印机给定移动的步骤的算法是什么?
在笛卡尔打印机上的运动非常简单。如果我们假设打印机在每个轴上有 100 步/毫米,那么在一个轴上移动 10 毫米就是在该轴上移动 1000 步。
不与一个轴对齐的运动也很简单。从 x,y = 0,0 移动到 10,10 将是 x 和 y 上的 1000 步。
在 deltas 上,即使是简单的移动,也有不止一台电机需要移动。仅计算到达目的地所需的每个轴上的步数可能会产生曲线移动。
那么计算 delta 打印机给定移动的步骤的算法是什么?
大多数开源 3d 打印机控制器使用的技术有两个主要的特殊步骤:
反向运动学非常简单。虚拟 90 度三角形由两个已知长度构建,以求解未知的第三个长度:
我认为这里最好的开源参考是 Steve Grave 的 Rostock Kinematics 文档,rev3 可在此处下载:https ://groups.google.com/d/msg/deltabot/V6ATBdT43eU/jEORG_l3dTEJ 一些相关图片:
这些逆运动学计算针对每个小车执行以获得“小车空间”目标位置,并且这针对每个路径子段执行。
然后可以将这些步骤的结果重新插入到打印机的标准线性路径插值技术中,其中它以必要的比率和必要的速率发射步骤,以产生所需的直线运动和加速度/速度曲线。(如何完成是一个不同的问题。)
最终效果是打印机将通过一系列小的“线性”滑架运动(线性意味着相对于时间的恒定*速度),这些移动共同近似产生所需的弯曲(相对于时间的二次位置)滑架运动直线末端执行器移动。
*(无论如何,在应用加速减速之前的恒定速度是为了遵守动力学约束。同样,这是另一个问题的主题。)
分割与使用多边形近似圆的过程非常相似。如果面足够小,则多边形是一个很好的近似值。更高的分割率产生更少的路径跟随误差。绘制圆弧和 Delta 运动路径之间的主要概念区别在于,所谓的带有 Delta 分割的“多面弧”是在高度与时间坐标中构建的,而不是您用来绘制圆弧的 X-vs-Y 坐标。计算机屏幕上的圆圈。
之所以使用该系统,很大程度上是因为对 Delta 式打印机的支持最初是用螺栓固定在基于 GRBL 的运动规划器上,该规划器专为笛卡尔打印机中的直线运动路径而编写。与实现完整的二次路径插值相比,这是对现有代码库的相对最小的修改。
多年来,技术不断发展。并且经常使用替代方法:例如,RepRapFirmware 的 dc42 分支通过在每一步之后重新计算下一步的适当时间来执行精确的路径跟踪而不进行分段。这在功能上相当于用多边形面数近似一个圆,以致屏幕上的每个像素都有自己的面。因此,它与电机的定位分辨率所允许的一样准确。不利的一面是,这种无分段技术是处理器密集型的,因此它只能在相对较快的控制器上工作,而不是在为当今大多数现有消费者/业余爱好者打印机提供动力的较旧的 8 位 Atmega AVR 上工作。
其他技术也是可能的。学术并行机器人控制文献是数学技术和复杂性的另一个世界,目的是产生适用于各种机器人机构的通用控制算法。相比之下,我们在开源 3d 打印机中使用的版本非常简单且特定于应用程序。
我正在描述这是如何在 Marlin 固件中完成的。
第一步是将一个从 (x, y, z) 到 (x', y', z') 的线性运动分成许多离散的段。为此,计算在给定速度下移动所需的时间量,并且使用值delta_segments_per_second来计算使用的段数。
这是在文件 Marlin_main.cpp中的函数prepare_move_delta中完成的。然后将这些段中的每一个的端点传递给函数calculate_delta:
void calculate_delta(float cartesian[3]) {
//reverse kinematics.
// Perform reversed kinematics, and place results in delta[3]
// The maths and first version has been done by QHARLEY . Integrated into masterbranch 06/2014 and slightly restructured by Joachim Cerny in June 2014
float SCARA_pos[2];
static float SCARA_C2, SCARA_S2, SCARA_K1, SCARA_K2, SCARA_theta, SCARA_psi;
SCARA_pos[X_AXIS] = cartesian[X_AXIS] * axis_scaling[X_AXIS] - SCARA_offset_x; //Translate SCARA to standard X Y
SCARA_pos[Y_AXIS] = cartesian[Y_AXIS] * axis_scaling[Y_AXIS] - SCARA_offset_y; // With scaling factor.
#if (Linkage_1 == Linkage_2)
SCARA_C2 = ((sq(SCARA_pos[X_AXIS]) + sq(SCARA_pos[Y_AXIS])) / (2 * (float)L1_2)) - 1;
#else
SCARA_C2 = (sq(SCARA_pos[X_AXIS]) + sq(SCARA_pos[Y_AXIS]) - (float)L1_2 - (float)L2_2) / 45000;
#endif
SCARA_S2 = sqrt(1 - sq(SCARA_C2));
SCARA_K1 = Linkage_1 + Linkage_2 * SCARA_C2;
SCARA_K2 = Linkage_2 * SCARA_S2;
SCARA_theta = (atan2(SCARA_pos[X_AXIS], SCARA_pos[Y_AXIS]) - atan2(SCARA_K1, SCARA_K2)) * -1;
SCARA_psi = atan2(SCARA_S2, SCARA_C2);
delta[X_AXIS] = SCARA_theta * SCARA_RAD2DEG; // Multiply by 180/Pi - theta is support arm angle
delta[Y_AXIS] = (SCARA_theta + SCARA_psi) * SCARA_RAD2DEG; // - equal to sub arm angle (inverted motor)
delta[Z_AXIS] = cartesian[Z_AXIS];
}
此函数负责将线段端点的 (x,y,z) 坐标转换为小车的相应位置所需的 delta 几何和计算。然后将转换后的坐标传递给plan_buffer_line,它计算每个步进电机所需的步骤并实际执行这些步骤。
在Marlin github 中更详细地解释了此函数中使用的确切运动学。
重要的是要注意 plan_buffer_line 线性移动托架,因此打印头描述的是弧线而不是直线。因此,直线运动由许多小弧线近似。