Danke euch allen.
So sieht das aus, was ich bis jetzt mit Hilfe von Teilen von py-gaugette zustande gebracht habe und immerhin läuft es:
Code: Alles auswählen
import math
import threading
import time
import wiringpi2
class GPIO:
def __init__(self):
self.gpio = wiringpi2.GPIO(wiringpi2.GPIO.WPI_MODE_PINS)
self.setup = self.wiringpi2_setup
self.output = self.gpio.digitalWrite
self.input = self.gpio.digitalRead
self.OUT = self.gpio.OUTPUT
self.IN = self.gpio.INPUT
self.HIGH = self.gpio.HIGH
self.LOW = self.gpio.LOW
self.PUD_UP = self.gpio.PUD_UP
self.PUD_DOWN = self.gpio.PUD_DOWN
self.PUD_OFF = self.gpio.PUD_OFF
def wiringpi2_setup(self, channel, direction, pull_up_down=None):
self.gpio.pinMode(channel, direction)
if pull_up_down is None: pull_up_down = self.gpio.PUD_OFF
self.gpio.pullUpDnControl(channel, pull_up_down)
class RotaryEncoder:
def __init__(self, a_pin, b_pin):
self.a_pin = a_pin
self.b_pin = b_pin
self.gpio = GPIO()
self.gpio.setup(self.a_pin, self.gpio.IN, self.gpio.PUD_DOWN)
self.gpio.setup(self.b_pin, self.gpio.IN, self.gpio.PUD_DOWN)
self.last_delta = 0
self.r_seq = self.rotation_sequence()
def rotation_sequence(self):
a_state = self.gpio.input(self.a_pin)
b_state = self.gpio.input(self.b_pin)
r_seq = (a_state ^ b_state) | b_state << 1
return r_seq
def get_delta(self):
delta = 0
r_seq = self.rotation_sequence()
if r_seq != self.r_seq:
delta = (r_seq - self.r_seq) % 4
if delta==3:
delta = -1
elif delta==2:
delta = int(math.copysign(delta, self.last_delta))
self.last_delta = delta
self.r_seq = r_seq
return delta
class Worker(threading.Thread):
def __init__(self, a_pin, b_pin, callback):
threading.Thread.__init__(self)
self.lock = threading.Lock()
self.callback = callback
self.encoder = RotaryEncoder(a_pin, b_pin)
self.daemon = True
self.delta = 0
def run(self):
while True:
event = 0
delta = self.encoder.get_delta()
with self.lock:
self.delta += delta
if abs(self.delta) >= 4:
event = self.delta//4
#print "hi there: %d" % (self.delta//4)
self.delta = self.delta%4
if event != 0:
self.callback(event)
time.sleep(0.003)
def get_delta(self):
with self.lock:
delta = self.delta//4
self.delta = self.delta%4
return delta
def rotary_event(event):
if event == -2:
print "zwei nach links"
elif event == -1:
print "nach links"
elif event == 1:
print "nach rechts"
elif event == 2:
print "2 nach rechts"
return
A1_PIN = 28
B1_PIN = 29
encoder = RotaryEncoder.Worker(A1_PIN, B1_PIN, rotary_event)
encoder.start()
while 1:
time.sleep(10)
aber irgendwie kommt mir das mit den Callbackfunktionen noch verkehrt herum vor. ich hätte mir vorgestellt, dass der Workerthread einfach die Events abliefert und dann das Hauptprogramm, je nachdem wie es ihm gerade in den Kram paßt darauf reagiert oder nicht, aber hier muss ich ja schon im Vorhinein die Routinen festlegen, die aufgerufen werden sollen.
Jetzt wäre ich sehr daran interessiert zu hören, was ich falsch oder schlecht gemacht habe (bzw. Guy Carpenter, der py-gaugette geschrieben hat und auf den ich mich ausreden werde
). Zum Beispiel die self.lock Geschichte kann ich mir vermutlich, so wie ich das geändert habe, vermutlich ersparen?
(
Original von Guy Carpenter)
Wenn ihr darüber hinaus noch Vorschläge hättet, wie ein Programm aufgebaut sein könnte, das in unterschiedlichen Situationen/Modi unterschiedlich auf Tastendrücke oder den Drehimpulsgeber reagieren soll, wäre das noch großartiger. Dabei soll eigentlich eine richtige (rudimentäre) Menüführung herauskommen.
(wenn ich mit lauter/leiser, nächstes/voriges Stück und Play/Pause zufrieden wäre, wäre ich an dieser Stelle ja schon so gut wie fertig)
lg smutbert