我有一个带有两个轮子/电机的机器人,每个机器人都有一个用于里程表的正交编码器。使用Pololu的滚轮/电机/编码器组合,我每转可获得48个过渡变化,而我的电机最多可提供400RPM。我发现它似乎错过了Pololu轮编码器库的一些编码器状态更改。通过H桥芯片驱动我的电机?

评论

没有看到您的实际代码,就不可能回答中断是否会引起问题。

#1 楼

中断服务程序应始终执行绝对最小值。请记住,当您的MCU处理中断时,它什么也没做。

对于简单的正交编码器,应该有一对ISR,一个ISR是由A通道的变化触发的,另一个是由B频道上的更改触发的。 ISR并可能更新状态转换时间(如果您正在使用此信息来更好地估计速度†)。

†请参阅RJE的光学增量编码器的速度和加速度估计快活,M.J.G. van de Molengraft,M。Steinbuch

使用一对标准正交编码器,每转48次转换变化,最大400RPM,您的跨通道中断的频率不应超过每秒640次这应该在16MHz处理器的能力之内。

单个通道可能会比该通道更频繁地产生更多中断(例如,当检测器位于边缘时),但是不会丢失那些状态变化必须影响最终位置值,并且在该通道稳定和另一个通道激活之间始终存在清晰的1.5ms。

因此,只要您可以为每个A / B和B /过渡,只要偶尔在下一个A / B或B / A过渡中同时考虑到A和B的状态,则偶尔处理A / A或B / B过渡都没有关系。 br />
请注意,如果您不需要计算AB和BA转换的时间(以更快的速度计算速度)使用低分辨率编码器),那么您可能会不如提姆·韦斯科特(Tim Wescott)所建议的那样具有固定的基于640Hz / 1.5ms定时器的中断服务程序,该程序可以同时查看A和B通道。

#2 楼

当我在ISR中处理正交编码器输入时,我更喜欢在计时器上运行一个简单的ISR,该计时器可以保证足够快地运行以捕获编码器的每个状态(而不是状态变化)。每次引脚转换时中断都会引起一种情况,如果引脚开始弹跳,处理器就会陷入瘫痪。以固定的速率进行中断可能会一直消耗处理器资源,但是它总是使用相同数量的资源,因此,即使您最不希望发生这种情况,也不会感到惊讶。

您的48个转数/转数,400RPM电机,每秒可完成320个转数:我将ISR设置为至少以两倍快的速度中断。除了检查两个销钉的当前状态是否与前一个销钉有关,它什么也不要做,然后根据所看到的情况适当地增加或减少轮子的计数器。即使在进行多个轮子的更新时,在640Hz时,这样的ISR也会给处理器带来很小的负担。

我已经建立了很多使用此方法的成功控制系统,因此它可以不会很糟糕。

#3 楼

是的,您会:市场上(我知道)的[Arduino]都无法有效跟踪状态变化而不会丢失一些状态变化。 (也许Due Due更好,或者另一块时钟频率更高的板子。)

中断可能会有所帮助,但是:


我相信它可以阻止一切芯片上的其他触发中断时,电动机可能会稍微停止。
如果两个中断同时触发,您可能会遇到问题
在处理完代码后,我相信我会稍稍延迟一下才能返回到

中断并不是解决此问题的最佳解决方案,但这是使用现代技术唯一可以做的事情。但是,如果您仍然希望中断,则可以在面包板上运行另一个带有中断的ATmel328,该中断在主芯片发送消息时可以发送每个轮子的转数,因为它是最后一次发送。我不知道在调用中断时它将如何工作,但是也许如果您使用诸如Arduino的Wire Library之类的开发库,它可能会在调用它时解决问题。

祝你好运。

评论


$ \ begingroup $
当运行中断服务程序时,不会处理其他中断。当前中断完成后,最多可以按ATmel预先确定的顺序对一种中断类型进行排队和处理。在这种情况下,中断之间存在一个指令的延迟。
$ \ endgroup $
–JamesC4S
13年4月15日在5:32

$ \ begingroup $
Arduino真的不能每秒处理640次(2x48x400 / 60)中断,并且还有时间进行其他处理吗?在16MHz时,每个中断是否超过25,000个时钟周期?
$ \ endgroup $
– Mark Booth♦
13年4月15日在13:20

$ \ begingroup $
@MarkBooth是的,只要ISR不会因不必要的指令而膨胀,它应该能够处理这么少的中断。
$ \ endgroup $
–JamesC4S
13年4月15日在16:21

$ \ begingroup $
感谢@ JamesC4S-我知道制作高效的ISR是您必须学习的技能,但是我认为您必须真正效率低下,才能在嵌入式CPU上以这种速度处理中断。
$ \ endgroup $
– Mark Booth♦
13年4月15日在16:31

$ \ begingroup $
@MarkBooth您又说对了。但是,一个很好的例子是尝试在ISR内部执行相对较慢的操作(例如浮点数学或Serial.print())的人。 [并且在Arduino 1.0中,由于Serial.print()现在是中断驱动的,因此它不起作用。]最好设置一个标志或增加一个计数器,然后退出。
$ \ endgroup $
–JamesC4S
13年4月15日在16:35