请提供一种比较格雷码数字的算法。

3
我有一个绝对编码器,它输出一个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)时,尽管我在物理上沿着相同的方向移动,但我编写的逻辑不能正确捕捉到这一点。另一个不行的方案是将Gray码值作为int进行比较。
如何比较两个Gray码值,它们相隔250毫秒,并在考虑编码器溢出方面确定旋转方向? 如果您能够帮助,可以提供一个简单的代码示例吗?

1
你期望你的编码器在250毫秒的间隔内移动多少? - xrisk
返回仅翻译文本:最多不超过400个脉冲(粗略估计)。但当它从950到250时,我的算法无法工作。 - Mike
1
一种方法是计算读数之间的差异,假设您正在“向前”和“向后”移动。然后,您假定编码器沿较小值的方向移动。当然,如果您的编码器将在250毫秒内行驶超过一半的间隔,则此方法会失败;在这种情况下,您需要增加采样频率。 - xrisk
S2-S1的结果在-1023到+1023的范围内;在该范围内,-1023〜-512和+1〜+511是向前的,而-511〜-1和512〜1023是向后的。 - m69 ''snarky and unwelcoming''
@m69,没有负数范围。这些值的范围限制在0到1023之间。根据这些值之间的差异,我正在尝试确定旋转方向。 - Mike
我在谈论“SampleTwo - SampleOne”的范围。如果S1=990,S2=12,则S2-S1=-978,在-1023〜-512的范围内,这意味着向前。 - m69 ''snarky and unwelcoming''
2个回答

4
假设A是您的初始读数,B是250毫秒后的读数。 假设编码器在向前移动(它的值随时间增加)。 那么,所覆盖的距离为(B-A+1024)%1024。我们称之为d_forward。 对于这个例子,d_forward为(250-950+1024)%1024=324。 向后行驶的距离(d_backward)将是1024-d_forward,即700。 d_forward和d_backward的最小值将给出编码器行驶的方向。 如果编码器在250毫秒内要行驶超过1023/2个单位,则此方法不起作用。在这种情况下,您应该减少获取读数之间的时间间隔。

我非常惊讶这是正确的答案。我本以为Frank Gray先生也会创建一些数学运算符来配合他的系统。我向你Rishav致敬...谢谢! - Mike

3

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

AB是两个读数,相隔250毫秒,并将它们从灰码转换为二进制。

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

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

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

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

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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接