I'm very new to evdev and am currently trying to use an xbox controller to control a small robot. I am successful with each of the buttons, but I can not seem to figure out how to get valid readings from the joysticks.
This code only works for button response.
edit: Whenever an ABXY button is pressed, EV_ABS events occur also. I am not sure how to distinguish between these values and actual values of the joystick. Additionally, the event codes from the joystick movements are inconsistent. Here is the code I'm currently running:
from evdev import InputDevice, categorize, ecodes
dev = InputDevice('/dev/input/event1')
print(dev)
for event in dev.read_loop():
if event.type == ecodes.EV_KEY:
print("button is pressed")
elif event.type == ecodes.EV_ABS:
print(event)
Any advice is appreciated! Thanks!
1 Answer 1
Python is not my favorite language, and there is probably a better method of calibrating, but I slapped this together. Hope it helps.
All the mappings and maximums were measured from my Xbox One Wireless controller, so you may need to experiment/adjust the constants to your own controller.
from evdev import list_devices, InputDevice, categorize, ecodes
CENTER_TOLERANCE = 350
STICK_MAX = 65536
dev = InputDevice( list_devices()[0] )
axis = {
ecodes.ABS_X: 'ls_x', # 0 - 65,536 the middle is 32768
ecodes.ABS_Y: 'ls_y',
ecodes.ABS_Z: 'rs_x',
ecodes.ABS_RZ: 'rs_y',
ecodes.ABS_BRAKE: 'lt', # 0 - 1023
ecodes.ABS_GAS: 'rt',
ecodes.ABS_HAT0X: 'dpad_x', # -1 - 1
ecodes.ABS_HAT0Y: 'dpad_y'
}
center = {
'ls_x': STICK_MAX/2,
'ls_y': STICK_MAX/2,
'rs_x': STICK_MAX/2,
'rs_y': STICK_MAX/2
}
last = {
'ls_x': STICK_MAX/2,
'ls_y': STICK_MAX/2,
'rs_x': STICK_MAX/2,
'rs_y': STICK_MAX/2
}
for event in dev.read_loop():
# calibrate zero on Y button
if event.type == ecodes.EV_KEY:
if categorize(event).keycode[0] == "BTN_WEST":
center['ls_x'] = last['ls_x']
center['ls_y'] = last['ls_y']
center['rs_x'] = last['rs_x']
center['rs_y'] = last['rs_y']
print( 'calibrated' )
#read stick axis movement
elif event.type == ecodes.EV_ABS:
if axis[ event.code ] in [ 'ls_x', 'ls_y', 'rs_x', 'rs_y' ]:
last[ axis[ event.code ] ] = event.value
value = event.value - center[ axis[ event.code ] ]
if abs( value ) <= CENTER_TOLERANCE:
value = 0
if axis[ event.code ] == 'rs_x':
if value < 0:
print('left')
else:
print('right')
print( value )
elif axis[ event.code ] == 'ls_y':
if value < 0:
print('foreward')
else:
print('backward')
print( value )
EV_ABSand/orEV_RELevents for the joysticks. The exact details depend on the gamepad, but I don't have an xbox around :-(EV_ABSaxes. ThoseABS_HAT*axes usually only have three possible values: -MAX, 0 and +MAX, that represent one button, no button and the other button, respectively, just as those old arcade digital joysticks.