From 0fe467268c5a6a58d6e8705a315f78f3e24090db Mon Sep 17 00:00:00 2001 From: Jacob Williams Date: Wed, 13 May 2026 20:16:20 -0400 Subject: [PATCH 1/4] Add battery voltage getter; simplify resetbot Replace the raw ADC threshold in Board.is_on with a voltage-based check (threshold 4.272 V) and add get_battery_voltage to read and convert ADC values. get_battery_voltage handles NanoXRP and RP2040 scaling and briefly toggles the VIN pin when needed. Also remove manual VIN pin reconfiguration from resetbot.py. --- XRPLib/board.py | 30 +++++++++++++++++++++++++++++- XRPLib/resetbot.py | 5 +---- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/XRPLib/board.py b/XRPLib/board.py index 8039f77..eb17e4f 100644 --- a/XRPLib/board.py +++ b/XRPLib/board.py @@ -46,7 +46,11 @@ def are_motors_powered(self) -> bool: :return: Returns true if the batteries are connected and powering the motors, false otherwise :rytpe: bool """ - return self.on_switch.read_u16() > 20000 + if "NanoXRP" in sys.implementation._machine: + return True + + threshold_voltage = 4.272 + return self.get_battery_voltage() > threshold_voltage def is_button_pressed(self) -> bool: """ @@ -125,3 +129,27 @@ def set_rgb_led(self, r:int, g:int, b:int): self.rgb_led.write() else: raise NotImplementedError("Board.set_rgb_led not implemented for the XRP Beta") + + def get_battery_voltage(self, vin_pin="BOARD_VIN_MEASURE") -> float: + """ + Returns the current battery voltage in volts. + + :param vin_pin: The pin the on/off switch is connected to + :type vin_pin: int + :return: Battery voltage in volts + :rtype: float + """ + + if "NanoXRP" in sys.implementation._machine: + # VIN pin on NanoXRP is also used for RM2. + self.on_switch = ADC(Pin(vin_pin)) + + battery_voltage = self.on_switch.read_u16() * (4.09 / 26000.0) + + Pin(vin_pin, Pin.OUT) + else: + # RP2040 ADC is 0-4095, MicroPython scales it to 0-65535. + # The voltage divider is calibrated to a 14V full-scale reading. + battery_voltage = self.on_switch.read_u16() / ((1024 * 64) / 14) + + return battery_voltage diff --git a/XRPLib/resetbot.py b/XRPLib/resetbot.py index 9a3bc37..54d11c1 100644 --- a/XRPLib/resetbot.py +++ b/XRPLib/resetbot.py @@ -77,7 +77,4 @@ def reset_hard(): reset_servos() if "XRPLib.webserver" in sys.modules: - reset_webserver() - -if "NanoXRP" in sys.implementation._machine: - Pin("BOARD_VIN_MEASURE", Pin.OUT) + reset_webserver() \ No newline at end of file From 5e21c1d072cda9540b7c17c231425d84c59daaf6 Mon Sep 17 00:00:00 2001 From: Jacob Williams Date: Wed, 13 May 2026 20:27:37 -0400 Subject: [PATCH 2/4] Add buzzer module and example; bump version Include XRPLib/buzzer.py and XRPExamples/buzzer_examples.py in package urls so the buzzer module and its example are packaged, and increment package version from 2.1.3 to 2.1.4. --- package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index fb9c107..3fb3f3f 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "urls": [ ["XRPLib/__init__.py", "github:Open-STEM/XRP_Micropython/XRPLib/__init__.py"], ["XRPLib/board.py", "github:Open-STEM/XRP_Micropython/XRPLib/board.py"], + ["XRPLib/buzzer.py", "github:Open-STEM/XRP_Micropython/XRPLib/buzzer.py"], ["XRPLib/controller.py", "github:Open-STEM/XRP_Micropython/XRPLib/controller.py"], ["XRPLib/defaults.py", "github:Open-STEM/XRP_Micropython/XRPLib/defaults.py"], ["XRPLib/differential_drive.py", "github:Open-STEM/XRP_Micropython/XRPLib/differential_drive.py"], @@ -20,6 +21,7 @@ ["XRPLib/timeout.py", "github:Open-STEM/XRP_Micropython/XRPLib/timeout.py"], ["XRPLib/webserver.py", "github:Open-STEM/XRP_Micropython/XRPLib/webserver.py"], ["XRPExamples/__init__.py", "github:Open-STEM/XRP_Micropython/XRPExamples/__init__.py"], + ["XRPExamples/buzzer_examples.py", "github:Open-STEM/XRP_Micropython/XRPExamples/buzzer_examples.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"], @@ -30,5 +32,5 @@ "deps": [ ["github:pimoroni/phew", "latest"] ], - "version": "2.1.3" + "version": "2.1.4" } From a2cfbc4c7b34f90dcc9fa8a4474d9734177967f9 Mon Sep 17 00:00:00 2001 From: Jacob Williams Date: Wed, 13 May 2026 22:25:08 -0400 Subject: [PATCH 3/4] Detect buzzer via Pin.board attribute Replace the module-import check for XRPLib.buzzer with an explicit hardware capability check using hasattr(Pin.board, "BOARD_BUZZER") in XRPLib/resetbot.py. --- XRPLib/resetbot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/XRPLib/resetbot.py b/XRPLib/resetbot.py index 54d11c1..0c6e3fb 100644 --- a/XRPLib/resetbot.py +++ b/XRPLib/resetbot.py @@ -70,7 +70,7 @@ def reset_hard(): if "XRPLib.board" in sys.modules: reset_led() -if "XRPLib.buzzer" in sys.modules: +if hasattr(Pin.board, "BOARD_BUZZER"): reset_buzzer() if "XRPLib.servo" in sys.modules: From 7d8cb9866d79925c82f1b155fd695d4e49607d00 Mon Sep 17 00:00:00 2001 From: Jacob Williams Date: Mon, 8 Jun 2026 15:03:16 -0400 Subject: [PATCH 4/4] Centralize DifferentialDrive hardware defaults Move platform-specific wheel defaults into DifferentialDrive, fixes blockly implementation. defaults.py no longer imports sys.implementation or branches for NanoXRP; it always uses get_default_differential_drive(). DifferentialDrive.__init__ now accepts 0.0 sentinel values for wheel_diam and wheel_track and sets the real defaults (NanoXRP vs other) by inspecting implementation._machine. This removes duplicated platform logic from defaults.py and centralizes hardware-dependent defaults in the drive class. --- XRPLib/defaults.py | 8 +------- XRPLib/differential_drive.py | 16 +++++++++++++--- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/XRPLib/defaults.py b/XRPLib/defaults.py index b467b01..266ee5f 100644 --- a/XRPLib/defaults.py +++ b/XRPLib/defaults.py @@ -10,7 +10,6 @@ from .webserver import Webserver from .buzzer import Buzzer from machine import Pin -from sys import implementation """ A simple file that constructs all of the default objects for the XRP robot @@ -24,12 +23,7 @@ motor_four = EncodedMotor.get_default_encoded_motor(index=4) imu = IMU.get_default_imu() - -if "NanoXRP" in implementation._machine: - drivetrain = DifferentialDrive(left_motor, right_motor, imu, wheel_diam=3.46, wheel_track=7.8) -else: - drivetrain = DifferentialDrive.get_default_differential_drive() - +drivetrain = DifferentialDrive.get_default_differential_drive() rangefinder = Rangefinder.get_default_rangefinder() reflectance = Reflectance.get_default_reflectance() servo_one = Servo.get_default_servo(index=1) diff --git a/XRPLib/differential_drive.py b/XRPLib/differential_drive.py index e68594d..2fc2ac6 100644 --- a/XRPLib/differential_drive.py +++ b/XRPLib/differential_drive.py @@ -27,7 +27,7 @@ def get_default_differential_drive(cls): return cls._DEFAULT_DIFFERENTIAL_DRIVE_INSTANCE - def __init__(self, left_motor: EncodedMotor, right_motor: EncodedMotor, imu: IMU = None, wheel_diam:float = 6.0, wheel_track:float = 15.5): + def __init__(self, left_motor: EncodedMotor, right_motor: EncodedMotor, imu: IMU = None, wheel_diam:float = 0.0, wheel_track:float = 0.0): """ A Differential Drive class designed for the XRP two-wheeled drive robot. @@ -48,8 +48,18 @@ def __init__(self, left_motor: EncodedMotor, right_motor: EncodedMotor, imu: IMU self.imu = imu self.brake_at_zero_power = False - self.wheel_diam = wheel_diam - self.track_width = wheel_track + + if (wheel_diam == 0.0): + if "NanoXRP" in implementation._machine: + self.wheel_diam = 3.46 + else: + self.wheel_diam = 6.0 + + if (wheel_track == 0.0): + if "NanoXRP" in implementation._machine: + self.wheel_track = 7.8 + else: + self.wheel_track = 15.5 self.heading_pid = None self.current_heading = None