-
-
Save artpoz/d66f72a6092b580b9903d088dd6d1262 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3 | |
__author__ = 'Artur Poznanski' | |
import evdev | |
import ev3dev.auto as ev3 | |
import threading | |
import time | |
## Some helpers ## | |
def clamp(n, minn, maxn): | |
return max(min(maxn, n), minn) | |
def scale(val, src, dst): | |
return (float(val - src[0]) / (src[1] - src[0])) * (dst[1] - dst[0]) + dst[0] | |
def scale_stick(value): | |
return scale(value,(0,255),(-1000,1000)) | |
def dc_clamp(value): | |
return clamp(value,-1000,1000) | |
## Initializing ## | |
print("Finding ps4 controller...") | |
devices = [evdev.InputDevice(fn) for fn in evdev.list_devices()] | |
ps4dev = devices[0].fn | |
gamepad = evdev.InputDevice(ps4dev) | |
forward_speed = 0 | |
side_speed = 0 | |
running = True | |
class MotorThread(threading.Thread): | |
def __init__(self): | |
self.right_motor = ev3.LargeMotor(ev3.OUTPUT_C) | |
self.left_motor = ev3.LargeMotor(ev3.OUTPUT_B) | |
threading.Thread.__init__(self) | |
def run(self): | |
print("Engine running!") | |
while running: | |
self.right_motor.run_forever(speed_sp=dc_clamp(forward_speed+side_speed)) | |
self.left_motor.run_forever(speed_sp=dc_clamp(-forward_speed+side_speed)) | |
self.right_motor.stop() | |
self.left_motor.stop() | |
motor_thread = MotorThread() | |
motor_thread.setDaemon(True) | |
motor_thread.start() | |
for event in gamepad.read_loop(): #this loops infinitely | |
if event.type == 3: #A stick is moved | |
if event.code == 0: #X axis on left stick | |
forward_speed = -scale_stick(event.value) | |
if event.code == 1: #Y axis on left stick | |
side_speed = -scale_stick(event.value) | |
if side_speed < 100 and side_speed > -100: | |
side_speed = 0 | |
if forward_speed < 100 and forward_speed > -100: | |
forward_speed = 0 | |
if event.type == 1 and event.code == 305 and event.value == 1: | |
print("X button is pressed. Stopping.") | |
running = False | |
time.sleep(0.5) # Wait for the motor thread to finish | |
break |
Figured out that connecting the PS4 controller registers as 3 input devices. Using this code:
devices = [evdev.InputDevice(fn) for fn in evdev.list_devices()] for device in devices: print(device.name)
It will output:
Wireless Controller
Wireless Controller Motion Sensors
Wireless Controller Touchpad
So the first is the gamepad (the buttons and the joysticks), the second is the accelerometer, and the third is the touchpad (touch and click).
What I haven't figured out still is how to capture the events for when the D-pad buttons (up,down,left,right) are pressed. They seem to be not registering from any of these three inputs of the PS4 controller connected with Bluetooth to the EV3. Anyone figured this out yet?
@Quantum357 if you can already confirm, let us know what is the exact event type, code, and value for the d-pad buttons. thanks!
Sorry for a dumb question but, I am using your code with the ev3dev os with a Pistorms-V2 module. I have everything set up correctly and can run the OS and I have paired the ps4 controller successfully but I am not getting any response when I run your program. Any suggestions? The error log is below if that is helpful.
_**Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/lib/python3.5/threading.py", line 914, in _bootstrap_inner
self.run()
File "/home/robot/ps4explor3r.py", line 42, in run
self.right_motor.run_forever(speed_sp=dc_clamp(forward_speed+side_speed))
File "/usr/lib/python3/dist-packages/ev3dev/core.py", line 799, in run_forever
setattr(self, key, kwargs[key])
File "/usr/lib/python3/dist-packages/ev3dev/core.py", line 589, in speed_sp
self._speed_sp = self.set_attr_int(self._speed_sp, 'speed_sp', value)
File "/usr/lib/python3/dist-packages/ev3dev/core.py", line 223, in set_attr_int
return self._set_attribute(attribute, name, str(int(value)))
File "/usr/lib/python3/dist-packages/ev3dev/core.py", line 216, in _set_attribute
raise Exception("%s is not connected" % self)
Exception: LargeMotor(outC) is not connected
Traceback (most recent call last):
File "/home/robot/ps4explor3r.py", line 51, in
for event in gamepad.read_loop(): #this loops infinitely
File "/usr/lib/python3/dist-packages/evdev/device.py", line 254, in read_loop
r, w, x = select([self.fd], [], [])
KeyboardInterrupt**_
There's a little problem in the stopping code. 305 is the O button, not the X button.
Is there a micropython version of this code? I wanted to the ps4 controller for a robot competition and waiting 20 whole seconds is not great. Can anyone help? (it will be great if i can control the motor separately with each joystick on my ps4)
How to detect if the d-pad buttons (up, down, left, right) are pressed? They don't seem to register when event.type == 1 like the rest of the buttons. Does anyone know if there is a reference somewhere that maps out all the event types, codes and values? I would like to find out too if the trackpad can also be used. Thanks!