vash3d / pigpio_encoder Goto Github PK
View Code? Open in Web Editor NEWPython module for the KY040 rotary encoder.
License: GNU General Public License v3.0
Python module for the KY040 rotary encoder.
License: GNU General Public License v3.0
Please add a wrap-around mode for encoder counter value. Example:
You have a range of 0-100 set in the encoder object. When you turn the encoder knob clockwise, the counter counts up until it reaches 100 and then counts up from 0 with additional clockwise turning. Conversely, when turning the knob counterclockwise, the counter counts down until it reaches 0 and then counts down from 100 with additional counterclockwise turning.
Dear @vash3d!
Thank you very much for accepting my pullrequest and to give me admin access to this repo.
Since there was no much conversation I accepted my own last pull request.
Is this OK for you? Please give me a hint what you are intending with this repo and what the rules are to mess with it.
If you like me to become the maintainer I am willing to do so.
Cheers,
Volker
Would be really nice if we can have a callback that just report a clockwise or counterclockwise rotation (maybe 2 different callback?) without any sens of scale / counter.
The way that this module is implemented : the callback doesn't get triggered if the counter is = min and we turn the encoder counterclockwise (same if counter = max and we turn the encoder clockwise)
Hi again,
I've notice in your code the following error on line 108 and 109:
if 'debouce' in kwargs: self.debounce = kwargs['debouce']
debouce should be replaced by debounce.
best regards
The setup_switch() method has a debounce parameter but it never gets used to adjust switch debounce (nor for anything else).
I have a project in which I scroll through a list with a rotary encoder. Is use short press to select an item in the list and a long press to jump to the next list where I repeat the process.
Is there a way of resetting the counter when I jump to the next list?
Many thanks
Hi. I'll start with I'm very new to Python so I may be overlooking a simple solution. I'm having difficulty with using threading to implement multiple rotary encoders. I'm using a Raspberry Pi4 and my implementation of threading is based on the multiple encoder example found here: https://github.com/raphaelyancey/pyKY040. I'm assuming since pigpio_encoder is similar, I can use the same method for multiple encoders.
With my current script below, the response time to encoder input is noticeably slow. It appears to not be able to keep up with the rotation of the encoder. If I comment out the lines under #Rotary one or #Rotary two, the response time is better but a bit more performance would be nice. When I use the multiple encoder example from the link above, response time is even faster. I'm assuming that may be due to it being a simpler module.
Would you have any suggestions for how I could optimize this code for faster performance? I prefer pigpio_encoder over pyKY040 because of the additional features such as long press.
Thanks
My Current Script
from pigpio_encoder import pigpio_encoder
import threading
import time
import datetime
def rotary_callback(counter):
print(datetime.datetime.now().strftime('%H:%M:%S.%f')[:-3] + " - " + "Counter value: ", counter)
def sw_short():
print("Switch short press")
def sw_long():
print("Switch long press")
def rotary_callback_two(counter):
print("Counter2 value: ", counter)
def sw_short_two():
print("Switch2 short press")
def sw_long_two():
print("Switch2 long press")
#Rotary one
my_rotary = pigpio_encoder.Rotary(clk=18, dt=17, sw=19)
my_rotary.setup_rotary(min=0, max=100, scale=1, debounce=100, rotary_callback=rotary_callback)
my_rotary.setup_switch(debounce=200, long_press=True, sw_short_callback=sw_short, sw_long_callback=sw_long)
my_thread = threading.Thread(target=my_rotary.watch)
my_thread.start()
#Rotary two
my_rotary_two = pigpio_encoder.Rotary(clk=13, dt=12, sw=16)
my_rotary_two.setup_rotary(min=0, max=100, scale=1, debounce=100, rotary_callback=rotary_callback_two)
my_rotary_two.setup_switch(debounce=200, long_press=True, sw_short_callback=sw_short_two, sw_long_callback=sw_long_two)
my_thread_two = threading.Thread(target=my_rotary_two.watch)
my_thread_two.start()
#Do other stuff
print('Other stuff...')
while True:
print('LoopedResponse tim stuff...')
time.sleep(1000)
This is output for my current script with two encoders enabled. I'm rotating the encoder clockwise with my fingers.
Other stuff...
Looped stuff...
14:15:46.059 - Counter value: 1
14:15:48.166 - Counter value: 2
14:15:48.210 - Counter value: 3
14:15:48.269 - Counter value: 4
14:15:48.640 - Counter value: 5
14:15:48.782 - Counter value: 6
14:15:49.968 - Counter value: 7
14:15:49.995 - Counter value: 6
14:15:50.035 - Counter value: 7
14:15:50.462 - Counter value: 8
14:15:51.039 - Counter value: 9
14:15:51.569 - Counter value: 10
14:15:51.592 - Counter value: 11
14:15:51.615 - Counter value: 12
14:15:51.637 - Counter value: 13
14:15:51.671 - Counter value: 15
14:15:51.693 - Counter value: 16
14:15:52.189 - Counter value: 17
This is output for my current script with the second encoder commented out. The script detects more movement.
Other stuff...
Looped stuff...
14:16:52.406 - Counter value: 1
14:16:52.489 - Counter value: 2
14:16:52.611 - Counter value: 3
14:16:53.023 - Counter value: 4
14:16:53.049 - Counter value: 5
14:16:53.145 - Counter value: 6
14:16:53.535 - Counter value: 7
14:16:53.598 - Counter value: 8
14:16:53.668 - Counter value: 9
14:16:54.059 - Counter value: 10
14:16:54.149 - Counter value: 11
14:16:54.229 - Counter value: 12
14:16:54.640 - Counter value: 13
14:16:54.728 - Counter value: 14
14:16:54.755 - Counter value: 15
14:16:55.163 - Counter value: 16
14:16:55.235 - Counter value: 17
14:16:55.574 - Counter value: 18
14:16:55.611 - Counter value: 17
14:16:55.689 - Counter value: 18
14:16:56.038 - Counter value: 19
14:16:56.081 - Counter value: 18
14:16:56.098 - Counter value: 19
14:16:56.115 - Counter value: 20
This is output for pyky040 script I'm using (code below) two encoders enabled. It's very fast.
Other stuff...
Looped stuff...
14:19:19.438 - Hello world! The scale position is 1
14:19:19.468 - Hello world! The scale position is 2
14:19:19.487 - Hello world! The scale position is 3
14:19:19.503 - Hello world! The scale position is 4
14:19:19.512 - Hello world! The scale position is 5
14:19:19.525 - Hello world! The scale position is 6
14:19:19.531 - Hello world! The scale position is 7
14:19:19.541 - Hello world! The scale position is 8
14:19:19.547 - Hello world! The scale position is 9
14:19:19.557 - Hello world! The scale position is 10
14:19:19.562 - Hello world! The scale position is 11
14:19:19.571 - Hello world! The scale position is 12
14:19:19.576 - Hello world! The scale position is 13
14:19:19.586 - Hello world! The scale position is 14
14:19:19.593 - Hello world! The scale position is 15
14:19:19.603 - Hello world! The scale position is 16
14:19:19.611 - Hello world! The scale position is 17
14:19:19.626 - Hello world! The scale position is 18
14:19:20.003 - Hello world! The scale position is 19
14:19:20.023 - Hello world! The scale position is 20
14:19:20.031 - Hello world! The scale position is 21
14:19:20.043 - Hello world! The scale position is 22
14:19:20.048 - Hello world! The scale position is 23
14:19:20.057 - Hello world! The scale position is 24
My Pyky040 Script
#https://pypi.org/project/pyky040/
#https://github.com/raphaelyancey/pyKY040
#Import the module and threading
from pyky040 import pyky040
import threading
import time
import datetime
def my_callback(scale_position):
print(datetime.datetime.now().strftime('%H:%M:%S.%f')[:-3] + ' - ' + 'Hello world! The scale position is {}'.format(scale_position))
def button():
print('Button pressed')
def my_callback_two(scale_position):
print('Hello world! The scale position2 is {}'.format(scale_position))
def button_two():
print('Button2 pressed')
my_encoder = pyky040.Encoder(CLK=17, DT=18, SW=19)
my_encoder.setup(scale_min=0, scale_max=100, step=1, chg_callback=my_callback, sw_callback=button)
my_thread = threading.Thread(target=my_encoder.watch)
my_thread.start()
my_encoder_two = pyky040.Encoder(CLK=12, DT=13, SW=16)
my_encoder_two.setup(scale_min=0, scale_max=100, step=1, chg_callback=my_callback_two, sw_callback=button_two)
my_thread_two = threading.Thread(target=my_encoder_two.watch)
my_thread_two.start()
#Do other stuff
print('Other stuff...')
while True:
print('Looped stuff...')
time.sleep(1000)
Thanks for the project. It works great.
Is there a way to have it increment the counter when rotating clockwise?
Hello vash3d,
Thanks for your library.
I encountered an error which seems to be linked to list.clear() function which is a python3 function while pigpio_encoder is installed on python2.7 distribution libraries with pip.
Here is the terminal output
Traceback (most recent call last): File "/usr/lib/python2.7/threading.py", line 801, in __bootstrap_inner self.run() File "/usr/lib/python2.7/dist-packages/pigpio.py", line 1181, in run cb.func(cb.gpio, newLevel, tick) File "/usr/local/lib/python2.7/dist-packages/pigpio_encoder/pigpio_encoder.py", line 61, in dt_fall self.sequence.clear() AttributeError: 'list' object has no attribute 'clear'
Maybe I'm doing something wrong. Let me know if its an issue on my side.
Best regard,
mm
The threshold time for the long push seems pretty long.
Could you add a kwarg to setup_switch()?
The watch() loop should examine the value of a variable that tells it when to exit. The variable would be set in one of the callbacks.
When i call the setup_rotary function with a min argument, the program tries to set the counter. But its setter calls the rotary_callback function, which at this time is not defined yet.
My code:
my_rotary.setup_rotary(min=-1, max=1, scale=1, rotary_callback=rotary_callback)
Error:
File "main.py", line 13, in <module>
my_rotary.setup_rotary(min=10, max=300, scale=5, debounce=200, rotary_callback=rotary_callback)
File "/home/pi/Desktop/pigpio_encoder/src/pigpio_encoder.py", line 119, in setup_rotary
self.counter = self.min
File "/home/pi/Desktop/pigpio_encoder/src/pigpio_encoder.py", line 71, in counter
self.rotary_callback(self._counter)
TypeError: 'NoneType' object is not callable
Hello i have try many libs but i have problem to gat the counter value just in time
I have try your lib but i gat the following error:
i copy your example:
from pigpio_encoder.rotary import Rotary
def rotary_callback(counter):
print("Counter value: ", counter)
def sw_short():
print("Switch pressed")
def up_callback():
print("Up rotation")
def down_callback():
print("Down rotation")
my_rotary = Rotary(clk_gpio=27, dt_gpio=22, sw_gpio=17)
my_rotary.setup_rotary(
rotary_callback=rotary_callback,
up_callback=up_callback,
down_callback=down_callback,
)
my_rotary.setup_switch(sw_short_callback=sw_short)
my_rotary.watch()
up_callback() takes 0 positional arguments but 1 was given
Can you help me
Thanks
So, apparently, I got something backwards,
Did the installations steps as the readme file states, copied the samples and I got this output:
ImportError: cannot import name 'Rotary' from 'pigpio_encoder' (/home/pi/.local/lib/python3.7/site-packages/pigpio_encoder/init.py)
My code looks like this:
from pigpio_encoder import Rotary
def rotary_callback(counter):
print("Counter value: ", counter)
def sw_short():
print("Switch pressed")
def up_callback():
print("Up rotation")
def down_callback():
print("Down rotation")
my_rotary = Rotary(clk=27, dt=22, sw=17)
my_rotary.setup_rotary(
rotary_callback=rotary_callback,
up_callback=up_callback,
down_callback=down_callback,
)
my_rotary.setup_switch(sw_short_callback=sw_short)
my_rotary.watch()
Now, if I do:
from pigpio_encoder import pigpio_encoder
...
my_rotaryi = pigpio_encoder.Rotary(clk=27, dt=22, sw=17)
It runs with no issues but, the up_callback and down_callback do not work, or at least, nothing is displayed for them, but the counter works just fine!
Image attached is from the counter working with the basic config as the samples here on github!
Hello,
I'm trying to run pigpio_encoder but I'm facing this issue
pigpio encoder needs 2 encoder steps to trigger callbacks
does any one know why? do I need to setup something else
self.encoder = Rotary(
clk_gpio=23,
dt_gpio=18,
sw_gpio=17
)
self.encoder.setup_rotary(
min=0,
max=120,
scale=1,
debounce=200,
rotary_callback=self.encoder_activity,
up_callback=self.encoder_up,
down_callback=self.encoder_down
)
self.encoder.setup_switch(
debounce=200,
long_press=True,
sw_short_callback=self.encoder_short,
sw_long_callback=self.encoder_long
)
I'm not calling watch
thanks
I'd like to use this for a robot with two motors and two wheels. Can the library run two instances of "rotary encoder"?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.