编辑2 经过更多测试后,我注意到以下解释的问题,甚至将脚本作为模块导入。 (相应更改标题)
我正在从事一个物联网项目,该项目需要将旋转编码器连接到Raspberry pi。
我发现一些python库和各种脚本(通常基于计时)可与编码器一起使用,但是这些都无法可靠地工作。 通常,主要的问题是快速旋转编码器时:获得的值在不遵循旋转方向的情况下上下波动。 也许是由于树莓硬件不够快引起的。
但是,我写了一个绝对不完美的脚本(基于gpiozero库),它会时不时地缺少编码器的一些输入,但是它解决了上述问题:当您顺时针旋转时值会升高,而会降低另一种方法。这就是我所需要的。
然后,我尝试创建该代码的类(以防万一,我必须使用多个编码器),但是这样做会使我的代码缺少设备中的许多输入,因此几乎无法使用。 我仍在学习python和所有这些东西,所以我不知道问题是否出在我的代码中,或者它是否可能是树莓的有限硬件。
编辑了更多信息
使用编码器的每个输入(只需单击一个步骤即可旋转编码器),您将获得4个不同的事件,可以从序列中实现:
旋转时钟
dt pressed (dt value = 1)
clk pressed (clk value = 1)
dt released (dt value = 0)
clk released (clk value = 0)
逆时针旋转
clk pressed (clk value = 1)
dt pressed (dt value = 1)
clk released (clk value = 0)
dt released (dt value = 0)
因此,在我的代码中,我只需检查此序列即可确定方向并避免出现不需要的值,因为快速旋转编码器会产生意外的值。
它适用于脚本,但使用该类的次数很多,甚至没有完成。例如,顺时针旋转仅获得dt pressed -> dt released
,逆时针旋转仅获得clk pressed -> clk released
。这种行为使我认为代码执行速度不够快。
这是脚本代码:
from gpiozero import Button
'''
Sequence of values that the rotary encoder output for every step/click.
Sequence -> dt 1 / clk 1 / dt 0 / clk 0
Sequence <- clk 1 / dt 1 / clk 0 / dt 0
'''
def clk_pressed():
global sequence
if len(sequence) > 2:
sequence.clear()
sequence.append('clk1')
def clk_released():
global sequence, counter
sequence.append('clk0')
if sequence == sequence_up:
if counter < max:
counter += scale
print(counter)
sequence.clear()
def dt_pressed():
global sequence
if len(sequence) > 2:
sequence.clear()
sequence.append('dt1')
def dt_released():
global sequence, counter
sequence.append('dt0')
if sequence == sequence_down:
if counter > min:
counter -= scale
print(counter)
sequence.clear()
clk = Button(27)
clk.when_pressed = clk_pressed
clk.when_released = clk_released
dt = Button(22)
dt.when_pressed = dt_pressed
dt.when_released = dt_released
sequence = []
sequence_up = ['dt1', 'clk1', 'dt0', 'clk0']
sequence_down = ['clk1', 'dt1', 'clk0', 'dt0']
counter = 0
min = 0
max = 100
scale = 5
message = input("Press ENTER to quit")
这是课程:
from gpiozero import Button
'''
Sequence of values that the rotary encoder output for every step/click.
Sequence -> dt 1 / clk 1 / dt 0 / clk 0
Sequence <- clk 1 / dt 1 / clk 0 / dt 0
'''
class Rotary:
sequence = []
sequence_up = ['dt1', 'clk1', 'dt0', 'clk0']
sequence_down = ['clk1', 'dt1', 'clk0', 'dt0']
counter = 0
last_counter = 0
clk_input = None
dt_input = None
def __init__(self, clk, dt, min, max, delta):
self.clk = clk
self.dt = dt
self.min = min
self.max = max
self.delta = delta
def clk_pressed():
if len(self.sequence) > 2:
self.sequence.clear()
self.sequence.append('clk1')
def clk_released():
self.sequence.append('clk0')
if self.sequence == self.sequence_up:
if self.counter < self.max:
self.counter = self.counter + self.delta
return self.counter
self.sequence.clear()
def dt_pressed():
if len(self.sequence) > 2:
self.sequence.clear()
self.sequence.append('dt1')
def dt_released():
self.sequence.append('dt0')
if self.sequence == self.sequence_down:
if self.counter > self.min:
self.counter = self.counter - self.delta
return self.counter
self.sequence.clear()
self.clk_input = Button(self.clk)
self.clk_input.when_pressed = clk_pressed
self.clk_input.when_released = clk_released
self.dt_input = Button(self.dt)
self.dt_input.when_pressed = dt_pressed
self.dt_input.when_released = dt_released
def watch(self):
while True:
if self.counter != self.last_counter:
print(self.counter)
self.last_counter = self.counter
所以现在我可以创建实例并甚至使用线程调用watch方法:
from rotary import Rotary
import threading
my_rotary = Rotary(clk=27, dt=22, min=0, max=100, delta=5)
my_thread = threading.Thread(target=my_rotary.watch)
my_thread.start()
# while True:
# my_rotary.watch()
很抱歉,很长的帖子。 任何提示真的很感激。 谢谢。