Compare commits

...

64 Commits

Author SHA1 Message Date
fb07967c4c Merge pull request 'dev' (#15) from dev into main
Reviewed-on: #15
2026-01-22 22:26:18 +00:00
6beeb837cf Fixed everything, final commit before 1.0.0 2026-01-22 16:25:09 -06:00
c8b520c12c Add templates/xboxcontroller.py 2026-01-22 20:29:11 +00:00
fab9650a9f Add templates/color-sensor-start-logic.py 2026-01-22 18:30:18 +00:00
8489a87ada 2026-01-21 16:49:54 -06:00
6ade2c2dc6 Merge pull request 'dev' (#14) from dev into main
Reviewed-on: #14
2026-01-09 19:21:14 +00:00
e7d5f2bdfc Update diagnostics/FullDiagnostics.py 2026-01-09 19:20:14 +00:00
734c60d2be Update diagnostics/ColorSensorDiagnostics.py 2026-01-09 00:04:25 +00:00
517d6a3e91 Update diagnostics/FullDiagnostics.py 2026-01-09 00:04:11 +00:00
6de3ebda08 Update diagnostics/MotorDiagnostics.py 2026-01-09 00:01:01 +00:00
b7f2978e66 Merge pull request 'Update README.md' (#13) from dev into main
Reviewed-on: #13
2025-12-19 22:47:39 +00:00
53402545c8 Update README.md 2025-12-19 22:46:10 +00:00
98a1e9c466 Merge pull request 'dev' (#12) from dev into main
Reviewed-on: #12
2025-12-19 22:45:12 +00:00
78e31482d0 Upload files to "diagnostics" 2025-12-19 22:44:53 +00:00
a236032857 Update diagnostics/HubDiagnostics.py 2025-12-19 22:43:14 +00:00
7095021001 Update diagnostics/FullDiagnostics.py 2025-12-19 22:43:08 +00:00
1812f91837 Update diagnostics/DriveBaseDiagnostics.py 2025-12-19 22:43:01 +00:00
9c6b44a31e Update diagnostics/ColorSensorDiagnostics.py 2025-12-19 22:42:43 +00:00
8b2748d503 Update diagnostics/ColorSensorDiagnostics.py 2025-12-19 22:41:50 +00:00
dd9c0910c1 Update diagnostics/BatteryDiagnostics.py 2025-12-19 22:41:40 +00:00
e067ae0f99 Upload files to "/" 2025-12-19 22:41:25 +00:00
abb96d5ac6 Delete diagnostics/OtherFunctions.py 2025-12-19 22:41:10 +00:00
4621a3ee75 Delete diagnostics/MotorDiagnostics.py 2025-12-19 22:41:07 +00:00
5b29d631ca Delete diagnostics/HubDiagnostics.py 2025-12-19 22:41:03 +00:00
694d4af5bd Delete diagnostics/FullDiagnostics.py 2025-12-19 22:40:59 +00:00
666247b33f Delete diagnostics/DriveBaseDiagnostics.py 2025-12-19 22:40:55 +00:00
ef01564705 Delete diagnostics/ColorSensorDiagnostics.py 2025-12-19 22:40:51 +00:00
541006041b Delete diagnostics/BatteryDiagnostics.py 2025-12-19 22:40:48 +00:00
557b025316 Delete diagnostics-old/OtherFunctions.py 2025-12-19 22:40:41 +00:00
06c7cf6e9f Delete diagnostics-old/MotorDiagnostics.py 2025-12-19 22:40:38 +00:00
5724bd9b81 Delete diagnostics-old/HubDiagnostics.py 2025-12-19 22:40:33 +00:00
5ab2af15fb Delete diagnostics-old/FullDiagnostics.py 2025-12-19 22:40:29 +00:00
46cf6dd3f3 Delete diagnostics-old/DriveBaseDiagnostics.py 2025-12-19 22:40:25 +00:00
657d706d82 Delete diagnostics-old/ColorSensorDiagnostics.py 2025-12-19 22:40:21 +00:00
2967456390 Delete diagnostics-old/BatteryDiagnostics.py 2025-12-19 22:40:17 +00:00
2b44be0315 Update README.md 2025-12-19 22:40:10 +00:00
3408ed5760 Update diagnostics/OtherFunctions.py 2025-12-18 19:22:39 +00:00
c8b72eff51 Update diagnostics/HubDiagnostics.py 2025-12-18 19:22:25 +00:00
ae9cbac032 Update diagnostics/FullDiagnostics.py 2025-12-18 19:09:39 +00:00
5b9ab7daed Update diagnostics/ColorSensorDiagnostics.py 2025-12-18 17:14:13 +00:00
4473d794bd Update diagnostics/FullDiagnostics.py 2025-12-18 17:12:44 +00:00
6884969cc1 Update diagnostics/ColorSensorDiagnostics.py 2025-12-18 17:11:51 +00:00
9620a0d935 Upload files to "diagnostics" 2025-12-18 17:09:21 +00:00
95adf1de84 Upload files to "diagnostics" 2025-12-18 16:42:55 +00:00
8441446e44 Add diagnostics-old/OtherFunctions.py 2025-12-17 17:25:07 +00:00
3efeafc55e Update diagnostics-old/MotorDiagnostics.py 2025-12-17 17:05:29 +00:00
acbe26eb50 Update diagnostics-old/HubDiagnostics.py 2025-12-17 17:05:21 +00:00
93d17833d1 Update diagnostics-old/FullDiagnostics.py 2025-12-17 17:05:13 +00:00
35b3726f46 Update diagnostics-old/DriveBaseDiagnostics.py 2025-12-17 17:05:05 +00:00
148d7a1c43 Update diagnostics-old/ColorSensorDiagnostics.py 2025-12-17 17:04:58 +00:00
f916a02d5a Update diagnostics-oldColorSensorDiagnostics.py 2025-12-17 17:04:52 +00:00
4a6cfc9974 Update diagnostics-old/BatteryDiagnostics.py 2025-12-17 17:04:45 +00:00
f28ec4994d Update diagnostics/HubDiagnostics.py 2025-12-17 17:04:25 +00:00
c1856220b1 Update diagnostics/HubDiagnostics.py 2025-12-17 15:20:45 +00:00
e6a2c24338 Add diagnostics/HubDiagnostics.py 2025-12-17 15:18:12 +00:00
2500f3e09b Add diagnostics/DriveBaseDiagnostics.py 2025-12-17 15:17:47 +00:00
979278d437 Update diagnostics/MotorDiagnostics.py 2025-12-17 13:29:57 +00:00
e02c0a5591 Add diagnostics/ColorSensorDiagnostics.py 2025-12-15 13:35:06 +00:00
60384d4367 Merge pull request 'dev' (#11) from dev into main
Reviewed-on: Arcmyx/pynamics-pybricks-utils#11
2025-12-11 14:29:29 +00:00
116836b86d Removed ambiguous Unicode characters 2025-12-11 14:29:13 +00:00
f58372d166 Update diagnostics/MotorDiagnostics.py 2025-12-11 14:28:52 +00:00
f688ef0cb3 Update diagnostics/MotorDiagnostics.py 2025-12-11 14:28:21 +00:00
19f735e7e2 Update diagnostics/FullDiagnostics.py 2025-12-11 14:27:56 +00:00
c2a7775d82 Update diagnostics/BatteryDiagnostics.py 2025-12-11 14:27:45 +00:00
11 changed files with 430 additions and 75 deletions

View File

@@ -10,9 +10,10 @@ How to use this:
Included utilities: Included utilities:
- Diagnostics - a program that allows you to diagnose issues and test parts of your robot, such as battery, motor, and color sensor. Open each program in the ```diagnostics``` folder in Pybricks, connect your robot, switch to the ```FullDiagnostics.py``` file and press run. - Diagnostics - a program that allows you to diagnose issues and test parts of your robot, such as battery, motor, and color sensor. Open each program in the ```diagnostics``` folder in Pybricks, (you can select all of them at once) connect your robot, switch to the ```FullDiagnostics.py``` file and press run.
- Color Sensor Tests (UPCOMING) - a program that identifies what color the sensor is detecting. If you'd like, you can use our color ranges in your own programs. - Color Sensor Tests (UPCOMING) - a program that identifies what color the sensor is detecting. If you'd like, you can use our color ranges in your own programs.
Please set your window size to 90% on small screens for best results with the ASCII art.
This code is licensed under the Creative Commons Attribution 4.0 International License (CC BY 4.0). This code is licensed under the Creative Commons Attribution 4.0 International License (CC BY 4.0).
Without the confusing legal speak, this means that you are free to: Without the confusing legal speak, this means that you are free to:

View File

@@ -1,24 +1,18 @@
from pybricks.pupdevices import Motor, ColorSensor, UltrasonicSensor, ForceSensor from pybricks.tools import wait
from pybricks.parameters import Button, Color, Direction, Port, Side, Stop
from pybricks.tools import run_task, multitask
from pybricks.tools import wait, StopWatch
from pybricks.robotics import DriveBase
from pybricks.hubs import PrimeHub
import umath import umath
# Initialize hub and devices
hub = PrimeHub()
class BatteryDiagnostics: class BatteryDiagnostics:
def __init__(self): def __init__(self, hub):
self.voltage = 0 self.voltage = 0
self.current = 0 self.current = 0
self.hub = hub
def printVoltage(self): def printVoltage(self):
self.voltage = hub.battery.voltage() self.voltage = self.hub.battery.voltage()
if self.voltage > 7800: if self.voltage > 7800:
print(f"Battery voltage is sufficient: {self.voltage}") print(f"Battery voltage is sufficient: {self.voltage}")
elif self.voltage < 7800 : elif self.voltage < 7800 :
print(f"Charging needed: {self.voltage}") print(f"Charging needed: {self.voltage}")
def printCurrent(self): def printCurrent(self):
self.current = hub.battery.current() self.current = self.hub.battery.current()
print("Battery current:", self.current) print("Battery current:", self.current)
def printAll(self): def printAll(self):
timeelapsed = 0 timeelapsed = 0
@@ -39,17 +33,17 @@ class BatteryDiagnostics:
print("Voltage deviation:", self.stdev(voltageList)) print("Voltage deviation:", self.stdev(voltageList))
print("Current deviation:", self.stdev(currentList)) print("Current deviation:", self.stdev(currentList))
def stdev(self, vals): def stdev(self, vals):
data = vals DATA = vals
if len(data) < 2: if len(DATA) < 2:
return 0 return 0
# Calculate the mean # Calculate the mean
mean = sum(data) / len(data) MEAN = sum(DATA) / len(DATA)
# Calculate the variance (sum of squared differences from the mean, divided by n-1 for sample standard deviation) # Calculate the variance (sum of squared differences from the mean, divided by n-1 for sample standard deviation)
variance = sum([(x - mean) ** 2 for x in data]) / float(len(data) - 1) VARIANCE = sum([(x - MEAN) ** 2 for x in DATA]) / float(len(DATA) - 1)
# Calculate the standard deviation (square root of the variance) # Calculate the standard deviation (square root of the variance)
std_dev_manual = umath.sqrt(variance) STD_DEV_MANUAL = umath.sqrt(VARIANCE)
return (std_dev_manual) return (STD_DEV_MANUAL)

View File

@@ -0,0 +1,48 @@
from pybricks.parameters import Color, Port, Stop
from pybricks.tools import wait, StopWatch
class ColorSensorDiagnostics:
def __init__(self, hub, colorsensorclass):
self.colorsensor = None
self.PORT_MAP = {
"A": Port.A,
"B": Port.B,
"C": Port.C,
"D": Port.D,
"E": Port.E,
"F": Port.F,
}
self.colorsensorclass = colorsensorclass
def initializeColorSensor(self):
VALID_PORTS = {"A", "B", "C", "D", "E", "F"}
while True:
colorinput = input(
"This will test your color sensor.\n"
"Enter the port for the color sensor you would like to test (A, B, C, D, E, or F): "
).strip().upper()
if colorinput not in VALID_PORTS:
print("Invalid port. Please enter A-F.")
continue
try:
if self.colorsensor is None:
self.colorsensor = self.colorsensorclass(self.PORT_MAP[colorinput])
print(f"Color Sensor initialized on port {colorinput}.")
else:
print(f"Reusing existing color sensor on port {colorinput}.")
break
except OSError as e:
if e.errno == 16: # EBUSY
print(f"Port {colorinput} is already in use. Reusing existing color sensor.")
break
else:
print(f"Error initializing color sensor on port {colorinput}: {e}")
print("Make sure a color sensor is actually connected to this port.")
self.colorsensor = None
self.colorsensor.detectable_colors([Color.RED, Color.YELLOW, Color.GREEN, Color.BLUE, Color.WHITE, Color.NONE])
def printAll(self):
self.initializeColorSensor()
stopwatch = StopWatch()
while stopwatch.time() < 5000:
print("HSV output:", self.colorsensor.hsv())
print("Detected color:", self.colorsensor.color())

View File

@@ -0,0 +1,165 @@
from pybricks.parameters import Direction, Port, Side, Stop
from pybricks.robotics import DriveBase
from pybricks.tools import wait, StopWatch
from usys import stdin
from uselect import poll
class DriveBaseDiagnostics:
def __init__(self, hub, motorclass, dbclass):
self.hub = hub
self.motorclass = motorclass
self.dbclass = dbclass
self.drive_base = None
self.PORT_MAP = {
"A": Port.A,
"B": Port.B,
"C": Port.C,
"D": Port.D,
"E": Port.E,
"F": Port.F,
}
def initializeDriveBase(self):
print("DriveBase setup:")
print("1 = Load from savefile (paste JSON)")
print("2 = Use defaults")
print("3 = Enter values manually")
choice = input("Choose an option: ")
# Default values
WHEEL_DIAMETER = 68.8
AXLE_TRACK = 180
DRIVE_SETTINGS = (600, 2000, 300, 2000)
# Motor ports (None until set)
leftmotorport = Port.A
rightmotorport = Port.B
# -----------------------------
# OPTION 1: LOAD SAVEFILE
# -----------------------------
if choice == "1":
print("Paste JSON:")
raw = input("> ")
# --- wheel ---
if "\"wheel\"" in raw:
part = raw.split("\"wheel\"")[1]
part = part.split(":")[1]
part = part.split(",")[0]
WHEEL_DIAMETER = float(part)
# --- axle ---
if "\"axle\"" in raw:
part = raw.split("\"axle\"")[1]
part = part.split(":")[1]
part = part.split(",")[0]
AXLE_TRACK = float(part)
# --- settings ---
if "\"settings\"" in raw:
part = raw.split("\"settings\"")[1]
part = part.split("[")[1]
part = part.split("]")[0]
nums = part.split(",")
DRIVE_SETTINGS = (int(nums[0]), int(nums[1]), int(nums[2]), int(nums[3]))
# --- left motor port ---
if "\"left_port\"" in raw:
part = raw.split("\"left_port\"")[1]
part = part.split("\"")[1] # first quoted value
leftmotorport = part
# --- right motor port ---
if "\"right_port\"" in raw:
part = raw.split("\"right_port\"")[1]
part = part.split("\"")[1]
rightmotorport = part
print("Loaded config.")
# -----------------------------
# OPTION 3: MANUAL ENTRY
# -----------------------------
elif choice == "3":
WHEEL_DIAMETER = float(input("Wheel diameter: "))
AXLE_TRACK = float(input("Axle track: "))
print("Enter drive settings:")
s1 = int(input("Straight speed: "))
s2 = int(input("Straight accel: "))
s3 = int(input("Turn rate: "))
s4 = int(input("Turn accel: "))
DRIVE_SETTINGS = (s1, s2, s3, s4)
# Ask for motor ports HERE (manual only)
leftmotorport = input("Left motor port: ")
rightmotorport = input("Right motor port: ")
# -----------------------------
# OPTION 2: DEFAULTS
# -----------------------------
else:
pass
# -----------------------------
# CREATE MOTORS
# -----------------------------
left_motor = self.motorclass(leftmotorport, Direction.COUNTERCLOCKWISE)
right_motor = self.motorclass(rightmotorport, Direction.CLOCKWISE)
# -----------------------------
# CREATE DRIVEBASE
# -----------------------------
self.drive_base = self.dbclass(left_motor, right_motor, WHEEL_DIAMETER, AXLE_TRACK)
self.drive_base.settings(*DRIVE_SETTINGS)
self.drive_base.use_gyro(True)
print("DriveBase initialized.")
return DRIVE_SETTINGS
def printAll(self):
self.driveRobot()
def driveRobot(self):
drivesettings = self.initializeDriveBase()
print(drivesettings)
keyboard = poll()
keyboard.register(stdin)
last_key_time = StopWatch()
last_key_time.reset()
while True:
key = None
# Check for keypress immediately
if keyboard.poll(0):
key = stdin.read(1).upper()
last_key_time.reset()
# Process key
if key:
if key == "W":
self.drive_base.drive(drivesettings[0], 0)
elif key == "A":
self.drive_base.drive(drivesettings[0], -180)
elif key == "S":
self.drive_base.drive(-drivesettings[0], 0)
elif key == "D":
self.drive_base.drive(drivesettings[0], 180)
elif key == "X":
break
# Auto-stop if no key for 120 ms
if last_key_time.time() > 120:
self.drive_base.stop()
# Tiny manual delay to avoid 100% CPU
# (much faster than wait())
for _ in range(200):
pass

View File

@@ -3,13 +3,19 @@ from pybricks.pupdevices import Motor, ColorSensor, UltrasonicSensor, ForceSenso
from pybricks.parameters import Button, Color, Direction, Port, Side, Stop from pybricks.parameters import Button, Color, Direction, Port, Side, Stop
from pybricks.robotics import DriveBase from pybricks.robotics import DriveBase
from pybricks.tools import wait, StopWatch from pybricks.tools import wait, StopWatch
hub = PrimeHub() HUB = PrimeHub()
from BatteryDiagnostics import BatteryDiagnostics from BatteryDiagnostics import BatteryDiagnostics
from MotorDiagnostics import MotorDiagnostics from MotorDiagnostics import MotorDiagnostics
battery = BatteryDiagnostics() from ColorSensorDiagnostics import ColorSensorDiagnostics
motor = MotorDiagnostics() from DriveBaseDiagnostics import DriveBaseDiagnostics
clearConfirmation = input("Do you want to clear the console before proceeding? Y/N (default: yes): ") from HubDiagnostics import HubDiagnostics
if(clearConfirmation == "Y" or clearConfirmation == "y" or clearConfirmation == "yes" or clearConfirmation == ""): battery = BatteryDiagnostics(HUB)
motor = MotorDiagnostics(HUB, Motor)
colorsensor = ColorSensorDiagnostics(HUB, ColorSensor)
drivebase = DriveBaseDiagnostics(HUB, Motor, DriveBase)
hubdiagnostics = HubDiagnostics(HUB)
CLEARCONFIRM = input("Clear the console before proceeding? Y/N (default: yes): ")
if(CLEARCONFIRM == "Y" or CLEARCONFIRM == "y" or CLEARCONFIRM == "yes" or CLEARCONFIRM == ""):
print("Clearing console... \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n") print("Clearing console... \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n")
print(""" print("""
@@ -21,22 +27,25 @@ print("""
The free and open source diagnostics tool for the LEGO® Education SPIKE Prime robots, designed for FIRST Lego League. The free and open source diagnostics tool for LEGO® Education SPIKE Prime robots, designed for FIRST Lego League.
Developed by Team 65266, Lego Dynamics. Developed by Team 65266, Lego Dynamics.
""" """
) )
while True: while True:
print("\nWhat diagnostic do you want to perform?") print("\nWhich diagnostic do you want to perform?")
print("Enter 'b' for Battery diagnostics") print("Enter 'b' for battery diagnostics")
print("Enter 'm' for Motor diagnostics") print("Enter 'm' for motor diagnostics")
print("Enter 'q' to Quit") print("Enter 'cs' for color sensor diagnostics")
print("Enter 'db' for drive base diagnostics")
print("Enter 'h' for hub diagnostics")
print("Enter 'q' to quit")
choice = input("Your choice: ").strip().lower() choice = input("Your choice: ").strip().lower()
if choice == "b": if choice == "b":
print("-----------------------BATTERY DIAGNOSTICS-----------------------") print("-----------------------BATTERY DIAGNOSTICS-----------------------")
print("This test will check the battery voltage and current. It will measure the voltage and current over a period of 3 seconds and provide average values and deviation values. Your voltage should be above 7800 mV for optimal performance.") print("This test will check the battery voltage and current. It will measure these over a period of 3 seconds and provide average and deviation values. Your voltage should be above 7800 mV for optimal performance.")
input("Press Enter to begin the battery diagnostics.") input("Press Enter to begin the battery diagnostics.")
battery.printAll() battery.printAll()
print("Battery diagnostics completed.") print("Battery diagnostics completed.")
@@ -44,11 +53,21 @@ while True:
elif choice == "m": elif choice == "m":
print("------------------------MOTOR DIAGNOSTICS------------------------") print("------------------------MOTOR DIAGNOSTICS------------------------")
motor.fullTest() motor.fullTest()
print("Motor diagnostics completed.") print("[Motor Diagnostics] Motor diagnostics completed.")
elif choice == "q": elif choice == "q":
print("Diagnostics completed successfully. Exiting with code 0. Good luck in the robot game!") print("Diagnostics completed successfully. Exiting program.")
break break
elif choice == "cs":
print("---------------------COLOR SENSOR DIAGNOSTICS---------------------")
colorsensor.printAll()
print("[Color Sensor Diagnostics] Color sensor diagnostics completed.")
elif choice == "db":
print("----------------------DRIVE BASE DIAGNOSTICS----------------------")
drivebase.printAll()
print("[Drivebase Diagnostics] Drivebase diagnostics completed.")
elif choice == "h":
print("--------------------------HUB DIAGNOSTICS--------------------------")
hubdiagnostics.printAll(False)
else: else:
print("Invalid choice. Please enter 'b', 'm', or 'q'.") print("Invalid choice. Please enter 'b', 'm', or 'q'.")

View File

@@ -0,0 +1,41 @@
from pybricks.tools import wait, StopWatch
from pybricks import version
import OtherFunctions as debug
from MicroPythonDiagnostics import MicroPythonDiagnostics
from pybricks.parameters import Port
class HubDiagnostics:
def __init__(self, hub):
self.hub = hub
self.port_map = {
"A": Port.A,
"B": Port.B,
"C": Port.C,
"D": Port.D,
"E": Port.E,
"F": Port.F,
}
def testLightSources(self, verbose):
v = verbose
self.hub.display.off()
for x in range(5):
for y in range(5):
debug.log(f"[Hub Diagnostics - Light Sources] Turning on pixel at position {x}, {y}...", v)
self.hub.display.pixel(x, y, brightness=100)
wait(100)
debug.log(f"[Hub Diagnostics - Light Sources] Turning off pixel at position {x}, {y}...", v)
self.hub.display.pixel(x, y, brightness=0)
def printAll(self, verbose=True):
v = verbose
debug.log("[Hub Diagnostics] Starting hub diagnostics...", v)
while True:
choice = input("[Hub Diagnostics] Which hub diagnostic would you like to run?\n[Hub Diagnostics] Enter 'l' for light source test\n[Hub Diagnostics] Enter 'm' for MicroPython diagnostics\n[Hub Diagnostics] Enter 'q' to quit\n[Hub Diagnostics] Your choice: ").strip().lower()
if choice == "l":
debug.log("[Hub Diagnostics] Running light source test...", v)
self.testLightSources(v)
if choice == "m":
debug.log("[Hub Diagnostics] Running MicroPython diagnostics...", v)
MicroPythonDiagnostics.printAll()
if choice == "q":
print("[Hub Diagnostics] Hub diagnostics completed.")
return

View File

@@ -0,0 +1,11 @@
import usys
from pybricks import version
class MicroPythonDiagnostics:
def __init__(self, hub):
pass
def printAll():
print("[Hub Diagnostics - MicroPython] Hub version information:", version)
print("[Hub Diagnostics - MicroPython] MicroPython version:", usys.version)
print("[Hub Diagnostics - MicroPython] Pybricks version information:", usys.version_info)
print("[Hub Diagnostics - MicroPython] MicroPython information:", usys.implementation)

View File

@@ -1,13 +1,8 @@
from pybricks.hubs import PrimeHub from pybricks.parameters import Direction, Port, Stop
from pybricks.pupdevices import Motor, ColorSensor, UltrasonicSensor, ForceSensor
from pybricks.parameters import Button, Color, Direction, Port, Side, Stop
from pybricks.robotics import DriveBase
from pybricks.tools import wait, StopWatch from pybricks.tools import wait, StopWatch
import umath import umath
hub = PrimeHub()
class MotorDiagnostics: class MotorDiagnostics:
def __init__(self): def __init__(self, hub, motorclass):
self.testmotor = None self.testmotor = None
self.port_map = { self.port_map = {
"A": Port.A, "A": Port.A,
@@ -17,46 +12,42 @@ class MotorDiagnostics:
"E": Port.E, "E": Port.E,
"F": Port.F, "F": Port.F,
} }
self.motorclass = motorclass
def stdev(self, vals): def stdev(self, vals):
data = vals DATA = vals
if len(data) < 2: if len(DATA) < 2:
return 0 return 0
# Calculate the mean # Calculate the mean
mean = sum(data) / len(data) MEAN = sum(DATA) / len(DATA)
# Calculate the variance (sum of squared differences from the mean, divided by n-1 for sample standard deviation) # Calculate the variance (sum of squared differences from the mean, divided by n-1 for sample standard deviation)
variance = sum([(x - mean) ** 2 for x in data]) / float(len(data) - 1) VARIANCE = sum([(x - MEAN) ** 2 for x in DATA]) / float(len(DATA) - 1)
# Calculate the standard deviation (square root of the variance) # Calculate the standard deviation (square root of the variance)
STD_DEV_MANUAL = umath.sqrt(VARIANCE)
std_dev_manual = umath.sqrt(variance)
return (std_dev_manual) return (STD_DEV_MANUAL)
def health_score(self, desired, avg_speed, stdev_speed, avg_load): def health_score(self, desired, avg_speed, stdev_speed, avg_load):
# Speed accuracy: penalize % error # Speed accuracy: penalize % error
accuracy = max(0, 100 - abs(avg_speed - desired) / desired * 100) ACCURACY = max(0, 100 - abs(avg_speed - desired) / desired * 100)
# Stability: penalize deviation relative to desired # Stability: penalize deviation relative to desired
stability = max(0, 100 - (stdev_speed / desired) * 100) STABILITY = max(0, 100 - (stdev_speed / desired) * 100)
# Normalize load: map 1020 as baseline (0%), 200 as max (100%) # Normalize load: map 10 to 20 as baseline (around 0%), 200 as max (around 100%)
baseline = 15 # midpoint of idle range BASELINE = 10 # midpoint of idle range
max_observed = 200 # heavy load/stall MAX_OBSERVED = 200 # heavy load/stall
normalized_load = max(0, avg_load - baseline) NORMALIZED_LOAD = max(0, avg_load - BASELINE)
load_pct = min(100, (normalized_load / (max_observed - baseline)) * 100) LOAD_PCT = min(100, (NORMALIZED_LOAD / (MAX_OBSERVED - BASELINE)) * 100)
load_score = max(0, 100 - load_pct) LOAD_SCORE = max(0, 100 - LOAD_PCT)
# Final score: average of the three # Final score: average of the three
return (accuracy + stability + load_score) / 3 return (ACCURACY + STABILITY + LOAD_SCORE) / 3
# Final score: average of the three
return (accuracy + stability + load_score) / 3
def initializeMotor(self): def initializeMotor(self):
valid_ports = {"A", "B", "C", "D", "E", "F"} VALID_PORTS = {"A", "B", "C", "D", "E", "F"}
while True: while True:
motorinput = input( motorinput = input(
"This test will run your motor at 3 speeds: 180, 540, and 1000 degrees per second.\n" "This test will run your motor at 3 speeds: 180, 540, and 1000 degrees per second.\n"
@@ -64,11 +55,13 @@ class MotorDiagnostics:
"If you want to test the wheel's load, note that this will affect the load measurements.\n" "If you want to test the wheel's load, note that this will affect the load measurements.\n"
"Enter the port for the motor you would like to test (A, B, C, D, E, or F): " "Enter the port for the motor you would like to test (A, B, C, D, E, or F): "
).strip().upper() ).strip().upper()
if motorinput not in VALID_PORTS:
print("That is not a valid port. Please enter A-F.")
continue
try: try:
# Only create a new Motor if we don't already have one # Only create a new Motor if we don't already have one
if self.testmotor is None: if self.testmotor is None:
self.testmotor = Motor(self.port_map[motorinput]) self.testmotor = self.motorclass(self.port_map[motorinput])
print(f"Motor initialized on port {motorinput}.") print(f"Motor initialized on port {motorinput}.")
else: else:
print(f"Reusing existing motor on port {motorinput}.") print(f"Reusing existing motor on port {motorinput}.")
@@ -89,16 +82,16 @@ class MotorDiagnostics:
motorspeeds = [] motorspeeds = []
motorloads = [] motorloads = []
target_angle = speed * 3 TARGET_ANGLE = speed * 3
print("\n", speed, "DEGREES PER SECOND TEST") print("\n", speed, "DEGREES PER SECOND TEST")
self.testmotor.run_angle(speed, target_angle, Stop.HOLD, False) self.testmotor.run_angle(speed, TARGET_ANGLE, Stop.HOLD, False)
stopwatchmotor = StopWatch() stopwatchmotor = StopWatch()
while stopwatchmotor.time() < 3000: while stopwatchmotor.time() < 3000:
wait(20) wait(20)
motorspeeds.append(self.testmotor.speed()) motorspeeds.append(self.testmotor.speed())
motorloads.append(self.testmotor.load()) motorloads.append(self.testmotor.load())
max_speed, max_accel, max_torque = self.testmotor.control.limits() MAX_SPEED, MAX_ACCEL, MAX_TORQUE = self.testmotor.control.limits()
print("Desired motor speed: ", str(speed)) print("Desired motor speed: ", str(speed))
@@ -117,25 +110,25 @@ class MotorDiagnostics:
else: else:
print("No load samples collected.") print("No load samples collected.")
avgload = 0 avgload = 0
score = self.health_score(speed, avg, self.stdev(motorspeeds), avgload) SCORE = self.health_score(speed, avg, self.stdev(motorspeeds), avgload)
print("Health score for this test:", str(score) + "%") print("Health score for this test:", str(SCORE) + "%")
return score return SCORE
def fullTest(self): def fullTest(self):
self.initializeMotor() self.initializeMotor()
print("Load measurements are in mNm. Speed measurements are in degrees per second.") print("Load measurements are in mNm. Speed measurements are in degrees per second.")
max_speed, max_accel, max_torque = self.testmotor.control.limits() MAX_SPEED, MAX_ACCEL, MAX_TORQUE = self.testmotor.control.limits()
print("Maximum motor speed:", max_speed) print("Maximum motor speed:", MAX_SPEED)
test180 = self.testSpeed(180) test180 = self.testSpeed(180)
test540 = self.testSpeed(540) test540 = self.testSpeed(540)
test1000 = self.testSpeed(1000) test1000 = self.testSpeed(1000)
print("\n FINAL MOTOR STATISTICS") print("\n FINAL MOTOR STATISTICS")
final = (test180 + test540 + test1000) / 3 final = (test180 + test540 + test1000) / 3
print("Final motor health score:", str(final) + "%") print("Final motor health score:", str(final) + "%")
if final < 80: if final < 65:
print("Your motor is in need of attention. Make sure to clean it regularly and charge the Prime Hub.") print("Your motor is in need of attention. Make sure to clean it regularly and charge the Prime Hub.")
elif final < 90: elif final < 85:
print("Your motor is in OK condition. Make sure to clean it regularly and charge the Prime Hub.") print("Your motor is in OK condition. Make sure to clean it regularly and charge the Prime Hub.")
elif final < 97: elif final < 95:
print("Your motor is in great condition!") print("Your motor is in great condition!")
else: else:
print("Your motor is in AMAZING condition!!!") print("Your motor is in AMAZING condition!!!")

View File

@@ -0,0 +1,3 @@
def log(string, verbose):
if(verbose):
print("[LOG (verbose)]", string)

View File

@@ -0,0 +1,62 @@
from pybricks.pupdevices import ColorSensor
from pybricks.parameters import Color, Port
from pybricks.tools import run_task
from pybricks.tools import wait
from pybricks.hubs import PrimeHub
hub = PrimeHub()
color_sensor = ColorSensor(Port.F) # Change the port to your color sensor's port
# Function to classify color based on HSV
def detect_color(h, s, v, reflected):
if reflected > 4:
if h < 4 or h > 350: # red
return "Red"
elif 3 < h < 40 and s > 70: # orange
return "Orange"
elif 47 < h < 56: # yellow
return "Yellow"
elif 70 < h < 160: # green - your brick should approach from the top for accuracy
return "Green"
elif 195 < h < 198: # light blue
return "Light_Blue"
elif 210 < h < 225: # blue - your brick should approach from the top for accuracy
return "Blue"
elif 260 < h < 350: # purple
return "Purple"
else:
return "Unknown"
return "Unknown"
async def main():
while True:
h, s, v = await color_sensor.hsv()
reflected = await color_sensor.reflection()
color = detect_color(h, s, v, reflected)
if color == "Green":
print('Running Task 1')
# Run a function with await Function() here
elif color == "Red":
print('Running Task 2')
# Run a function with await Function() here
elif color == "Yellow":
print('Running Task 3')
# Run a function with await Function() here
elif color == "Blue":
print('Running Task 4')
# Run a function with await Function() here
elif color == "Orange":
print('Running Task 5')
# Run a function with await Function() here
elif color == "Purple":
print('Running Task 6')
# Run a function with await Function() here
elif color == "Light_Blue":
print("Running Task 7")
# Run a function with await Function() here
else:
print(f"Unknown color detected (Hue: {h}, Sat: {s}, Val: {v})")
#pass
await wait(10)
# Run the main function
run_task(main())

View File

@@ -0,0 +1,18 @@
from pybricks.pupdevices import Motor
from pybricks.parameters import Button, Direction, Port, Side, Stop
from pybricks.tools import run_task, multitask
from pybricks.tools import wait, StopWatch
from pybricks.robotics import DriveBase
from pybricks.iodevices import XboxController
from pybricks.hubs import PrimeHub
hub = PrimeHub()
testmotor = Motor(Port.C)
async def main():
while True:
if(Button.UP in buttons.pressed()):
testmotor.run(500)
else:
testmotor.stop()
await wait(10)
# Run the main function
run_task(main())