我正在为CNC机床编程控制器,因此当我从A点到B点时,我需要在每个方向上获得步进电机步数。比如A点……
您应该获取每个坐标上的距离之间的比率,然后在具有最长距离的坐标的步骤之间交替,在两个坐标上执行单个单位步骤的步骤。
这是JavaScript中的一个实现 - 只使用最简单的语法:
function steps(a, b) { const dx = Math.abs(b.x - a.x); const dy = Math.abs(b.y - a.y); const sx = Math.sign(b.x - a.x); // sign = -1, 0, or 1 const sy = Math.sign(b.y - a.y); const longest = Math.max(dx, dy); const shortest = Math.min(dx, dy); const ratio = shortest / longest; const series = []; let longDone = 0; let remainder = 0; for (let shortStep = 0; shortStep < shortest; shortStep++) { const steps = Math.ceil((0.5 - remainder) / ratio); if (steps > 1) { if (dy === longest) { series.push( {x: 0, y: (steps-1)*sy} ); } else { series.push( {x: (steps-1)*sx, y: 0} ); } } series.push( {x: sx, y: sy} ); longDone += steps; remainder += steps*ratio-1; } if (longest > longDone) { if (dy === longest) { series.push( {x: 0, y: longest-longDone} ); } else { series.push( {x: longest-longDone, y: 0} ); } } return series; } // Demo console.log(steps({x: 0, y: 0}, {x: 3, y: 15}));
请注意,第一个段比所有其他段短,因此它与序列在第二个点附近的结束方式更加对称。如果你不喜欢,那么替换出现的 0.5 在代码中有0或1。
0.5
如果您的控制器可以比步进器实际转动的速度更快地发出命令,那么您可能希望使用某种基于事件的定时器系统。你需要计算 什么时候 触发每个电机,使运动均匀分布在两个轴上。
应该尽可能快地编程较长的运动(也就是说,如果电机每秒可以进行100步,每隔1/100秒进行一次脉冲),另一次以较长的间隔进行运动。
编辑:上面的段落假定您要尽快移动工具。通常情况并非如此。通常,给定刀具速度,因此您需要分别计算沿X和Y(也可能是Z)轴的速度。您还应该知道什么工具行程距离对应于电机的一个步骤。因此,您可以计算每个时间单位需要执行的步数,以及整个运动的持续时间,从而计算沿每个轴的连续步进脉冲之间的时间间隔。
因此,您可以将计时器编程为在计算出的最小计时间隔后触发,脉冲相应的电机,为下一个脉冲编程定时器,依此类推。
这是一种简化,因为与所有物理对象一样,电机具有惯性并需要时间来加速/减速。因此,如果您想要产生平滑的运动,则需要考虑到这一点。还有更多需要考虑的因素。但这更多是关于物理而不是编程。编程模型保持不变。您将机器建模为物理对象,以某种已知方式对已知刺激(步进脉冲)作出反应。您的程序计算来自模型的步进脉冲的时序,并位于事件循环中,等待下一次事件发生。
考虑 Bresenham的线描算法 m - 他多年前为绘图员发明了它。 (也是DDA之一)
在你的情况下,X / Y位移具有公约数 GCD=3 > 1 ,所以步骤应该均匀变化,但一般情况下,它们不会如此均匀地分布。
GCD=3 > 1