User avatar
Davespice
Forum Moderator
Forum Moderator
Posts: 1662
Joined: Fri Oct 14, 2011 8:06 pm
Location: The Netherlands
Contact: Twitter

Simultaneously use both push buttons and joystick

Thu Jul 02, 2015 4:58 pm

Hi folks
Okay so I just wanted to post some example code here to help those of you who are writing games for Tim Peake to play. Perhaps you want to use the joystick to move and the GPIO push buttons to fire?

Information on using the joystick can be found here and on the push buttons here (you'll need to have built that breadboard set up in order to test this code).

The problem you'll have is that you need to use something like pygame to consume events from the joystick, but this isn't neatly compatible with how GPIO button detection works. Marrying the two together could be a bit of a pain. However there is a clever trick you can do which is demonstrated by the code below.

You hook up the GPIO edge detection as per the examples given but you then make it write phantom key press events to the Linux event queue. That way you can receive the events from both joystick and push buttons in pygame at the same time!

To use this you need to install a python module called evdev.

Code: Select all

sudo pip-3.2 install evdev
Also note that the joystick is rotated clockwise through 90 degrees when in flight configuration, so UP on the joystick is actually RIGHT. So I've compensated for this in the code where I test for the key codes.

The code is below.

Code: Select all

#!/usr/bin/python3
import time
import RPi.GPIO as GPIO
from evdev import uinput, ecodes as e
import pygame

print("Press Escape to quit")
time.sleep(1)

from pygame.locals import *
from astro_pi import AstroPi

ap = AstroPi()
ap.set_rotation(270)

pygame.init()
pygame.display.set_mode((640, 480))

UP = 26
DOWN = 13
LEFT = 20
RIGHT = 19
A = 16
B = 21  

running = True

keys = {}  # use a dictionary to map GPIO nos to key events

keys[UP] = e.KEY_U
keys[DOWN] = e.KEY_D
keys[LEFT] = e.KEY_L
keys[RIGHT] = e.KEY_R
keys[A] = e.KEY_A
keys[B] = e.KEY_B

ui = uinput.UInput()

def button_pressed(button):
    global ui
    key = keys[button]
    key_state = not GPIO.input(button)
    ui.write(e.EV_KEY, key, key_state) 
    ui.syn()

GPIO.setmode(GPIO.BCM)

for pin in [UP, DOWN, LEFT, RIGHT, A, B]:
    GPIO.setup(pin, GPIO.IN, GPIO.PUD_UP)
    GPIO.add_event_detect(pin, GPIO.BOTH, callback=button_pressed, bouncetime=50)

while running:
    for event in pygame.event.get():
        if event.type == KEYUP:
            ap.clear()
        elif event.type == KEYDOWN:
            if event.key == K_ESCAPE:
                running = False
            if event.key == pygame.K_DOWN:
                ap.show_letter("L")
            elif event.key == pygame.K_UP:
                ap.show_letter("R")
            elif event.key == pygame.K_LEFT:
                ap.show_letter("U")
            elif event.key == pygame.K_RIGHT:
                ap.show_letter("D")
            elif event.key == pygame.K_RETURN:
                ap.show_letter("E")
            elif event.key == pygame.K_u:
                ap.show_letter("u")
            elif event.key == pygame.K_d:
                ap.show_letter("d")
            elif event.key == pygame.K_l:
                ap.show_letter("l")
            elif event.key == pygame.K_r:
                ap.show_letter("r")
            elif event.key == pygame.K_a:
                ap.show_letter("a")
            elif event.key == pygame.K_b:
                ap.show_letter("b")

ap.clear()
ui.close()
GPIO.cleanup()
Attachments
IMG_0193.JPG
IMG_0193.JPG (229.98 KiB) Viewed 1738 times

konbert
Posts: 1
Joined: Thu Mar 24, 2016 7:23 pm

Re: Simultaneously use both push buttons and joystick

Thu Mar 24, 2016 7:25 pm

This is nice, but an astro-pi is headless and this code will not work without screen because of pygame.
Is there a solution without using pygame?

Return to “Astro Pi”