Skip to content

Commit 0210cae

Browse files
committed
Refactor IMU/Drive/Buzzer
Clean up example and library code: remove unused Buzzer import/instantiation from examples, restore trailing newline. In XRPLib.buzzer remove duration constants. In differential_drive always initialize heading_pid when an IMU exists and fix comment/indentation around secondary controller setup. In IMU cache the NanoXRP check in self._is_nanoxrp and use it where needed. In reflectance replace an f-string with a plain string in a RuntimeError for minor linting consistency. Non-blocking buzzer inter-note gap handling Implement proper inter-note silence and robust non-blocking playback for the Buzzer. - Add _in_gap and _gap_end_time state to track short gaps between notes instead of sleeping inside the timer callback; refactor _update to advance songs after the gap expires and stop the timer when the song finishes. - Fix note parsing by initializing octave_pos and handling modifier positions to avoid undefined behavior. - When starting single non-blocking notes, clear any active song state and reset gap flags; when starting a non-blocking song, stop any existing timer/playback before beginning. - Ensure _in_gap is cleared on reset. - Update resetbot to call Buzzer.get_default_buzzer().reset_buzzer() (use instance) instead of calling a class method. These changes remove blocking sleeps from timer callbacks, prevent race conditions between single-note and song playback, and make non-blocking behavior deterministic. Clean up imports and fix flip_dir logic Move the re import to the module top in XRPLib/encoder.py and remove the redundant local import. In XRPLib/motor.py, replace the expression flip_dir ^ True with the clearer and correct not flip_dir for NanoXRP, ensuring proper boolean inversion and improving readability.
1 parent d596014 commit 0210cae

7 files changed

Lines changed: 11 additions & 23 deletions

File tree

XRPExamples/buzzer_examples.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
from lib.XRPLib.buzzer import Buzzer
21
from XRPLib.defaults import *
32
import time
43

@@ -8,9 +7,6 @@
87
play music while it is moving.
98
"""
109

11-
# Get the singleton instance of the buzzer
12-
buzzer = Buzzer.get_default_buzzer()
13-
1410
def simple_scale():
1511
"""Plays a basic C major scale."""
1612
print("Playing a simple scale...")
@@ -82,4 +78,4 @@ def main():
8278

8379
musical_robot()
8480

85-
main()
81+
main()

XRPLib/buzzer.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,6 @@ class Buzzer:
1515
Supports natural notes, sharps, and flats.
1616
"""
1717

18-
# Duration constants (based on a default 120 BPM tempo)
19-
WHOLE = 4
20-
HALF = 2
21-
QUARTER = 1
22-
EIGHTH = 0.5
23-
SIXTEENTH = 0.25
24-
2518
# Note names to semitone offset (semitones from C4 = 0)
2619
NOTE_OFFSETS = {
2720
# Natural notes
@@ -389,4 +382,4 @@ def play_twinkle_twinkle(self, blocking: bool = True):
389382
("F4", "quarter"), ("F4", "quarter"), ("E4", "quarter"), ("E4", "quarter"),
390383
("D4", "quarter"), ("D4", "quarter"), ("C4", "half"),
391384
]
392-
self.play_song(twinkle_twinkle, tempo, blocking)
385+
self.play_song(twinkle_twinkle, tempo, blocking)

XRPLib/differential_drive.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,7 @@ def __init__(self, left_motor: EncodedMotor, right_motor: EncodedMotor, imu: IMU
5757
self.turning = False
5858

5959
if self.imu:
60-
# if the IMU is initialized, then create a PID controller that can be used
61-
# to maintain a constant heading when driving
62-
if not "NanoXRP" in implementation._machine:
63-
self.heading_pid = PID( kp = 0.075, kd=0.001, )
60+
self.heading_pid = PID( kp = 0.075, kd=0.001, )
6461

6562
def set_effort(self, left_effort: float, right_effort: float) -> None:
6663
"""
@@ -313,7 +310,7 @@ def turn(self, turn_degrees: float, max_effort: float = 0.5, timeout: float = No
313310
tolerance = 1,
314311
tolerance_count = 3
315312
)
316-
# Secondary controller to keep encoder values in sync
313+
# Secondary controller to keep encoder values in sync
317314
if secondary_controller is None:
318315
secondary_controller = PID(
319316
kp = 0.32,
@@ -335,7 +332,7 @@ def turn(self, turn_degrees: float, max_effort: float = 0.5, timeout: float = No
335332
tolerance = 1,
336333
tolerance_count = 3
337334
)
338-
# Secondary controller to keep encoder values in sync
335+
# Secondary controller to keep encoder values in sync
339336
if secondary_controller is None:
340337
secondary_controller = PID(
341338
kp = 0.25,

XRPLib/encoder.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import rp2
55
import time
66
from sys import implementation
7+
import re
78

89
class Encoder:
910
if "NanoXRP" in implementation._machine:
@@ -53,7 +54,6 @@ def _get_pin_id(self, pin):
5354
# String representation is usually "Pin(GPIO16, mode=IN)" or "Pin(16)"
5455
# We look for the numeric part associated with the GPIO.
5556
s = str(pin)
56-
import re
5757
match = re.search(r'(\d+)', s)
5858
if match:
5959
return int(match.group(1))

XRPLib/imu.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ def get_default_imu(cls):
3030
return cls._DEFAULT_IMU_INSTANCE
3131

3232
def __init__(self, scl_pin: int|str = "I2C_SCL_1", sda_pin: int|str = "I2C_SDA_1", addr=LSM_ADDR_PRIMARY):
33+
self._is_nanoxrp = "NanoXRP" in implementation._machine
34+
3335
# I2C values
3436
self.i2c = I2C(id=1, scl=Pin(scl_pin), sda=Pin(sda_pin), freq=400000)
3537
self.addr = addr
@@ -551,7 +553,7 @@ def _update_imu_readings(self):
551553
self.get_gyro_rates()
552554

553555
# Flip and swap for NanoXRP
554-
if "NanoXRP" in implementation._machine:
556+
if self._is_nanoxrp:
555557
delta_pitch = self.irq_v[1][1] / 1000 / self.timer_frequency
556558
delta_roll = self.irq_v[1][0] / 1000 / self.timer_frequency
557559
delta_yaw = -1 * self.irq_v[1][2] / 1000 / self.timer_frequency

XRPLib/reflectance.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ def get_middle(self) -> float:
5858
: rtype: float
5959
"""
6060
if self._middleReflectance is None:
61-
raise RuntimeError(f"Middle reflectance sensor is not available on this board configuration.")
61+
raise RuntimeError("Middle reflectance sensor is not available on this board configuration.")
6262

6363
return self._get_value(self._middleReflectance)
6464

XRPLib/resetbot.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ def reset_buzzer():
3333
# Turn off the buzzer
3434
try:
3535
# Turn off the Buzzer if the board has one
36-
Buzzer.reset_buzzer()
36+
Buzzer.get_default_buzzer().reset_buzzer()
3737
except:
3838
pass
3939

0 commit comments

Comments
 (0)