请提出一种比较格雷码编号的算法

时间:2018-09-16 18:44:04

标签: algorithm gray-code

我有一个绝对编码器,它以格雷码输出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毫秒的格雷码值,并在考虑编码器的滚动角度的同时确定旋转方向?如果您愿意提供帮助,请提供一个简单的代码示例?

2 个答案:

答案 0 :(得分:4)

假设A是您的初始读数,B是250ms之后的读数。
让我们以A = 950和B = 250为例。

让我们假设编码器向前移动(其值随时间增加)。

然后,覆盖的距离为(B - A + 1024) % 1024。我们称之为d_forward

在此示例中,d_forward(250 - 950 + 1024) % 1024 = 324

后退(d_backward)的覆盖范围为1024 - d_forward700

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

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

答案 1 :(得分:3)

里沙夫(Rishav)的答案是正确的,但计算起来更容易。

A B 是两个间隔250ms的读数,并从格雷码转换为二进制。

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

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

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

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

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

如果 MIN 为正数,则在进行模数运算之前,请添加一个足够大的1024倍数以确保其为正数,因为大多数语言中的模数运算符的行为与负数古怪。