请建议一种算法来比较格雷码数
Please suggest an algorithm to compare Gray code numbers
我有一个绝对编码器,它以格雷码形式输出 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_forward
和 d_backward
中的最小值将给出编码器行进的方向。
如果编码器要在 250 毫秒内移动超过 1023/2 个单位,这将 不起作用 。在这种情况下,您应该减少读取之间的间隔。
Rishav 的答案是正确的,但更容易计算。
令 A 和 B 是相隔 250 毫秒并从格雷码转换为二进制的两个读数。
编码器位置的差异只是 diff = ((1536 + B - A) & 1023) - 512。如果您不想使用按位数学,那么 diff = ((1536 + B - A) % 1024) - 512.
注意1536是1024+512,答案diff由两个约束决定:
- 差异 = B-A mod 1024
- diff 在 [-512, 511] 范围内,这是 10 位有符号数的正常范围.
如果您的编码器 allowed/expected 在一个方向上比另一个方向走得更快,那么您可以调整 (2) 中的范围。
要允许答案在 [MIN,MIN+1023] 范围内,请使用 diff = ((1024 - MIN + B - A) % 1024) + 最小值
如果 MIN 为正数,请添加足够大的 1024 倍数以确保在执行 modulus 运算之前它为正数,因为 mod大多数语言中的 ulus 运算符在处理负数时表现得很奇怪。
我有一个绝对编码器,它以格雷码形式输出 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_forward
和 d_backward
中的最小值将给出编码器行进的方向。
如果编码器要在 250 毫秒内移动超过 1023/2 个单位,这将 不起作用 。在这种情况下,您应该减少读取之间的间隔。
Rishav 的答案是正确的,但更容易计算。
令 A 和 B 是相隔 250 毫秒并从格雷码转换为二进制的两个读数。
编码器位置的差异只是 diff = ((1536 + B - A) & 1023) - 512。如果您不想使用按位数学,那么 diff = ((1536 + B - A) % 1024) - 512.
注意1536是1024+512,答案diff由两个约束决定:
- 差异 = B-A mod 1024
- diff 在 [-512, 511] 范围内,这是 10 位有符号数的正常范围.
如果您的编码器 allowed/expected 在一个方向上比另一个方向走得更快,那么您可以调整 (2) 中的范围。
要允许答案在 [MIN,MIN+1023] 范围内,请使用 diff = ((1024 - MIN + B - A) % 1024) + 最小值
如果 MIN 为正数,请添加足够大的 1024 倍数以确保在执行 modulus 运算之前它为正数,因为 mod大多数语言中的 ulus 运算符在处理负数时表现得很奇怪。