前言:
当前咱们对“旋转屏幕算法”可能比较关切,我们都想要知道一些“旋转屏幕算法”的相关知识。那么小编同时在网摘上网罗了一些关于“旋转屏幕算法””的相关文章,希望同学们能喜欢,咱们快快来了解一下吧!旋转编码器控制的另一种算法操作原理
旋转编码器是通常将轴的角运动转换为数字输出信号的设备。有许多 Web 资源解释了这些设备的机制以及如何将它们连接到微型计算机,但本页并非完整的概述。这个想法是提出另一种算法来正确读取机械旋转编码器的输出。
原则上,常见的旋转编码器通过交替闭合两个开关来产生信号,如上图所示。根据连接,中性状态可以是高 (1) 或低 (0)。我们在这里假设中性状态为高的最常见连接。对于顺时针运动,第一个开关的动作先于第二个开关的动作,而逆时针运动则相反。如果我们将每个状态表示为二进制数,两位数字表示两个开关的状态,则中性状态表示为11, 顺时针旋转由状态链表示11→01→00→10→11逆时针旋转由状态链表示11→10→00→01→11.
开关弹跳
问题是机械电气开关不完善,所以会出现开关弹跳的现象。当切换开关时,触点必须从一个位置物理移动到另一个位置。当开关的组件进入新位置时,它们会机械弹跳,导致底层电路多次打开和关闭。得到的信号如上图所示。
这个问题可以通过硬件或软件来解决。在软件的情况下,这涉及到某个主观确定的保持时间,在此期间开关的活动被忽略。然而,在旋转开关的情况下,我们可以完全避免保持时间。由于这对开关经过四个连续的状态,我们原则上可以准确地定义操作何时完成。
算法
微处理器一共可以读出四种不同的状态,连续两次读出总共给出了十六种可能的转换,如上图所示。四个过渡代表没有移动,四个过渡代表向右四分之一移动,四个过渡代表向左四分之一移动,四个过渡代表理论上不可能的过渡。
让我们将一个完整的周期定义为一个以中性状态开始和结束的过程。通过指定 0 表示没有移动,+1 表示向右移动四分之一,-1 表示向左移动四分之一,我们得到 +4 的总和表示向右的一个完整周期,-4 的总和表示一个完整的周期循环向左,总和为 0 表示没有移动。特别是,每个单独的开关弹跳,无论是向左还是向右,总和为 0,对结果没有影响。此外,聚合和 4 的模数为我们提供了确切的状态。例如,如果模数为零,则当前状态为中性状态。
必须特别注意“不可能”的转换。由于技术上的不足,它们确实是可能的。如果我们将值 0 分配给不可能的转换,则具有恰好一个不可能转换的完整循环的总和是 -6、-2、+2 或 +6。要认识到整个循环包含一个(或多个)不可能的转换,我们必须为不可能的转换分配一个大于 10 的数字,以便整个循环的总和大于 4。但是,如果我们分配数字 14 ,我们不仅认识到不可能转换的存在,而且当且仅当达到中性状态时,聚合的模数和 4 再次为零。
执行
所有这些考虑因素都可以在以下 Python 脚本中观察到,该脚本旨在用于 Raspberry Pi。rotary函数首先更新,lrmem一个四位二进制变量,其中前两位表示前一个状态,后两位表示当前状态,本质上是最后一次转换。该列表TRANS包含每个转换的值,如下表所示。
lrmem
转型
TRANS
评论
0b0000
00→00
0
没有动静
0b0001
00→01
-1
向左移动
0b0010
00→10
+1
向右移动
0b0011
00→11
+14
不可能的运动
0b0100
01→00
+1
向右移动
0b0101
01→01
0
没有动静
0b0110
01→10
+14
不可能的运动
0b0111
01→11
-1
向左移动
0b1000
10→00
-1
向左移动
0b1001
10→01
+14
不可能的运动
0b1010
10→10
0
没有动静
0b1011
10→11
+1
向右移动
0b1100
11→00
+14
不可能的运动
0b1101
11→01
+1
向右移动
0b1110
11→10
-1
向左移动
0b1111
11→11
0
没有动静
然后该rotary函数更新lrsum包含当前聚合的变量。当达到中性状态时,该功能相应地起作用。
树莓派的 Python 代码
import pigpiopi = pigpio.pi()# -1: left transition, +1: right transition, 0: no transition and 14: impossible transitionTRANS = [0, -1, 1, 14, 1, 0, 14, -1, -1, 14, 0, 1, 14, 1, -1, 0]LEFT = 16RIGHT = 20PUSH = 21def rotary(): global lrmem global lrsum l = pi.read(LEFT) r = pi.read(RIGHT) lrmem = (lrmem % 4)*4 + 2*l + r lrsum = lrsum + TRANS[lrmem] # encoder not in the neutral state if(lrsum % 4 != 0): return(0) # encoder in the neutral state if (lrsum == 4): lrsum=0 return(1) if (lrsum == -4): lrsum=0 return(-1) # lrsum > 0 if the impossible transition lrsum=0 return(0)pi.set_mode(LEFT, pigpio.INPUT)pi.set_mode(RIGHT, pigpio.INPUT)pi.set_mode(PUSH, pigpio.INPUT)pi.set_pull_up_down(LEFT, pigpio.PUD_UP)pi.set_pull_up_down(RIGHT, pigpio.PUD_UP)pi.set_pull_up_down(PUSH, pigpio.PUD_UP)lrmem = 3lrsum = 0num = 0print(num)while(True): res = rotary() if (res!=0): num=num + res print(num) if(pi.read(PUSH)==0): break
请注意,不需要额外的电子组件,因为脚本使用内置的 Raspberry Pi 上拉电阻。
Arduino的C代码
#define LEFT 2#define RIGHT 3#define PUSH 4uint8_t lrmem = 3;int lrsum = 0;int num = 0;int8_t rotary(){ static int8_t TRANS[] = {0,-1,1,14,1,0,14,-1,-1,14,0,1,14,1,-1,0}; int8_t l, r; l = digitalRead(LEFT); r = digitalRead(RIGHT); lrmem = ((lrmem & 0x03) << 2) + 2*l + r; lrsum = lrsum + TRANS[lrmem]; /* encoder not in the neutral state */ if(lrsum % 4 != 0) return(0); /* encoder in the neutral state */ if (lrsum == 4) { lrsum=0; return(1); } if (lrsum == -4) { lrsum=0; return(-1); } /* lrsum > 0 if the impossible transition */ lrsum=0; return(0);}void setup(){ pinMode(LEFT, INPUT); pinMode(RIGHT, INPUT); pinMode(PUSH, INPUT); pinMode(LEFT, INPUT_PULLUP); pinMode(RIGHT, INPUT_PULLUP); pinMode(PUSH, INPUT_PULLUP); Serial.begin(9600); Serial.println(num, DEC);}void loop(){ int8_t res; res = rotary(); if (res!=0) { num = num + res; Serial.println(num); } if (digitalRead(PUSH) == 0) { Serial.println(num); delay(250); }}
标签: #旋转屏幕算法