Ctpelnar1988
Ctpelnar1988

Reputation: 1255

How to identify which button is being pressed on PS4 controller using pygame

I am using a Raspberry Pi 3 to control a robotic vehicle. I have successfully linked my PS4 controller to the RPi using ds4drv. I have the following code working and outputting "Button Pressed"/"Button Released" when a button is pressed/released on the PS4 controller using pygame. I am wondering how to identify which button is exactly being pressed.

ps4_controller.py

import pygame

pygame.init()

j = pygame.joystick.Joystick(0)
j.init()

try:
    while True:
        events = pygame.event.get()
        for event in events:
            if event.type == pygame.JOYBUTTONDOWN:
                print("Button Pressed")
            elif event.type == pygame.JOYBUTTONUP:
                print("Button Released")

except KeyboardInterrupt:
    print("EXITING NOW")
    j.quit()

Upvotes: 9

Views: 16624

Answers (4)

Ctpelnar1988
Ctpelnar1988

Reputation: 1255

Figured out a hack.

The PS4 buttons are numbered as the following:

0 = SQUARE

1 = X

2 = CIRCLE

3 = TRIANGLE

4 = L1

5 = R1

6 = L2

7 = R2

8 = SHARE

9 = OPTIONS

10 = LEFT ANALOG PRESS

11 = RIGHT ANALOG PRESS

12 = PS4 ON BUTTON

13 = TOUCHPAD PRESS

To figure out which button is being pressed I used j.get_button(int), passing in the matching button integer.

Example:

import pygame

pygame.init()

j = pygame.joystick.Joystick(0)
j.init()

try:
    while True:
        events = pygame.event.get()
        for event in events:
            if event.type == pygame.JOYBUTTONDOWN:
                print("Button Pressed")
                if j.get_button(6):
                    # Control Left Motor using L2
                elif j.get_button(7):
                    # Control Right Motor using R2
            elif event.type == pygame.JOYBUTTONUP:
                print("Button Released")

except KeyboardInterrupt:
    print("EXITING NOW")
    j.quit()

Upvotes: 11

Artur Spirin
Artur Spirin

Reputation: 254

A bit late, but if there are people looking for a solution on this still, I have created a module: pyPS4Controller that has all the button events on the controller already mapped and they can be overwritten like so:

from pyPS4Controller.controller import Controller


class MyController(Controller):

    def __init__(self, **kwargs):
        Controller.__init__(self, **kwargs)

    def on_x_press(self):
       print("Hello world")

    def on_x_release(self):
       print("Goodbye world")

controller = MyController(interface="/dev/input/js0", connecting_using_ds4drv=False)
# you can start listening before controller is paired, as long as you pair it within the timeout window
controller.listen(timeout=60)

This is just an example for 1 event. There are more events that can be overwritten such as:

on_x_press
on_x_release
on_triangle_press
on_triangle_release
on_circle_press
on_circle_release
on_square_press
on_square_release
on_L1_press
on_L1_release
on_L2_press
on_L2_release
on_R1_press
on_R1_release
on_R2_press
on_R2_release
on_up_arrow_press
on_up_down_arrow_release
on_down_arrow_press
on_left_arrow_press
on_left_right_arrow_release
on_right_arrow_press
on_L3_up
on_L3_down
on_L3_left
on_L3_right
on_L3_at_rest  # L3 joystick is at rest after the joystick was moved and let go off
on_L3_press  # L3 joystick is clicked. This event is only detected when connecting without ds4drv
on_L3_release  # L3 joystick is released after the click. This event is only detected when connecting without ds4drv
on_R3_up
on_R3_down
on_R3_left
on_R3_right
on_R3_at_rest  # R3 joystick is at rest after the joystick was moved and let go off
on_R3_press  # R3 joystick is clicked. This event is only detected when connecting without ds4drv
on_R3_release  # R3 joystick is released after the click. This event is only detected when connecting without ds4drv
on_options_press
on_options_release
on_share_press  # this event is only detected when connecting without ds4drv
on_share_release  # this event is only detected when connecting without ds4drv
on_playstation_button_press  # this event is only detected when connecting without ds4drv
on_playstation_button_release  # this event is only detected when connecting without ds4drv

Full documentation is available @ https://github.com/ArturSpirin/pyPS4Controller

Upvotes: 0

LEO 188
LEO 188

Reputation: 1

if event.type == pygame.JOYBUTTONDOWN:
        if j.get_button(0):
            PXV = -0.1
        if j.get_button(2):
            PXV = 0.1
    if event.type == pygame.JOYBUTTONUP:
        if j.get_button(0) or j.get_button(2):
            PXV = 0

joy button down works but PXV(player x velocity) does not get reset back to zero when i release my controller

Upvotes: -2

CodeSurgeon
CodeSurgeon

Reputation: 2465

You are really close! With a few tweaks, you code becomes this instead:

import pygame

pygame.init()
j = pygame.joystick.Joystick(0)
j.init()

try:
    while True:
        events = pygame.event.get()
        for event in events:
            if event.type == pygame.JOYAXISMOTION:
                print(event.dict, event.joy, event.axis, event.value)
            elif event.type == pygame.JOYBALLMOTION:
                print(event.dict, event.joy, event.ball, event.rel)
            elif event.type == pygame.JOYBUTTONDOWN:
                print(event.dict, event.joy, event.button, 'pressed')
            elif event.type == pygame.JOYBUTTONUP:
                print(event.dict, event.joy, event.button, 'released')
            elif event.type == pygame.JOYHATMOTION:
                print(event.dict, event.joy, event.hat, event.value)

except KeyboardInterrupt:
    print("EXITING NOW")
    j.quit()

Some resources that I found helpful in writing the up included pygame's event documentation, the use of python's dir function to see what properties a python object has, and the documentation for pygame's parent C library, SDL if you wanted a deeper explanation of what the property actually means. I included both the dictionary access version (using event.dict) as well as the property-access version (using just event.whatever_the_property_name_is). Note that event.button only gives you a number; it is up to you to manually create a mapping of what each button number means on your controller. Hope this clears it up!

Upvotes: 9

Related Questions