我有一个绝对编码器,它以格雷码输出 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
将给出编码器行进的方向。
如果编码器要在 1023 毫秒内移动超过 250 个单位,这将不起作用。在这种情况下,您应该减少读取读数之间的间隔。
里沙夫的答案是正确的,但可以更容易地计算出来。
设A和B是两个相隔 250 毫秒的读数,并从格雷码转换为二进制。
编码器位置的差异只是diff = ((1536 + B - A(和1023( - 512。 如果您不想使用按位数学,则diff = ((1536 + B - A( % 1024( - 512。
请注意,1536 是 1024+512,答案差异由两个约束决定:
- 差异 = B-A mod 1024
- diff在[-512, 511] 范围内,这将是 10 位有符号数字的正常范围。
如果您的编码器被允许/预期在一个方向上比另一个方向更快,那么您可以调整 (2( 中的范围。
要允许答案在[MIN,MIN+1023] 范围内,请使用 diff = ((1024 - 最小值 +B - A( % 1024( + 最小值
如果MIN为正数,请在执行模运算之前添加足够大的倍数 1024 以确保它是正数,因为大多数语言中的模运算符在负数时的行为很奇怪。