Motoren mit PS4-Controller steuern

Nachdem ich vor einiger Zeit ein kleines Auto mit PS3-Controller-Steuerung gebaut habe, wagte ich es nun, das ganze auf den aktuellen Stand zu bringen. Mein momentanes Mini-Auto lässt sich nun mit dem Playstation 4 Controller steuern.

Dazu ist ein bisschen Vorarbeit notwendig. Dafür übernehme ich einige Schritte aus dieser einer hilfreichen GitHub-Repo: https://github.com/macunixs/dualshock4-pi

sudo apt-get update
sudo apt-get -y install joystick
sudo apt install python-dev python3-dev python-pip python3-pip
sudo pip3 install ds4drv
(Ich bleibe bei Python 3. Für Python 2 "pip" nutzen)

Mit den nächsten Schritten erlauben wir anderen User neben Root, den Zugriff auf den Joystick.

sudo wget https://raw.githubusercontent.com/chrippa/ds4drv/master/udev/50-ds4drv.rules -O /etc/udev/rules.d/50-ds4drv.rules

sudo udevadm control --reload-rules

sudo udevadm trigger

Nun kann der Playstation 4 Controller durch das Drücken und Halten der PS-Taste und der Share-Taste für einige Sekunden in den Pairing-Modus versetzt werden. Das wird dadurch signalisiert, dass die Lampe des Controllers schnell blinkt.

Der Treiber wird gestartet mit

sudo ds4drv

Nach ein paar Sekunden sollte die Meldung auftauchen, dass der Controller verbunden wurde. Nun kann in einem zweiten Terminal der Joystick-Test durchgeführt werden.

jstest /dev/input/js0

Es erscheinen nun eine Menge Zahlen. Beim genaueren Hinsehen erkennt man, dass das Chaos nach Achsen und Buttons sortiert ist. Bewegt man nun einen der Sticks, so ändert sich ein Wert einer Achse. Bei einem Knopf wird ein Knopf von off auf on springen. Bitte beachtet 1. Das der Controller einen Bewegungssensor hat. Er werden sich also andauernd Werte ändern, wenn Ihr den Controller bewegt und 2. Manche Tasten einen Achse und ein Knopf sind. Das heisst z.B. R2 kann wie eine Achse analog bewegt werden (langsames Beschleunigen z.B.) oder durchgedrückt werden und dann springt ebenfalls einer der Buttons von off auf on.

Damit der Treiber nicht jedes Mal neu gestartet werden muss, kann er der rc.local hinzugefügt um bei Start mitgeladen werden. Dazu die Datei im Editor öffnen:

sudo nano /etc/rc.local

Und nach der Zeile # By default this script does nothing.

diese Zeile einfügen

/usr/local/bin/ds4drv &

Jetzt können wir uns bereits dem Python-Programm für das Auto widmen. Meins ist so ausgelegt, dass das Auto über die Achse R2 stufenlos beschleunigt werden kann (PWM an Enable A und B) und über den linken Stick wird die Richtung angegeben. (Vor, Zurück, Rechts, Links). DIe H-Brückenfunktion übernimmt ein L298N. Die Pin-Belegung kann dem Python-Programm entnommen werden.

#!/usr/bin/python

import pygame
import sys
from time import sleep
import RPi.GPIO as GPIO
import os

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)

IN1=3
IN2=5
IN3=8
IN4=13
ENA=12
ENB=19

GPIO.setup(IN1, GPIO.OUT)
GPIO.setup(IN2, GPIO.OUT)
GPIO.setup(IN3, GPIO.OUT)
GPIO.setup(IN4, GPIO.OUT)
GPIO.setup(ENA, GPIO.OUT)
GPIO.setup(ENB, GPIO.OUT)

ENA_PWM = GPIO.PWM(ENA, 100)
ENB_PWM = GPIO.PWM(ENB, 100)

ENA_PWM.start(0)
ENB_PWM.start(0)


axisR2 = 4
axisL2= 3
stickVZ = 1
stickLR = 0

r1=  4
l1 = 5

os.putenv('DISPLAY', ':0.0')
pygame.init()
pygame.joystick.init()


# Get count of joysticks
joystick_count = pygame.joystick.get_count()

print ("sticks ", joystick_count)
 # For each joystick:
for i in range(joystick_count):
    joystick = pygame.joystick.Joystick(i)
    joystick.init()

# Joysticks finden und benennen - Optional
    name = joystick.get_name()
    print (name)

    axes = joystick.get_numaxes()
    print ("achsen", axes)

    for i in range( axes ):
        axis = joystick.get_axis( i )
        print ("achse ",axis)

while True:
    hadEvent = False
    events = pygame.event.get()
    # Handle each event individually
    for event in events:
        if event.type == pygame.JOYBUTTONDOWN:
        # A button on the joystick just got pushed down
            hadEvent = True
        elif event.type == pygame.JOYAXISMOTION:
            # A joystick has been moved
            hadEvent = True
            
        if hadEvent:
            
            R2 = joystick.get_axis(axisR2)
            L2 = joystick.get_axis(axisL2)
            R1 = joystick.get_button(r1)
            L1 = joystick.get_button(l1)
            StickVZ = joystick.get_axis(stickVZ)
            StickLR = joystick.get_axis(stickLR)
            
            print (R2, L2,R1, L1, StickVZ,StickLR)

            dc = (R2+1) *50
            print dc
            ENA_PWM.ChangeDutyCycle(dc)
            ENB_PWM.ChangeDutyCycle(dc)


            if StickLR < 0:

                GPIO.output(IN1, True)
                GPIO.output(IN2, False)
                GPIO.output(IN3, False)
                GPIO.output(IN4, True)
                

            if StickLR > 0:
                GPIO.output(IN1, False)
                GPIO.output(IN2, True)
                GPIO.output(IN3, True)
                GPIO.output(IN4, False)

            if StickLR == 0:
                # M1 stop
                GPIO.output(IN3, False)
                GPIO.output(IN4, False)
                # M2 stop
                GPIO.output(IN1, False)
                GPIO.output(IN2, False)
#                 

            if StickVZ > 0.6:
                # M1 Zurueck
                GPIO.output(IN1, False)
                GPIO.output(IN2, True)
                # M2 Zurueck
                GPIO.output(IN3, False)
                GPIO.output(IN4, True)

            if StickVZ < - 0.2:
            
                GPIO.output(IN1, True)
                GPIO.output(IN2, False)
                # M2 Vor
                GPIO.output(IN3, True)
                GPIO.output(IN4, False)
                
                

            if StickVZ == 0:
                # M1 stop
                GPIO.output(IN3, False)
                GPIO.output(IN4, False)
                # M2 stop
                GPIO.output(IN1, False)
                GPIO.output(IN2, False)

 

Kommentar verfassen