A joystick event reports a controller change to software. Button presses identify a button and its on/off state; stick movement reports an axis and position. For a two-motor robot, each stick’s vertical position can set the direction and throttle level of its matching motor, enabling forward, reverse, turns, spins, and variable speed. section 7.3 section 7.5.1
Analog sticks generate x-axis events when moved horizontally and y-axis events when moved vertically. Robot driving can concentrate on y-axis events: forward and backward stick travel becomes forward and backward motor throttle, while how far the stick moves determines the requested speed. section 7.3 section 7.5
Choose an event-reading layer that fits the application:
- Use Pygame to initialize a joystick device, poll the event queue, and call a handler for each received event. Handle JOYBUTTONDOWN and JOYAXISMOTION separately to inspect button identifiers or axis positions. section 7.4 section 7.4.2
- Read the Linux joystick device directly when a graphical game library is unnecessary. Connected controllers appear as device files such as /dev/input/js0, and jstest provides a live view of detected buttons and axes. section 7.5 section 7.5.1
- Parse each raw Linux event as a C-style structure containing a timestamp, value, type, and axis or button number. Python Struct('I h B B') reads one complete event at a time from the binary device file. section 7.5.1 section 7.5.2
Detect button and stick events with Pygame
Create joystick 0, then pass every queued event to a handler. A button-down event prints event.button; an axis-motion event prints event.axis and event.value. Moving a stick can produce repeated axis events, including very small position changes. section 7.4.2
Listing 7.2 pygame_joystick.py: Detecting specific joystick events with Pygame
#!/usr/bin/env python3
import pygame
FRAME_RATE = 60
WINDOW_SIZE = [100, 100]
def handle_event(event):
if event.type == pygame.JOYBUTTONDOWN:
print('button pressed', event.button)
if event.type == pygame.JOYAXISMOTION:
print('axis motion', event.axis, event.value)
def main():
pygame.init()
screen = pygame.display.set_mode(WINDOW_SIZE)
clock = pygame.time.Clock()
joystick = pygame.joystick.Joystick(0)
print('joystick name:', joystick.get_name())
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
return
handle_event(event)
clock.tick(FRAME_RATE)
main()
This runnable loop initializes Pygame and a controller, polls events continuously, and separates button presses from axis motion in one handler. section 7.4.2
Treat high event volume as part of the control problem. Sensitive analog-stick sensors can generate many events per second, potentially flooding motor throttle requests. Measure axis-event rate, then reduce requests by mapping positions to three directional levels and acting only when the level changes. A configurable dead zone can ignore movement near neutral. section 7.6 section 7.8
