DualShock 4 Controller and pygame

So our robot is going to have two motors working to produce differential steering. I.e. move one side faster to turn.

This means we need two hardware PWMs for continuous speed control and to have some way of controlling it remotely!
With the raspberry pi3 there is an opportunity to have no external hardware on the robot itself by using a PS4 DS4 controller which connects over bluetooth.
We’re working in python and there is handily a python based driver called ds4drv.
To get ds4drv on the pi running you can use the following commands:

sudo apt install python3-dev python3-pip
sudo pip3 install ds4drv

Then in the file “/home/user/.bashrc” – where user is pi by default – add the following line to the file:

sudo ds4drv --daemon --led 000008 --emulate-xpad-wireless &

This ensures that the bluetooth driver is initialised every time you log in. Then to connect your ds4 controller hold the share button and the ps button until manic flashing begins and the light bar should turn blue when it’s all connected.

To test this was working I used a program called jstest. You can get this by running the commands:

sudo apt-get install joystick
jstest /dev/input/js0

The js0 may be different on your pi if you have multiple joysticks attached.
When jstest is running you will get a readout of each change to the status of js0, i.e. every time you press a button or move a joystick you will get an update on the command line telling you what each button a joystick value is now.

Now to implement this in a python script!
For this it was important to make sure that python3, pygame and wiringpi were all installed. Then the following script gets a connected ds4 controller and maps the trigger values to two hardware pwms. In this example there is stuff for controlling the H-bridge we’ve got for powering the motors too.

"""Test script for using pygame to read in ds4 controller
with ds4drv  running as a daemon
DS4  controller axis maps:
Axis0: Left stick l-r (-1 left, 1 right)
Axis1: Left stick u-d (-1 up, 1 down)
Axis2: Left trigger (-1 unpressed, 1 completely pressed)
Axis3: Right stick l-r (-1 left, 1 right)
Axis4: Right stick u-d (-1 up, 1 down)
Axis5: Right trigger (-1 unpressed, 1 completely pressed)
"""

import pygame
import wiringpi
from time import sleep
import sys

#initialise DS4 controller
screen = pygame.display.set_mode([10,10]) #make a 10x10 window
pygame.joystick.init() #find the joysticks
joy = pygame.joystick.Joystick(0)
joy.init()
if(joy.get_name()=='Sony Entertainment Wireless Controller'):
    print("DS4 connected")
else:
    print("Not a DS4")


Motor1PWM  = 1 # gpio pin 12 = wiringpi no. 1 (BCM 18)
Motor1AIN1 = 4 # gpio pin 16 = wiringpi no. 4 (BCM 23)
Motor1AIN2 = 5 # gpio pin 18 = wiringpi no. 5 (BCM 24)
MotorStandby = 6 # gpio pin 22 = wiringpi no. 6 (BCM 25)
Motor2PWM = 23 # gpio pin 33 = wiringpi no. 23 (BCM 13)
Motor2BIN1 = 21 # gpio pin 29 = wiringpi no. 21 (BCM 5)
Motor2BIN2 = 22 # gpio pin 31 = wiringpi no. 22 (BCM 6)

# Initialize PWM output
wiringpi.wiringPiSetup()
wiringpi.pinMode(Motor1PWM, 2)     # PWM mode
wiringpi.pinMode(Motor1AIN1, 1) #Digital out mode
wiringpi.pinMode(Motor1AIN2, 1) #Digital out mode
wiringpi.pinMode(MotorStandby, 1) #Ditial out mode

wiringpi.pinMode(Motor2PWM, 2)     # PWM mode
wiringpi.pinMode(Motor2BIN1, 1)    #Digital out mode
wiringpi.pinMode(Motor2BIN2, 1)    #Digital out mode


wiringpi.pwmWrite(Motor1PWM, 0)    # OFF
wiringpi.pwmWrite(Motor2PWM, 0)    # OFF
wiringpi.digitalWrite(Motor1AIN1, 1) #forward mode
wiringpi.digitalWrite(Motor1AIN2, 0) #forward mode
wiringpi.digitalWrite(Motor2BIN1, 1)
wiringpi.digitalWrite(Motor2BIN2, 0)
wiringpi.digitalWrite(MotorStandby, 1) #enabled


# Set Motor Speed
def motorspeed(speed1, speed2):
    wiringpi.pwmWrite(Motor1PWM, speed1) #motorspeed from 0 to 1024
    wiringpi.pwmWrite(Motor2PWM, speed2) 

while True:
    pygame.event.get()
    rt = joy.get_axis(5)
    lt = joy.get_axis(2)
    print(rt)
    print(lt)
    speed1 = (rt+1)*512
    speed2 = (lt+1)*512
    motorspeed(int(speed1),int(speed2))
    sleep(0.1) #limit the frequency to 10Hz

Success! This resulted in two hardware PWMs and associated digital signals being controlled in a simple way by the DS4 controller over bluetooth. Seems pretty reliable so far too. Videos to follow when then is wired up to SunnyBot himself!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s