我有一个绝对编码器,它以格雷码输出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毫秒的格雷码值,并在考虑编码器的滚动角度的同时确定旋转方向?如果您愿意提供帮助,请提供一个简单的代码示例?
答案 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_forward
; 700
。
d_forward
和d_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 由两个约束条件确定:
如果允许/预期编码器在一个方向上的移动速度要快于另一个方向,则可以在(2)中调整范围。
要允许答案在 [MIN,MIN + 1023] 范围内,请使用 diff =((1024-MIN + B-A)%1024)+ MIN < / p>
如果 MIN 为正数,则在进行模数运算之前,请添加一个足够大的1024倍数以确保其为正数,因为大多数语言中的模数运算符的行为与负数古怪。>