Joypad Abfrage Modul

Heute ist Stammtischzeit:
Jeden Donnerstag 20:30 Uhr hier im Chat.
Wer Lust hat, kann sich gerne beteiligen. ;)
  • Hier stelle ich Euch mein Tool zur einfachen Abfrage von Joypad-Eingaben vor.

    Die Idee dahinter war, dass ich ohne etwas an meinem Hauptprogramm ändern zu müssen jederzeit ein anderes Pad anschließen kann.
    Ich habe hier ein kabelloses X-Box Pad und ein PS2 Nachbau von HAMA.
    Wenn die Batterie allerdings mal ausgehen sollte, hätte ich keinen Zugriff mehr auf mein Programm.
    Würde ich einfach ein anderes Pad anschließen, wäre die komplette Steuerung durcheinander.
    Dafür habe ich mir dieses Modul geschrieben, welches alle Eingaben in ein einheitliches Format übersetzt.
    Dies kann sicherlich auch für andere User sehr nützlich sein, da man sich nicht großartig mit Pygame auseinandersetzen muss,
    und mit wenigen Handgriffen sofort in sein Projekt einbinden kann.
    Ich denke da z.B. an Roboter-Steuerung, Menu-Steuerung, und vieles weitere.

    In diesem Modul gibt es zwei Funktionen.
    Einmal eine Abfrage für die Analog-Achsen und eine Abfrage für die einzelnen Buttons.
    Ich habe das aufgesplittet, damit man je nach Bedarf einzelne Zustände abfragen kann.

    Beim Starten erkennt das Modul, welches Pad angeschlossen ist und stellt die Konfiguration entsprechend um.
    Zur Zeit ist das X-Box Pad und das HAMA Pad integriert. Andere Pads können bei Bedarf ergänzt werden.
    Zunächst wird nur ein Pad abgefragt, was aber für die meisten Projekte vollkommen ausreichen sollte.
    Für die Namen der Buttons habe ich mich an der Belegung des X-Box Pads orientiert,
    um das 1. einheitlicher zu halten und 2. weil die Beschriftung vom HAMA Pad schon abgewetzt ist :D

    Kennt das Modul das angeschlossene Pad nicht, ist keins angeschlossen, oder fehlerhafte Werte werden abgefragt,
    gibt das Modul eine entsprechende Fehlermeldung zurück.

    Das Programm kann entweder direkt in den eigenen Code eingebaut werden oder (was kompfortabler und übersichtlicher ist) als Modul importiert werden.
    Dafür sollte das Programm in dem gleichem Ordner wie das Haupt-Programm liegen (oder dort, wo Python nach Modulen sucht).
    Importiert werden die Funktionen mit

    Python
    from eingabe import joy, joy_a

    Anwendung:
    Es gibt mehrere Möglichkeiten, das Joypad abzufragen.
    Am Programmende habe ich ein kleines Beispiel angehängt, wo man alles mal ausprobieren kann.
    Startet man "eingabe.py" also alleine, werden alle Joypad-Werte angezeigt.
    Wahlweise kann auch das im Attachment befindliche "test.py" Programm gestartet werden.
    Für weitere Informationen kann die help Funktion genutzt werden.
    Dafür startet man die Python-Shell und gibt folgendes ein:

    Code
    import eingabe
    help(eingabe)


    In eurem Code muss nur die Zeile

    Python
    from eingabe import joy, joy_a


    stehen und dann kann es sofort verwendet werden.


    joy(Taste, Typ)
    Hiermit werden die Buttons abgefragt. Die Funktionsweise der Werte "Taste" und "Typ" erkläre ich mal kurz:

    a = joy( 0 , TYP)
    Es wird ein Tupel zurückgegeben, mit den aktuellen Zuständen ALLER Buttons.
    a[0] ist ein String und gibt den Namen des zuletzt gedrückten Buttons wieder.
    a[ 1 - 17 ] zeigt den Zustand der einzelnen Buttons an. Dabei steht a[1] z.B. für den A Button. 1 ist gedrückt und 0 ist nicht gedrückt. Die genaue Nummerierung kann im Code nachgeschaut werden (bnames). Diese Funktion eignet sich z.B. um mehrere Tasten GELEICHZEITIG abzufragen (für Tastenkombinationen).
    Beachte: das HAMA Pad hat nur 16 Tasten. Beim X-Box Pad kann zusätzlich der X-Button abgefragt werden.

    a = joy( 1 - 17 , TYP)
    Es wird 1 oder 0 zurückgegeben und entspricht dem Zustand der abgefragten Taste (1-17)

    a = joy( TASTE , 0 )
    Die Abfrage erfolgt SOFORT

    a = joy( TASTE , 1 )
    Das Programm WARTET bis eine Taste gedrückt wurde. Demzufolge gibt es auch nur eine 1 zurück, wenn die entsprechende Taste gedrückt wurde. Hier ist Vorsicht geboten, denn wenn der falsche Button abgefragt wird, wartet das Programm bis in alle Ewigkeit...


    joy_a()
    Die zweite Funktion dient der Abfrage der Analog-Achsen

    a = joy_a()
    Hier kommt ein tupel zurück mit den Werten der jeweiligen Achsen.
    a[0] = Linker Stick vertikal (-10 = UP , +10 = DOWN)
    a[1] = Linker Stick horizontal (-10 = LEFT, +10 = RIGHT)
    a[2] = Rechter Stick vertikal (-10 = UP , +10 = DOWN)
    a[3] = Rechter Stick horizontal (-10 = LEFT, +10 = RIGHT)
    a[4] = L2 Regler (falls vorhanden) (0 - 10)
    a[5] = R2 Regler (falls vorhanden) (0 - 10)

    Die Werte -1 und +1 habe ich auf 0 abgeglättet, da besonders das X-Box Pad Probleme macht, eine Nullstellung zu finden.


    Wer jetzt noch Verbesserungsvorschläge hat oder vllt. sein eigenes Pad eingebunden hat,
    bzw. Hilfe dabei braucht kann sich gerne hier drunter melden.
    Über Erfahrungsberichte / Feedback würde ich mich auch sehr freuen.

    Dann wünsche ich mal viel spass und gutes Gelingen mit diesem kleinem Tool :thumbs1:

    Euer Scholli!


    ___________________________________________________________________________________________________________________
    Hinweis: Diesen Thread sollte man sich mal angucken.
    Da geht es um das abschalten der Debugmessages von Pygame, damit man sich das Terminal nicht vollspammt.
    Dieser "Fehler" wird wohl erst in einer späteren Version von Pygame endgültig eleminiert. Solange muss man selber Hand anlegen.
    Ist aber von meigrafds SUPER beschrieben und schnell erledigt.
    Danke an dieser Stelle nochmal dafür!
    ___________________________________________________________________________________________________________________

  • Ich halte mir hier mal ne Position frei für Erweiterungen, Änderungen, Konfigurationseinstellungen, etc..
    Lässt sich nämlich prima ausbauen und hab da noch einiges "in petto"... :)

    ...and write down with pencil&paper...
    Where can i download "pencil&paper" ?

  • Guten Morgen,
    also ich habe mir über einen Kumpel einen Wireless xbox Controller besorgt.
    Hast du denn schon einen Ansatz wie man die Analogsticks einbauen/auswerten kann?

    Bin schon am rumgoogeln aber so wie ich dich kenne hast du das ziemlich schnell raus ;)

    Liebe Grüße

    Neolinga

  • Ich hab gestern nochmal einiges umgebaut.
    Jetzt ist eine zuverlässige Fehlerabfrage dabei, falls kein Pad eingesteckt ist, falls das Pad nicht bekannt ist oder falls die abgefragten Werte nicht vom Joypad unterstützt werden.
    Der PS2 Nachbau ist ja nicht 1 zu 1 kompatibel mit dem X-Box Pad. Denn beim X-Box Pad kann zusätzlich der X-Button abgefragt werden und die L2/R2 Tasten sind Analog.

    Hatte das Programm zunächst nur für mich geschrieben und da war es noch nicht nötig, die Analogsticks abzufragen. Wollte nur eine Steuerung für ein Menü haben, unabhängig davon welches Pad ich gerade eingestöpselt hab. Die Batterien vom Wireless Pad geben ja schnell mal auf und dann wollte ich nicht ohne Steuerung dastehen...
    Hole das aber heute nach. ;)
    Spätestens morgen lade ich dann eine überarbeitete Version hoch.

    Evtl. könntest Du mir sogar dabei helfen, das Saitek Keypad mit einzubinden. Dazu komm ich aber später. Falls nötig, helfe ich Dir dann auch das in Dein Programm einzubinden (ist ja unabhängig vom verwendetem Pad).
    Melde mich dann in Deinem Thread nochmal.

    Bis später, Scholli.

    ...and write down with pencil&paper...
    Where can i download "pencil&paper" ?

  • Guten Tag ,

    dachte ich melde mich mal wieder. Hatte in letzter Zeit recht wenig Zeit hierfür. Nunja Musste mir jetzt auch eine neue H-Brücke kaufen, da bei der alten die eine Seite nicht mehr so richtig funktioniert hat. Wenn ich dein eingabe.py programm importiere kann ich ja mit den Abfragen:

    Code
    if  key == "A":
            ControlAPairOfPins("19","0","21","1")
            ControlAPairOfPins("23","1","24","0")	
            print "up"
            key=False

    weiterarbeiten, oder?
    Bzw welche Methode oder Variable muss ich nach dem import abfragen?
    joy bzw joy_a wir ja dann reingeladen.

    ich weiß nicht wie ich das in den Code einbauen kann. Dh. was ich alles wo und wie noch deklarieren muss. :s
    Also ich glaub ich stell mich da leicht doof an. Im Anhang stell ich mal das ganze Programm rein. Ich hoffe du kannst mir weiterhelfen.


    Liebe Grüße

    Neolinga

  • Ist doch erstmal ganz gut geworden. :thumbs1:
    Ein paar Fehler haben sich aber eingeschlichen.
    Erstmal muss die Abfrage angepasst werden:

    Code
    key = joy(0,0)[0]


    Damit wird die aktuell gedrückte Taste in die Variable "key" geschrieben.

    Dann gibt die Funktion "joy" keinen Wert zurück, der "BREAK" heißt. Da irgendeine Taste einsetzen, z.B. "A" oder "START"

    Zu guterletzt kannst Du noch folgenden Codeteil einfach entfernen, da Du ja nur das X-Box Pad verwendest.

    Code
    if name == "GreenAsia Inc.      USB  Joystick  ":
            bjoy = [ 0, 2, 1, 3, 0, 4, 5, 6, 7,10,11, 8, 9,99,96,95,97,98]
            ajoy = [1,0,2,3]
            bekannt = True


    Das läuft also schonmal. Jetzt könnte man das ganze noch etwas verfeinern.
    Ich bleibe mal bei einem kleinem Beispiel, die anderen Richtungen kannst Du ja dann entsprechend ergänzen.

    Jetzt sollte Dein Fahrzeug optimal auf das Gamepad reagieren.


    /edit: Bevor ich es vergesse: Am günstigsten wäre es, wenn Du folgende Abfrage verwendest:

    Code
    key = joy(0,1)[0]


    So wartet das Programm auf eine Joypad Eingabe. Ein ständiges abarbeiten der "Stop Motor" Funktion wird damit vermieden.

    nochmal in Kurzform:
    joy(0,0) = Sofortige Abfrage ALLER Tasten
    joy(0,1) = Warten auf Tastendruck ALLER Tasten
    Ein Ergebnis würde dann so aussehen:

    Code
    "UP", 0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0


    mit joy(0,0)[0] kann man dann die erste Stelle vom Ergebnis abfragen. in diesem Beispiel das "UP". Wie man sieht ist die 14. Stelle mit einer "1" belegt.

    ...and write down with pencil&paper...
    Where can i download "pencil&paper" ?

    Einmal editiert, zuletzt von LieberScholli (3. Mai 2014 um 18:15)

  • Danke dir für die Erläuterung, jetzt ist es mir einiges klarer :)
    Bis jetzt wurde mir auch jede 0,5s der jeweilige Wert ausgegeben. Jetzt immer nur einmal ---> finde ich viel besser.
    Ein kleines Problem hab ich jedoch noch. Wenn ich ein Signal gebe dann nimmt er das Signal immer weiter ohne es zurückzusetzen. Sprich er fährt dann ewig geradeaus :D :s

    Hab ich das richtig jetzt auch gelesen, dass ich die Analogsticks(hinten), also LT und RT hierfür auch einsetzen kann wenn ich 5/6 benutze?
    Bzw. diese "Knüppel" :lol:

    Schonmal im Vorraus vielen Dank für deine wunderbare Hilfe :danke_ATDE:

    Liebe Grüße

  • Das Werte nicht "zurückgesetzt" werden ist mir beim wireless X-Box Pad auch schon aufgefallen. Manchmal geht der erst wieder in "Ruheposition", wenn irgendeine andere Taste gedrückt wurde. Das liegt aber irgendwie am Pad, bzw. am Treiber. Mit anderen Pads ist mir solch ein Verhalten noch nicht aufgefallen.

    Vllt. solltest Du die Verhaltensweise und Reaktionszeit einfach mal hiermit kurz testen:

    Code
    a = 0
    while 1:
        a += 1
        print a, joy(0,0)[0]


    Die Analogsticks kannst Du natürlich auch zur Steuerung einsetzen.
    Das würde dann etwa so aussehen:


    Statt den print Befehlen natürlich die Motorsteuerung einfügen.
    Auch hier am besten überall die Schleife einfügen, die auf das loslassen wartet:

    Code
    while joy_a[0] < 0: sleep(.1)
    key_a[0] = 0: key_a[1] = 0

    Ich glaub ich setze mich heut abend mal da dran und schreibe Dir Dein Programm etwas um. Jetzt hast Du meine Python-Triebe wieder geweckt :D
    Beste Grüße!

    ...and write down with pencil&paper...
    Where can i download "pencil&paper" ?

  • Klasse, das mit den Analogsticks werde ich ausprobiere :) damit hab ich vor eventuelle Lampen anzusteuern.
    Ein großes Problem ist bei mir etwas auch noch die Mechanik. Habe mir aus Fischertechnik ein Raupencahssis gebaut und betreibe die Ketten mit 2 Motoren. Jedoch muss ich da mit der Getriebeübersetzung etc. etwas rumspielen. Wollte nur zu dem Thema auch etwas Rückmeldung geben. Das Geld mir ein anderes stabileres Chassis zu holen, wie z.B. von Makeblock hab ich im Moment nicht. Vielleicht später. In meinem Thread werde ich im Laufe der nächsten Woche auch einige Bilder reinstellen. Wenn Interesse besteht auch Schaltpläne.


    Liebe Grüße

    Neolinga

  • Soo, ich hab grad mal Deinen Code etwas überarbeitet.

    Das Eingabe-Modul habe ich jetzt mal gemäß seiner Bestimmung als Modul geladen und nicht direkt in den Code eingepflanzt. Das ist dann alles doch sehr viel übersichtlicher, da an dem Modul ja eigentlich nichts verändert werden muss. Dafür muss "Eingabe" nur in dem gleichem Ordner sein, wie das Programm. Python erstellt beim ersten Start eine compilierte Datei in dem Ordner, welches das Modul beinhaltet. Die Datei "eingabe.py" ist ab da an eigentlich überflüssig und wird nicht mehr weiter verwendet.

    Die Motorsteuerung habe ich auch etwas angepasst. Erschien mir doch etwas unübersichtlich.

    Die Steuerung erfolgt über den linken Analogstick. Abgebrochen wird mit Taste "A"
    Jetzt kann man auch sehr einfach Lichter an und ausschalten. Hier mal ein kleines Beispiel.

    Code
    licht_vorne = 0
    GPIO.setup(22,GPIO.OUT)
    
    
    if taste == "B":
        licht_vorne = (licht_vorne is 0) * 1
        GPIO.output(22, licht_vorne)
        while joy(0,0)[0] == "B": pass


    (Wo das hingehört sollte eigentlich klar sein, oder?)

    Das "pass" könnte man in beiden Codes auch durch ein "sleep" ersetzen. Da kommt es ganz auf die Hardware an.
    Müsste man halt individuell abstimmen, was für die Prozessorauslastung am besten ist und sich trotzdem noch reibungslos steuern lässt.

    Der Knaller wäre jetzt noch, die Geschwindigkeit mittels PWM zu regulieren.
    Die Abfragemöglichkeit wäre gegeben, nur die Steuerung wäre etwas komplizierter. Aber das kann man sich ja für später mal vornehmen. Ich glaub ich werd demnächst die Legokisten aus der Verwandtschaft mal etwas plündern...:D

    Viel spass!

    ...and write down with pencil&paper...
    Where can i download "pencil&paper" ?

    Einmal editiert, zuletzt von LieberScholli (4. Mai 2014 um 05:13)

  • @ Neolinga:
    Gib mir doch netterweise mal n Bild von Deinem Roboter.
    Würde mich echt mal interessieren.

    Und da das einer meiner ersten universell einsetzbaren Anwendungen ist,
    würden mich auch brennend andere Usermeinungen interessieren (wurde ja noch nicht so oft geladen...).
    Mir bereitet dieses Modul immer treue Dienste, daher schätze ich mal das das auch für andere schnell und erfolgreich eingesetzt werden kann.

    Ich hoffe, ich habe das ausreichend Dokumentiert.
    Für Verbesserungsvorschläge und Kritik bin ich jederzeit offen.

    Liebe Grüße, Scholli.

    ...and write down with pencil&paper...
    Where can i download "pencil&paper" ?

  • Juhu bin grad dabei eine Art Tut zu schreiben.
    Wenn du aber jetzt gleich ein Bild haben willst dann schicke ich dir schonmal vorab Bilder :)

    Liebe Grüße

    Neolinga

  • Erstmal danke Scholli für dein Programm. Es nimmt mir einen Haufen Arbeit ab. :thumbs1:
    Ich habe selbst ein Testprogramm geschrieben, das mit den Einzelabfragen arbeitet. Mein Problem ist nur, dass die beiden Trigger am Anfang den Wert 5 haben und erst nach einmal drücken auf 0 zurückspringen
    Hab leider überhaupt keine Ahnung was falsch ist :huh:
    Hoffe du kannst mir helfen.
    hab nen wireless 360 controller

    Code : http://pastebin.com/yT89JALR
    sorry wenn der nicht kommentiert und sehtr unordentlich ist. Bin noch Anfänger :D

    LG Andi

  • So jetzt wollte ich, nachdem ich auf dieses Modul in dem Roboter Thread aufmerksam wurde, selbst mal testen ob ich das zum laufen bekomme.

    Ich hab jetzt einfach mal deine beiden Pythonskripte auf den Raspberry gespielt, mein Xbox 360 USB Controller eingesteckt und die Test.py gestartet. Wenn ich es richtig recherchiert habe, brauche ich keinen Treiber, weil der als Kernelmodul mit der Firmware schon drauf ist und xpad heißt.

    Allerdings bekomm ich im Terminal nur die meldung Microsoft X-Box 360 pad nicht bekannt und das tausendfach immer wieder bis es es mit ctrl c abbreche. Der Controller ist per aktivem USB Hub angeschlossen. Geht leider nciht anders, weil ich einen Raspi a+ mit nur einem USB hab, da aber noch der WLan Stick dranhängt wegen SSH. Und einen Monitor hab ich auch keinen um das ohne ssh zu testen. Die Freundin killt mich, wenn ich deswegen unseren Fernseher blockiere ;)

  • Hallo Theo,
    Seltsam dass es bei dir nicht will.
    Bei mir funktioniert ist. Schau mal nach den folgenden Punkten:

    • beide Skripte im gleichen Verzeichnis?
    • pygame auf dem neusten Stand?
    • xboxdrv installiert? (Hab ich zumindes mal)
    • Skript mit sudo ausgeführt?

    Ich benutze Übrigens den wireless Controller.
    Sollte xboxdrv nicht installiert sein einfach über

    Code
    apt-get install xboxdrv


    installieren .

    Hoffe das hilft.

    LG speechbubble21 :)

    Einmal editiert, zuletzt von speechbubble21 (20. Dezember 2014 um 23:55)

  • Also ich hab jetzt nochmal geschaut.

    Die beiden skripte liegen beide im homeverzeichnis, im selben ordner selbstverständlich.

    Wie kann ich denn feststellen welche Version von Pygame installiert ist? Das muss ich doch in der Python shell machen, oder? habs mit

    Code
    import pygame as pygame
    pygame.VERSION

    probiert, bekomme aber ne Fehlermeldung AttributeError: 'module' object has no attribute 'VERSION'

    Bin da leider noch sehr unerfahren.

    EDIT: Ok habs rausgefunden, mit PIP geht es, hab aber bis jetzt nur für Python 2 rausgefunden das pygame 1.9.1release installiert ist, und das scheint die aktuelle Version zu sein, zumindest konnte pip es nicht upgraden.

    EDIT2: Ok habs auch für Python3 rausgefunden, laut pip ist hier pygame1.9.2a0 installiert

    Auf jedenfall hab ich python 2.7.3 und python 3.2.3 installiert. Für python 3 hab ich pygame nach dieser Anleitung nochmal installiert.

    Wenn ich das Test.py skript mit

    Code
    python test.py

    aufrufe bekomme ich die Meldung Microsoft X-Box 360 pad nicht bekannt.

    wenn ich es mit

    Code
    python3 test.py

    aufrufe kommt folgende Meldung

    Code
    File "test.py", line 6
        print joy(0,0),joy_a()
                ^
    SyntaxError: invalid syntax


    Mit Xboxdrv hab ich auch probiert. Wenn ich es einfach als Sudo aufrufe bekomme ich folgende Meldung

    Code
    -- [ ERROR ] ------------------------------------------------------
     Error couldn't claim the USB interface: LIBUSB_ERROR_BUSY
    Try to run 'rmmod xpad' and then xboxdrv again or start xboxdrv with the option --detach-kernel-driver.

    Wenn ich die Anweisung mit rmmod xpad ausprobiere bekomme ich zwar in xboxdrv eine Antwort vom Pad, aber dafür kommt in test.py nur noch joypad unbekannt.

    Skripte wahlweise als Sudo ausgeführt bringt auch keinen erfolg.

    Einmal editiert, zuletzt von theo100 (21. Dezember 2014 um 14:51)

  • Hallo LieberScholli,
    habe jetzt endlich wieder die Zeit gefunden, an meinem Roboter weiterzubauen. Nicht zuletzt weil ich mit meinem 3D Drucker endlich Gehäuseteile fertigen kann. Nun hätte ich bei deinem Modul zur Steuerung noch ein paar Fragen an dich:
    Gibt es eine Möglichkeit die Tasten auf der Rückseite des X-BoxControllers (LT/RT) auszuwerten, bzw. in dein Modul zu integrieren?
    Wäre nett wenn du mir wie schon zuvor auf die Sprünge helfen könntest :)

    Liebe Grüße

    Neolinga

  • Hallo
    Da ich keinen XBox controller habe verwende ich einen ps3 controller.
    Ich würde gerne wissen wie ich herausfinden kann welche Taste an welche stelle der bjoy =[] und ajoy=[] gehört.

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!