Open coreyblosser opened 3 years ago
@coreyblosser Thank you for choosing pigpio_encoder! I think the problem is that you are using the watch function. This function is there only for backward compatibility but should NOT be used. The pigpio_ecoder lib is interrupt driven so you need no loop. I have not tried but I am quite sure that you even do not need two threads to operate two encoders in parallel.
So my suggestion is to drop the treads and the watch func and look what happens.
You will just need to have a single final loop for your code to wait, or a thread or so.
Cheers, Volker
@coreyblosser I also noticed that you have set the debounce time to 100ms. This gives you a general 100ms delay. Before using debounce at all - try without. If the noise is to strong (e.g. you will see more than one step per step or missing steps) crank up the debounce time in 10ms increments till you reach a stable operation. Different encoders (or encoder models) have quite different characteristic so for each one the debounce has to be adjusted. But at first try without . I have some cheap china encoders that run really fine without debouncing.
Cheers, Volker
@volkerjaenisch Thanks for your guidance. I started a new script, based on the "example using all features" found here: https://pypi.org/project/pigpio-encoder. I removed the debounce and .watch(). If understood correctly, I believe this is the direction you suggested.
The good news is the button presses for both encoders work but there is no output when turning the encoders. If I replace the while loop with my_rotary.watch(), I can see output for button presses and turning the both encoders. Am I missing a detail?
Corey
from pigpio_encoder import pigpio_encoder
def rotary_callback(counter): print("Counter value: ", counter) def sw_short(): print("Switch short press") def sw_long(): print("Switch long press")
def rotary_callback_two(counter): print("Counter value2: ", counter) def sw_short_two(): print("Switch2 short press") def sw_long_two(): print("Switch2 long press")
my_rotary = pigpio_encoder.Rotary(clk=18, dt=17, sw=19) my_rotary.setup_rotary(min=0, max=100, scale=1, rotary_callback=rotary_callback) my_rotary.setup_switch(long_press=True, sw_short_callback=sw_short, sw_long_callback=sw_long)
my_rotary_two = pigpio_encoder.Rotary(clk=13, dt=12, sw=16) my_rotary_two.setup_rotary(min=0, max=100, scale=1, rotary_callback=rotary_callback_two) my_rotary_two.setup_switch(long_press=True, sw_short_callback=sw_short_two, sw_long_callback=sw_long_two)
while(True): pass
@coreyblosser The code looks perfect to me. What version of pigpio_encoder are you using? If you comment out the second encoder, does the first one work?
@volkerjaenisch pigpiod -v shows version 79 and I'm using Python 3.7.3
When I comment out the second encoder, the behavior does not change. Short and long button presses work but no output when turning the first encoder. With the second encoder commented out, if I also comment out the while loop and uncomment the my_rotary.watch(), I see output for button presses and turning the encoder.
@volkerjaenisch I notice the distribution version of pigpio_encoder I have is 0.2.2 but I see 0.2.5 on Github. Could that be significant?
@coreyblosser
I notice the distribution version of pigpio_encoder I have is 0.2.2 but I see 0.2.5 on Github. Could that be significant?
Therefore my question for the version. Please use the version from GH. I will deploy the 0.2.5 version as Python package on PyPI in the next hours
With the second encoder commented out, if I also comment out the while loop and uncomment the my_rotary.watch(), I see output for button presses and turning the encoder.
This is really strange. If you please have a look at .watch() :
@staticmethod def watch(): """ A simple convenience function to have a waiting loop """ while True: time.sleep(10)
It is no more than a loop. But the problem may be that your loop does eat up all CPU since it has no wait in it.
Can you please give your loop a wait and test again. Mainwhile I do the deployment to PyPI.
Cheers, Volker
Current Version 0.2.4 is now available on PyPI.
@volkerjaenisch I was able to install the 0.2.4 version. All works with both encoders. This is great! Thanks for all of your help!
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)