请建议一种算法来比较格雷码数



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

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

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 毫秒的两个格雷码值,并在考虑编码器翻转方面的情况下确定旋转方向?如果您愿意提供帮助,您能否提供一个简单的代码示例?

假设A是你的初始读数,B是250ms后的读数。
让我们以 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将给出编码器行进的方向。

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

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

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

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

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

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

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

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

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

最新更新