Hallo, ich bin ganz neu hier und brauche dringend Unterstützung.
Mit einem Keyboard (Rii Mini i8+/2.4 GHz) möchte ich auf meinem Raspberry 3B+ 2 Servos fernsteuern und ein Roboterauto bewegen. Dazu muss ich feststellen, welche Taste gedrückt wird. Das schaffe ich, auch bei Sondertasten, die eigntlich für Lautstärke- und Videosteuerung vorgesehen sind.
Mein Problem liegt aber darin, dass ich die Variablen, die für die sukzessive Bewegung der Servos vorgesehen sind, nicht ändern kann.
Der Programmcode funktioniert nur, wenn ich feste Werte eingebe, nicht wenn ich die Variablen ändere.
Im folgenden Python-Code sind die Zeilen, die einen Abbruch-Fehler hervorrufen deaktiviert (##).
Hat jemand eine Idee, was ich falsch mache?
Danke für jeden zielführenden Hinweis.
Anbei der Python-Code:
from __future__ import division
import sys, tty, termios, os, readchar
import pynput
from pynput import keyboard
import time
import pygame
pygame.init()
# Import the PCA9685 module.
import Adafruit_PCA9685
Taste = ""
servo_lr_akt = 400
servo_lr_min = 130
servo_lr_max = 730
servo_hr_akt = 400
servo_hr_min = 130
servo_hr_max = 730
currentlyRunning = True
# Initialise the PCA9685 using the default address (0x40).
pwm = Adafruit_PCA9685.PCA9685()
pwm.set_pwm(0, 0, servo_lr_akt)
pwm.set_pwm(0, 0, servo_lr_akt)
def set_servo_pulse(channel, pulse):
pulse_length = 1000000 # 1,000,000 us per second
pulse_length //= 60 # 60 Hz
print('{0}us per period'.format(pulse_length))
pulse_length //= 4096 # 12 bits of resolution
print('{0}us per bit'.format(pulse_length))
pulse *= 1000
pulse //= pulse_length
pwm.set_pwm(channel, 0, pulse)
def on_press(key):
try:
print('Key {0} pressed'.format(key.char))
except AttributeError:
print('Key {0} pressed'.format(key))
def on_release(key):
print('{0} released'.format(key))
print(key)
Taste = str(key)
print(Taste)
if Taste.find("269025046") == True:
##servo_lr_akt = servo_lr_akt + 5
pwm.set_pwm(0, 0, servo_lr_akt)
sleep(1)
print("rechts")
return True
if Taste.find("269025047") == True:
##servo_lr_akt = servo_lr_akt + 5
pwm.set_pwm(0, 0, servo_lr_akt)
sleep(1)
print("links")
return True
if Taste.find("269025041") == True:
##servo_hr_akt = servo_hr_akt + 5
pwm.set_pwm(1, 0, servo_hr_max)
sleep(1)
print("hoch")
return True
if Taste.find("269025043") == True:
##servo_hr_akt = servo_hlr_akt + 5
pwm.set_pwm(1, 0, servo_hr_akt )
sleep(1)
print("runter")
return True
if Taste.find("269025044") == True:
#servo_lr_akt = servo_lr_akt + 5
pwm.set_pwm(0, 0, servo_lr_akt)
pwm.set_pwm(1, 0, servo_hr_akt)
print("stop")
return True
if key == keyboard.Key.esc:
pwm.set_pwm(0, 0, servo_lr_akt)
pwm.set_pwm(1, 0, servo_hr_akt)
return False
# Collect events until released
with keyboard.Listener(
on_press=on_press,
on_release=on_release) as listener:
listener.join()
Keyboard (2.4 GHz) als Fernsteuerung nutzen
Du importierst termios, tty, readchar und pygame, ohne sie zu benutzen. Es ist gut, wenn Du verschiedene Sachen ausprobierst, aber dann solltest Du sie auch wieder restlos entfernen, wenn es nicht geklappt hat. Warum hat pygame nicht geklappt? Es greift deutlich weniger in System ein als pynput, wäre also die bessere Wahl.
Auch wenn Du Sondertasten benutzt, die in keyboard.Key nicht definiert sind, solltest Du sie ähnliich behandeln, also eine Konstante definieren und key direkt vergleichen, anstatt eine Zahl in einen String zu verwandeln diesen mit find in einen Wahrheitswert zu überführen und dann noch explizit mit True zu vergleichen.
Dein Problem ist, dass pynput mit Threads arbeitet, und Du die ganze Arbeit in enem Callback erledigst. Das kann zu verschiedenen seltsamen Problemen führen, nicht nur, dass Du keine Variablen über zwei Aufrufe hinaus speichern kannst. Besser ist es daher, im Callback nur eine Queue zu füttern, und das eigentliche Abarbeiten im Hauptthread zu machen.
Eingerückt wird übrigens immer mit 4 Leerzeichen pro Ebene, nicht Tabs und Leerzeichen mischen!
Auch wenn Du Sondertasten benutzt, die in keyboard.Key nicht definiert sind, solltest Du sie ähnliich behandeln, also eine Konstante definieren und key direkt vergleichen, anstatt eine Zahl in einen String zu verwandeln diesen mit find in einen Wahrheitswert zu überführen und dann noch explizit mit True zu vergleichen.
Dein Problem ist, dass pynput mit Threads arbeitet, und Du die ganze Arbeit in enem Callback erledigst. Das kann zu verschiedenen seltsamen Problemen führen, nicht nur, dass Du keine Variablen über zwei Aufrufe hinaus speichern kannst. Besser ist es daher, im Callback nur eine Queue zu füttern, und das eigentliche Abarbeiten im Hauptthread zu machen.
Code: Alles auswählen
from __future__ import division
from functools import partial
from pynput.keyboard import Key, Listener
from Queue import Queue
import time
import Adafruit_PCA9685
XF86_AUDIO_LOWER_VOLUME = 0x1008FF11
XF86_AUDIO_MUTE = 0x1008FF12
XF86_AUDIO_RAISE_VOLUME = 0x1008FF13
XF86_AUDIO_PLAY = 0x1008FF14
XF86_AUDIO_STOP = 0x1008FF15
XF86_AUDIO_PREV = 0x1008FF16
XF86_AUDIO_NEXT = 0x1008FF17
def servo_init(servo_lr_akt, servo_hr_akt):
pwm = Adafruit_PCA9685.PCA9685()
pwm.set_pwm(0, 0, servo_lr_akt)
pwm.set_pwm(1, 0, servo_hr_akt)
return pwm
def set_servo_pulse(pwm, channel, pulse):
pulse_length = 1000000 # 1,000,000 us per second
pulse_length //= 60 # 60 Hz
print('{0}us per period'.format(pulse_length))
pulse_length //= 4096 # 12 bits of resolution
print('{0}us per bit'.format(pulse_length))
pulse *= 1000
pulse //= pulse_length
pwm.set_pwm(channel, 0, pulse)
def on_press(key):
try:
print('Key {0} pressed'.format(key.char))
except AttributeError:
print('Key {0} pressed'.format(key))
def on_release(key, queue):
print('{0} released'.format(key))
if key in (XF86_AUDIO_PREV, XF86_AUDIO_NEXT, XF86_AUDIO_LOWER_VOLUME,
XF86_AUDIO_RAISE_VOLUME, XF86_AUDIO_PLAY):
queue.put(key)
return True
elif key == keyboard.Key.esc:
queue.put(key)
return False
def main():
servo_lr_akt = 400
servo_lr_min = 130
servo_lr_max = 730
servo_hr_akt = 400
servo_hr_min = 130
servo_hr_max = 730
pwm = servo_init(servo_lr_akt, servo_hr_akt)
queue = Queue()
with keyboard.Listener(
on_press=on_press,
on_release=partial(on_release, queue=queue)) as listener:
while True:
key = queue.get()
if key == XF86_AUDIO_PREV:
servo_lr_akt = servo_lr_akt + 5
pwm.set_pwm(0, 0, servo_lr_akt)
sleep(1)
print("rechts")
elif key == XF86_AUDIO_NEXT:
servo_lr_akt = servo_lr_akt + 5
pwm.set_pwm(0, 0, servo_lr_akt)
sleep(1)
print("links")
elif key == XF86_AUDIO_LOWER_VOLUME:
servo_hr_akt = servo_hr_akt + 5
pwm.set_pwm(1, 0, servo_hr_max)
sleep(1)
print("hoch")
elif key == XF86_AUDIO_RAISE_VOLUME:
servo_hr_akt = servo_hlr_akt + 5
pwm.set_pwm(1, 0, servo_hr_akt )
sleep(1)
print("runter")
elif key == XF86_AUDIO_PLAY:
servo_lr_akt = servo_lr_akt + 5
pwm.set_pwm(0, 0, servo_lr_akt)
pwm.set_pwm(1, 0, servo_hr_akt)
print("stop")
elif key == keyboard.Key.esc:
pwm.set_pwm(0, 0, servo_lr_akt)
pwm.set_pwm(1, 0, servo_hr_akt)
break
if __name__ == '__main__':
main()
Vielen Dank für die sehr ausführliche Hilfe. Ich bin begeistert!
Leider habe ich bei der Ausführung des Programms immer noch Probleme. Nach dem Start erscheint sofort folgende Fehlermeldung:
Traceback (most recent call last):
File "testprog.py", line 96, in <module>
main()
File "testprog.py", line 60, in main
with keyboard.Listener(
NameError: global name 'keyboard' is not defined
Ich beschäftige mich erst seit kurzer Zeit mit Python und stehe wirklich auf dem Schlauch.
Gerne würde ich mich auch, wie vorgeschlagen, nur auf pygame einlassen, konnte jedoch online keine Beispiele für mein Problem mit den Sondertasten finden.
Leider habe ich bei der Ausführung des Programms immer noch Probleme. Nach dem Start erscheint sofort folgende Fehlermeldung:
Traceback (most recent call last):
File "testprog.py", line 96, in <module>
main()
File "testprog.py", line 60, in main
with keyboard.Listener(
NameError: global name 'keyboard' is not defined
Ich beschäftige mich erst seit kurzer Zeit mit Python und stehe wirklich auf dem Schlauch.
Gerne würde ich mich auch, wie vorgeschlagen, nur auf pygame einlassen, konnte jedoch online keine Beispiele für mein Problem mit den Sondertasten finden.
So muß es bei mir richtig sein
und natürlich auch
Code: Alles auswählen
with Listener(
Code: Alles auswählen
elif key == Key.esc: