Skip to content

Add in Gamepad support #86

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jul 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions XRPExamples/gamepad_example.blocks
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from XRPLib.gamepad import *
from XRPLib.differential_drive import DifferentialDrive

gp = Gamepad.get_default_gamepad()

differentialDrive = DifferentialDrive.get_default_differential_drive()


while not (gp.is_button_pressed(gp.BACK)):
differentialDrive.arcade((gp.get_value(gp.Y1)), (gp.get_value(gp.X1)))



## [2025-07-13 01:36:24]
##XRPBLOCKS {"blocks":{"languageVersion":0,"blocks":[{"type":"controls_whileUntil","id":"#/DDnbE2JxVsLQo`C`e^","x":-363,"y":16,"fields":{"MODE":"UNTIL"},"inputs":{"BOOL":{"block":{"type":"xrp_gp_button_pressed","id":"DtLypJc;SU2xT4A~S3nV","fields":{"GPBUTTON":"BACK"}}},"DO":{"block":{"type":"xrp_arcade","id":"(|]Iln#JYa9hzgEz+(4g","inputs":{"STRAIGHT":{"shadow":{"type":"math_number","id":"FOj1uvC$:~x/+cX}d(:|","fields":{"NUM":0.8}},"block":{"type":"xrp_gp_get_value","id":"s#GS_Dt)B8Cb9+4ctpwk","fields":{"GPVALUE":"Y1"}}},"TURN":{"shadow":{"type":"math_number","id":"n1jAKrjST!+3#bfChh$d","fields":{"NUM":0.2}},"block":{"type":"xrp_gp_get_value","id":"*]`U9XHyYnA?Gp%U;$NF","fields":{"GPVALUE":"X1"}}}}}}}}]}}
97 changes: 97 additions & 0 deletions XRPLib/gamepad.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
from ble.blerepl import uart
import sys
from micropython import const

class Gamepad:

_DEFAULT_GAMEPAD_INSTANCE = None

X1 = const(0)
Y1 = const(1)
X2 = const(2)
Y2 = const(3)
BUTTON_A = const(4)
BUTTON_B = const(5)
BUTTON_X = const(6)
BUTTON_Y = const(7)
BUMPER_L = const(8)
BUMPER_R = const(9)
TRIGGER_L = const(10)
TRIGGER_R = const(11)
BACK = const(12)
START = const(13)
DPAD_UP = const(14)
DPAD_DN = const(15)
DPAD_L = const(16)
DPAD_R = const(17)

_joyData = [
0.0,
0.0,
0.0,
0.0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0]

@classmethod
def get_default_gamepad(cls):
"""
Get the default XRP bluetooth joystick instance. This is a singleton, so only one instance of the gamepad sensor will ever exist.
"""
if cls._DEFAULT_GAMEPAD_INSTANCE is None:
cls._DEFAULT_GAMEPAD_INSTANCE = cls()
cls._DEFAULT_GAMEPAD_INSTANCE.start()
return cls._DEFAULT_GAMEPAD_INSTANCE

def __init__(self):
"""
Manages communication with gamepad data coming from a remote computer via bluetooth

"""
def start(self):
"""
Signals the remote computer to begin sending gamepad data packets.
"""
for i in range(len(self._joyData)):
self._joyData[i] = 0.0
uart.set_data_callback(self._data_callback)
sys.stdout.write(chr(27))
sys.stdout.write(chr(101))


def stop(self):
"""
Signals the remote computer to stop sending gamepad data packets.
"""
sys.stdout.write(chr(27))
sys.stdout.write(chr(102))

def get_value(self, index:int) -> float:
"""
Get the current value of a joystick axis

:param index: The joystick axis index
Gamepad.X1, Gamepad.Y1, Gamepad.X2, Gamepad.Y2
:type int
:returns: The value of the joystick between -1 and 1
:rtype: float
"""
return -self._joyData[index] #returning the negative to make normal for user

def is_button_pressed(self, index:int) -> bool:
"""
Checks if a specific button is currently pressed.

:param index: The button index
Gamepad.BUTTON_A, Gamepad.TRIGGER_L, Gamepad.DPAD_UP, etc
:type int
:returns: The value of the button 1 or 0
:rtype: bool
"""
return self._joyData[index] > 0

def _data_callback(self, data):
if(data[0] == 0x55 and len(data) == data[1] + 2):
for i in range(2, data[1] + 2, 2):
self._joyData[data[i]] = round(data[i + 1]/127.5 - 1, 2)


10 changes: 10 additions & 0 deletions XRPLib/resetbot.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,21 @@ def reset_webserver():
# Shut off the webserver and close network connections
Webserver.get_default_webserver().stop_server()

def reset_gamepad():
from XRPLib.gamepad import Gamepad
# Stop the browser from sending more gamepad data
Gamepad.get_default_gamepad().stop()

def reset_hard():
reset_gamepad()
reset_motors()
reset_led()
reset_servos()
reset_webserver()

if "XRPLib.gamepad" in sys.modules:
reset_gamepad()

if "XRPLib.encoded_motor" in sys.modules:
reset_motors()

Expand All @@ -50,3 +59,4 @@ def reset_hard():

if "XRPLib.webserver" in sys.modules:
reset_webserver()

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
["XRPLib/differential_drive.py", "github:Open-STEM/XRP_Micropython/XRPLib/differential_drive.py"],
["XRPLib/encoded_motor.py", "github:Open-STEM/XRP_Micropython/XRPLib/encoded_motor.py"],
["XRPLib/encoder.py", "github:Open-STEM/XRP_Micropython/XRPLib/encoder.py"],
["XRPLib/gamepad.py", "github:Open-STEM/XRP_Micropython/XRPLib/gamepad.py"],
["XRPLib/imu_defs.py", "github:Open-STEM/XRP_Micropython/XRPLib/imu_defs.py"],
["XRPLib/imu.py", "github:Open-STEM/XRP_Micropython/XRPLib/imu.py"],
["XRPLib/motor_group.py", "github:Open-STEM/XRP_Micropython/XRPLib/motor_group.py"],
Expand All @@ -20,6 +21,7 @@
["XRPLib/webserver.py", "github:Open-STEM/XRP_Micropython/XRPLib/webserver.py"],
["XRPExamples/__init__.py", "github:Open-STEM/XRP_Micropython/XRPExamples/__init__.py"],
["XRPExamples/drive_examples.py", "github:Open-STEM/XRP_Micropython/XRPExamples/drive_examples.py"],
["XRPExamples/gamepad_example.blocks", "github:Open-STEM/XRP_Micropython/XRPExamples/gamepad_example.blocks"],
["XRPExamples/installation_verification.py", "github:Open-STEM/XRP_Micropython/XRPExamples/installation_verification.py"],
["XRPExamples/led_example.py", "github:Open-STEM/XRP_Micropython/XRPExamples/led_example.py"],
["XRPExamples/sensor_examples.py", "github:Open-STEM/XRP_Micropython/XRPExamples/sensor_examples.py"],
Expand All @@ -28,5 +30,5 @@
"deps": [
["github:pimoroni/phew", "latest"]
],
"version": "2.0.1"
"version": "2.1.3"
}