Skip to content

Commit c1aa463

Browse files
committed
updated for combined nano release
Updated the XRPLib, XRPExamples, xprlib.zip, and package.json for all the new files.
1 parent e00736c commit c1aa463

13 files changed

Lines changed: 282 additions & 147 deletions

File tree

public/XRPLib.zip

4.74 KB
Binary file not shown.

public/lib/XRPExamples/dashboard sample.py

Lines changed: 0 additions & 65 deletions
This file was deleted.

public/lib/XRPLib/board.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,11 @@ def are_motors_powered(self) -> bool:
4646
:return: Returns true if the batteries are connected and powering the motors, false otherwise
4747
:rytpe: bool
4848
"""
49-
return self.on_switch.read_u16() > 20000
49+
if "NanoXRP" in sys.implementation._machine:
50+
return True
51+
52+
threshold_voltage = 4.272
53+
return self.get_battery_voltage() > threshold_voltage
5054

5155
def is_button_pressed(self) -> bool:
5256
"""
@@ -125,3 +129,27 @@ def set_rgb_led(self, r:int, g:int, b:int):
125129
self.rgb_led.write()
126130
else:
127131
raise NotImplementedError("Board.set_rgb_led not implemented for the XRP Beta")
132+
133+
def get_battery_voltage(self, vin_pin="BOARD_VIN_MEASURE") -> float:
134+
"""
135+
Returns the current battery voltage in volts.
136+
137+
:param vin_pin: The pin the on/off switch is connected to
138+
:type vin_pin: int
139+
:return: Battery voltage in volts
140+
:rtype: float
141+
"""
142+
143+
if "NanoXRP" in sys.implementation._machine:
144+
# VIN pin on NanoXRP is also used for RM2.
145+
self.on_switch = ADC(Pin(vin_pin))
146+
147+
battery_voltage = self.on_switch.read_u16() * (4.09 / 26000.0)
148+
149+
Pin(vin_pin, Pin.OUT)
150+
else:
151+
# RP2040 ADC is 0-4095, MicroPython scales it to 0-65535.
152+
# The voltage divider is calibrated to a 14V full-scale reading.
153+
battery_voltage = self.on_switch.read_u16() / ((1024 * 64) / 14)
154+
155+
return battery_voltage

public/lib/XRPLib/defaults.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88
from .reflectance import Reflectance
99
from .servo import Servo
1010
from .webserver import Webserver
11+
from .buzzer import Buzzer
1112
from machine import Pin
13+
from sys import implementation
1214

1315
"""
1416
A simple file that constructs all of the default objects for the XRP robot
@@ -18,9 +20,16 @@
1820
left_motor = EncodedMotor.get_default_encoded_motor(index=1)
1921
right_motor = EncodedMotor.get_default_encoded_motor(index=2)
2022
motor_three = EncodedMotor.get_default_encoded_motor(index=3)
21-
motor_four = EncodedMotor.get_default_encoded_motor(index=4)
23+
if hasattr(Pin.board, "MOTOR_4_IN_1"):
24+
motor_four = EncodedMotor.get_default_encoded_motor(index=4)
25+
2226
imu = IMU.get_default_imu()
23-
drivetrain = DifferentialDrive.get_default_differential_drive()
27+
28+
if "NanoXRP" in implementation._machine:
29+
drivetrain = DifferentialDrive(left_motor, right_motor, imu, wheel_diam=3.46, wheel_track=7.8)
30+
else:
31+
drivetrain = DifferentialDrive.get_default_differential_drive()
32+
2433
rangefinder = Rangefinder.get_default_rangefinder()
2534
reflectance = Reflectance.get_default_reflectance()
2635
servo_one = Servo.get_default_servo(index=1)
@@ -31,4 +40,7 @@
3140
if hasattr(Pin.board, "SERVO_3"):
3241
servo_three = Servo.get_default_servo(index=3)
3342
if hasattr(Pin.board, "SERVO_4"):
34-
servo_four = Servo.get_default_servo(index=4)
43+
servo_four = Servo.get_default_servo(index=4)
44+
45+
if hasattr(Pin.board, "BOARD_BUZZER"):
46+
buzzer = Buzzer.get_default_buzzer()

public/lib/XRPLib/differential_drive.py

Lines changed: 73 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from .timeout import Timeout
66
import time
77
import math
8+
from sys import implementation
89

910
class DifferentialDrive:
1011

@@ -56,8 +57,6 @@ def __init__(self, left_motor: EncodedMotor, right_motor: EncodedMotor, imu: IMU
5657
self.turning = False
5758

5859
if self.imu:
59-
# if the IMU is initialized, then create a PID controller that can be used
60-
# to maintain a constant heading when driving
6160
self.heading_pid = PID( kp = 0.075, kd=0.001, )
6261

6362
def set_effort(self, left_effort: float, right_effort: float) -> None:
@@ -198,24 +197,40 @@ def straight(self, distance: float, max_effort: float = 0.5, timeout: float = No
198197
starting_left = self.get_left_encoder_position()
199198
starting_right = self.get_right_encoder_position()
200199

201-
202-
if main_controller is None:
203-
main_controller = PID(
204-
kp = 0.1,
205-
ki = 0.04,
206-
kd = 0.04,
207-
min_output = 0.3,
208-
max_output = max_effort,
209-
max_integral = 10,
210-
tolerance = 0.25,
211-
tolerance_count = 3,
212-
)
213-
214-
# Secondary controller to keep encoder values in sync
215-
if secondary_controller is None:
216-
secondary_controller = PID(
217-
kp = 0.075, kd=0.001,
218-
)
200+
if "NanoXRP" in implementation._machine:
201+
if main_controller is None:
202+
main_controller = PID(
203+
kp = 0.32,
204+
kd = 0.0184,
205+
min_output = 0.1,
206+
max_output = max_effort,
207+
tolerance = 0.25,
208+
tolerance_count = 3,
209+
)
210+
211+
# Secondary controller to keep encoder values in sync
212+
if secondary_controller is None:
213+
secondary_controller = PID(
214+
kp = 0.012, kd=0.00129,
215+
)
216+
else:
217+
if main_controller is None:
218+
main_controller = PID(
219+
kp = 0.1,
220+
ki = 0.04,
221+
kd = 0.04,
222+
min_output = 0.3,
223+
max_output = max_effort,
224+
max_integral = 10,
225+
tolerance = 0.25,
226+
tolerance_count = 3,
227+
)
228+
229+
# Secondary controller to keep encoder values in sync
230+
if secondary_controller is None:
231+
secondary_controller = PID(
232+
kp = 0.075, kd=0.001,
233+
)
219234

220235
if self.imu is not None:
221236
# record current heading to maintain it
@@ -284,28 +299,44 @@ def turn(self, turn_degrees: float, max_effort: float = 0.5, timeout: float = No
284299
time_out = Timeout(timeout)
285300
starting_left = self.get_left_encoder_position()
286301
starting_right = self.get_right_encoder_position()
287-
288-
if main_controller is None:
289-
main_controller = PID(
290-
# kp = 0.2,
291-
# ki = 0.004,
292-
# kd = 0.0036,
293-
kd = 0.0036 + 0.0034 * (max(max_effort, 0.5) - 0.5) * 2,
294-
kp = 0.2,
295-
ki = 0.004,
296-
#kd = 0.007,
297-
min_output = 0.1,
298-
max_output = max_effort,
299-
max_integral = 30,
300-
tolerance = 1,
301-
tolerance_count = 3
302-
)
303-
304-
# Secondary controller to keep encoder values in sync
305-
if secondary_controller is None:
306-
secondary_controller = PID(
307-
kp = 0.25,
308-
)
302+
303+
if "NanoXRP" in implementation._machine:
304+
if main_controller is None:
305+
main_controller = PID(
306+
kp = 0.016,
307+
kd = 0.0008,
308+
min_output = 0.05,
309+
max_output = max_effort,
310+
tolerance = 1,
311+
tolerance_count = 3
312+
)
313+
# Secondary controller to keep encoder values in sync
314+
if secondary_controller is None:
315+
secondary_controller = PID(
316+
kp = 0.32,
317+
kd = 0.0184,
318+
)
319+
else:
320+
if main_controller is None:
321+
main_controller = PID(
322+
# kp = 0.2,
323+
# ki = 0.004,
324+
# kd = 0.0036,
325+
kd = 0.0036 + 0.0034 * (max(max_effort, 0.5) - 0.5) * 2,
326+
kp = 0.2,
327+
ki = 0.004,
328+
#kd = 0.007,
329+
min_output = 0.1,
330+
max_output = max_effort,
331+
max_integral = 30,
332+
tolerance = 1,
333+
tolerance_count = 3
334+
)
335+
# Secondary controller to keep encoder values in sync
336+
if secondary_controller is None:
337+
secondary_controller = PID(
338+
kp = 0.25,
339+
)
309340

310341
if use_imu and (self.imu is not None):
311342
turn_degrees += self.imu.get_yaw()

public/lib/XRPLib/encoded_motor.py

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
from .motor import SinglePWMMotor, DualPWMMotor
22
from .encoder import Encoder
3-
from machine import Timer
3+
from machine import Timer, Pin
44
from .controller import Controller
55
from .pid import PID
6-
import sys
6+
from sys import implementation
77

88
class EncodedMotor:
99

@@ -25,10 +25,10 @@ def get_default_encoded_motor(cls, index:int = 1):
2525
:type index: int
2626
"""
2727

28-
if "RP2350" in sys.implementation._machine:
29-
MotorImplementation = DualPWMMotor
30-
else:
28+
if "Beta" in implementation._machine:
3129
MotorImplementation = SinglePWMMotor
30+
else:
31+
MotorImplementation = DualPWMMotor
3232

3333
if index == 1:
3434
if cls._DEFAULT_LEFT_MOTOR_INSTANCE is None:
@@ -51,7 +51,7 @@ def get_default_encoded_motor(cls, index:int = 1):
5151
Encoder(2, "MOTOR_3_ENCODER_A", "MOTOR_3_ENCODER_B")
5252
)
5353
motor = cls._DEFAULT_MOTOR_THREE_INSTANCE
54-
elif index == 4:
54+
elif index == 4 and hasattr(Pin.board, "MOTOR_4_IN_1"):
5555
if cls._DEFAULT_MOTOR_FOUR_INSTANCE is None:
5656
cls._DEFAULT_MOTOR_FOUR_INSTANCE = cls(
5757
MotorImplementation("MOTOR_4_IN_1", "MOTOR_4_IN_2"),
@@ -70,12 +70,21 @@ def __init__(self, motor, encoder: Encoder):
7070
self.brake_at_zero = False
7171

7272
self.target_speed = None
73-
self.DEFAULT_SPEED_CONTROLLER = PID(
74-
kp=0.035,
75-
ki=0.03,
76-
kd=0,
77-
max_integral=50
78-
)
73+
if "NanoXRP" in implementation._machine:
74+
self.DEFAULT_SPEED_CONTROLLER = PID(
75+
kp=0.015,
76+
ki=0.06,
77+
kd=0,
78+
max_integral=1/0.06
79+
)
80+
else:
81+
self.DEFAULT_SPEED_CONTROLLER = PID(
82+
kp=0.035,
83+
ki=0.03,
84+
kd=0,
85+
max_integral=50
86+
)
87+
7988
self.speedController = self.DEFAULT_SPEED_CONTROLLER
8089
self.prev_position = 0
8190
self.speed = 0

0 commit comments

Comments
 (0)