我有一个Arduino Mega连接到一个6轴机械臂。所有6个中断都连接到编码器(中断时为一个编码器引脚,另一个为香草数字输入)。使用以下代码处理中断:
void readEncoder1(){
//encoders is a 2d array, where the first d is the axis, and the two pin numbers
//first pin is on an interrupt (CHANGE), and second is a standard digital in
if (digitalRead(encoders[0][0]) == digitalRead(encoders[0][1])) {
positions[0]++;
} else {
positions[0]--;
}
if(servoEnable){
updatePositions(); //// compares positions[] to targets[] and adjusts motor speed accordingly
}
}
这是为了保持手臂锁定在某个位置 - 如果arduino检测到电机的位置偏离某个阈值,它会更新进入电机的电源以保持手臂就位。
问题是,那么 - 如果两个或三个(或更多)轴处于负载状态(需要不断更新以保持原位)或它们正在移动,Arduino将停止接收串行输入上的完整命令,几个字符将被删除。中断显然运行得非常快,并且由于某种原因导致命令被破坏。有没有办法解决?在建筑方面,我做得对吗?我的主要直觉是在主运行循环中调用updatePositions(),例如100 ms间隔,这会显着减少中断开销吗?我想我的问题归结为如何将可靠的串行命令输入Arduino,即使所有6个编码器都在脉冲输出?
答案 0 :(得分:2)
正交编码器设计为由硬件计数器读取。电机全速运转时,脉冲率通常较高。一兆赫并不罕见。脉冲数越多,伺服回路的工作效果越好,您可以更准确地定位电机。
这样做是在软件中使用低功耗cpu,具有挑战性。当ISR花费的时间超过脉冲之间的间隔时,它将会崩溃。你将失去脉冲,从而失去位置。特别糟糕,因为你无法检测到这种错误情况。并且这种损失发生在机器人快速移动时,最糟糕的情况是失去控制。
你绝对不能在中断处理程序中更新伺服循环,所以先摆脱它。将ISR保持在最低限度,只计算位置而不计算其他任何内容。伺服环路应该是独立的,由定时器中断或滴答驱动。你不能用100毫秒的伺服更新来正确控制机器人,除非它是一个缓慢的,这需要最多几毫秒来获得平稳的加速和稳定的反馈。
花费40美元来控制数千美元的机器人硬件是有限的智慧。无法跟上伺服回路是您可以检测到的,当位置误差累积过多时将其关闭。关于失去脉冲你无能为力,这是一个残骸。获取硬件计数器。
答案 1 :(得分:1)
嵌入式系统的第一条规则:
在中断时尽量少做。
在您的情况下,只需更新中断位置并在后台运行您的位置/速度控制循环或以较低的优先级运行。
除此之外:我假设你知道你正在“丢失”编码器脉冲,因为你在其中一个通道上没有中断?
此外,中断驱动的编码器分析非常容易出现噪音。如果你得到一个噪声脉冲,你可能只看到一个边缘的中断,因为它们太靠近在一起处理它们。
更强大的方法是使用一个监视所有4个转换的状态机,但这需要在两个通道的两个边缘都进行中断,或者轮询足够快,以便不会错过任何你期望看到的速率。< / p>