3

我有一个绝对编码器,它以格雷码输出 10 位值(0 到 1023)。我要解决的问题是如何确定编码器是向前还是向后移动。

我决定“最佳”算法如下:首先我将格雷码转换为常规二进制(完全归功于最后一个答案:https ://www.daniweb.com/programming/software-development/code/216355/格雷码转换):

int grayCodeToBinaryConversion(int bits)
{
  bits ^= bits >> 16; // remove if word is 16 bits or less
  bits ^= bits >>  8; // remove if word is 8 bits or less
  bits ^= bits >>  4;
  bits ^= bits >>  2;
  bits ^= bits >>  1;
  return bits;
}

其次,我比较了两个相隔 250 毫秒的采样值。我认为比较两个值会让我知道我是向前还是向后。例如:

if((SampleTwo – SampleOne) > 1)
{
  //forward motion actions
}

if((SampleTwo – SampleOne) < 1)
{
  //reverse motion actions
}

if(SampleTwo == SampleOne)
{
  //no motion action
}

就在我开始觉得自己很聪明的时候,令我失望的是,我意识到这个算法有一个致命的缺陷。当我将二进制值 824 与 1015 进行比较时,此解决方案效果很好。此时我知道编码器的移动方式。然而在某些时候,编码器会从 1023 翻转到 0 并爬升,然后当我去比较 1015 的第一个采样值和 44 的第二个采样值时,即使我在物理上朝同一个方向移动,我写的逻辑没有正确捕捉到这一点。另一个不行是将格雷码值作为一个整数,并比较两个整数。

如何比较两个相隔 250 毫秒的格雷码值并确定旋转方向,同时考虑到编码器的翻转方面?如果您愿意提供帮助,您能否提供一个简单的代码示例?

4

2 回答 2

4

假设 A 是您的初始读数,B 是 250 毫秒后的读数。
让我们在这里以 A = 950 和 B = 250 为例。

让我们假设编码器正在向前移动(它的值随着时间的推移而增加)。

那么,经过的距离为(B - A + 1024) % 1024。让我们称之为d_forward.

对于此示例,d_forward结果为(250 - 950 + 1024) % 1024= 324

向后覆盖的距离 ( d_backward) 将是1024 - d_forward; 这是700

的最小值d_forwardd_backward将给出编码器行进的方向。

如果编码器在 250 毫秒内移动超过 1023/2 个单位,这将不起作用。在这种情况下,您应该缩短读数之间的间隔。

于 2018-09-16T18:56:31.433 回答
3

Rishav 的答案是正确的,但可以更容易地计算出来。

AB是两个读数相隔 250 毫秒,并从格雷码转换为二进制。

编码器位置的差异只是diff = ((1536 + B - A) & 1023) - 512。如果您不想使用按位数学,那么diff = ((1536 + B - A) % 1024) - 512

注意 1536 是 1024+512,答案diff由两个约束决定:

  1. 差异 = BA mod 1024
  2. diff[-512, 511]范围内,这将是 10 位有符号数的正常范围。

如果您的编码器被允许/预期在一个方向上比另一个方向更快,那么您可以调整 (2) 中的范围。

要允许[MIN,MIN+1023]范围内的答案,请使用diff = ((1024 - MIN + B - A) % 1024) + MIN

如果MIN为正数,请在执行取模运算之前添加一个足够大的 1024 倍数以确保它是正数,因为大多数语言中的取模运算符对负数的行为很奇怪。

于 2018-09-16T20:06:40.810 回答