Compare commits
8 Commits
dev
...
60384d4367
| Author | SHA1 | Date | |
|---|---|---|---|
| 60384d4367 | |||
| a91e79a02a | |||
| ffd89e5698 | |||
| 17db936432 | |||
| d3a740e705 | |||
| 960fd598c9 | |||
| f3460290e5 | |||
| 345da15b22 |
@@ -10,10 +10,9 @@ 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, (you can select all of them at once) 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, 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:
|
||||||
|
|||||||
@@ -1,18 +1,24 @@
|
|||||||
from pybricks.tools import wait
|
from pybricks.pupdevices import Motor, ColorSensor, UltrasonicSensor, ForceSensor
|
||||||
|
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, hub):
|
def __init__(self):
|
||||||
self.voltage = 0
|
self.voltage = 0
|
||||||
self.current = 0
|
self.current = 0
|
||||||
self.hub = hub
|
|
||||||
def printVoltage(self):
|
def printVoltage(self):
|
||||||
self.voltage = self.hub.battery.voltage()
|
self.voltage = 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 = self.hub.battery.current()
|
self.current = hub.battery.current()
|
||||||
print("Battery current:", self.current)
|
print("Battery current:", self.current)
|
||||||
def printAll(self):
|
def printAll(self):
|
||||||
timeelapsed = 0
|
timeelapsed = 0
|
||||||
@@ -33,17 +39,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)
|
||||||
@@ -3,19 +3,13 @@ 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 battery_diagnostics import BatteryDiagnostics
|
from BatteryDiagnostics import BatteryDiagnostics
|
||||||
from motor_diagnostics import MotorDiagnostics
|
from MotorDiagnostics import MotorDiagnostics
|
||||||
from color_sensor_diagnostics import ColorSensorDiagnostics
|
battery = BatteryDiagnostics()
|
||||||
from drive_base_diagnostics import DriveBaseDiagnostics
|
motor = MotorDiagnostics()
|
||||||
from hub_diagnostics import HubDiagnostics
|
clearConfirmation = input("Do you want to clear the console before proceeding? Y/N (default: yes): ")
|
||||||
battery = BatteryDiagnostics(HUB)
|
if(clearConfirmation == "Y" or clearConfirmation == "y" or clearConfirmation == "yes" or clearConfirmation == ""):
|
||||||
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("""
|
||||||
███████████ █████ █████ ██████ █████ █████████ ██████ ██████ █████ █████████ █████████
|
███████████ █████ █████ ██████ █████ █████████ ██████ ██████ █████ █████████ █████████
|
||||||
@@ -27,25 +21,22 @@ print("""
|
|||||||
█████ █████ █████ ▒▒█████ █████ █████ █████ █████ █████ ▒▒█████████ ▒▒█████████
|
█████ █████ █████ ▒▒█████ █████ █████ █████ █████ █████ ▒▒█████████ ▒▒█████████
|
||||||
▒▒▒▒▒ ▒▒▒▒▒ ▒▒▒▒▒ ▒▒▒▒▒ ▒▒▒▒▒ ▒▒▒▒▒ ▒▒▒▒▒ ▒▒▒▒▒ ▒▒▒▒▒ ▒▒▒▒▒▒▒▒▒ ▒▒▒▒▒▒▒▒▒
|
▒▒▒▒▒ ▒▒▒▒▒ ▒▒▒▒▒ ▒▒▒▒▒ ▒▒▒▒▒ ▒▒▒▒▒ ▒▒▒▒▒ ▒▒▒▒▒ ▒▒▒▒▒ ▒▒▒▒▒▒▒▒▒ ▒▒▒▒▒▒▒▒▒
|
||||||
|
|
||||||
The free and open source diagnostics tool for LEGO® Education SPIKE™ Prime robots, designed for FIRST Lego League.
|
The free and open source diagnostics tool for the 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("\nWhich diagnostic do you want to perform?")
|
print("\nWhat 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 'cs' for color sensor diagnostics")
|
print("Enter 'q' to Quit")
|
||||||
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 these over a period of 3 seconds and provide average 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 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.")
|
||||||
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.")
|
||||||
@@ -53,21 +44,11 @@ while True:
|
|||||||
elif choice == "m":
|
elif choice == "m":
|
||||||
print("------------------------MOTOR DIAGNOSTICS------------------------")
|
print("------------------------MOTOR DIAGNOSTICS------------------------")
|
||||||
motor.fullTest()
|
motor.fullTest()
|
||||||
print("[Motor Diagnostics] Motor diagnostics completed.")
|
print("Motor diagnostics completed.")
|
||||||
|
|
||||||
elif choice == "q":
|
elif choice == "q":
|
||||||
print("Diagnostics completed successfully. Exiting program.")
|
print("Diagnostics completed successfully. Exiting with code 0. Good luck in the robot game!")
|
||||||
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'.")
|
||||||
@@ -1,8 +1,13 @@
|
|||||||
from pybricks.parameters import Direction, Port, Stop
|
from pybricks.hubs import PrimeHub
|
||||||
|
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, hub, motorclass):
|
def __init__(self):
|
||||||
self.testmotor = None
|
self.testmotor = None
|
||||||
self.port_map = {
|
self.port_map = {
|
||||||
"A": Port.A,
|
"A": Port.A,
|
||||||
@@ -12,42 +17,46 @@ 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 10 to 20 as baseline (around 0%), 200 as max (around 100%)
|
# Normalize load: map 10 to 20 as baseline (around 0%), 200 as max (around 100%)
|
||||||
BASELINE = 10 # midpoint of idle range
|
baseline = 15 # 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"
|
||||||
@@ -55,13 +64,11 @@ 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 = self.motorclass(self.port_map[motorinput])
|
self.testmotor = Motor(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}.")
|
||||||
@@ -82,16 +89,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))
|
||||||
@@ -110,25 +117,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 < 65:
|
if final < 80:
|
||||||
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 < 85:
|
elif final < 90:
|
||||||
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 < 95:
|
elif final < 97:
|
||||||
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!!!")
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
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())
|
|
||||||
@@ -1,165 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
from pybricks.tools import wait, StopWatch
|
|
||||||
from pybricks import version
|
|
||||||
import other_functions as debug
|
|
||||||
from micropython_diagnostics 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
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
import usys
|
|
||||||
import micropython
|
|
||||||
from pybricks import version
|
|
||||||
class MicroPythonDiagnostics:
|
|
||||||
def __init__(self, hub):
|
|
||||||
pass
|
|
||||||
def printVersionDiagnostics():
|
|
||||||
print("[Hub Diagnostics - MicroPython - Version] Hub version information:", version)
|
|
||||||
print("[Hub Diagnostics - MicroPython - Version] MicroPython version:", usys.version)
|
|
||||||
print("[Hub Diagnostics - MicroPython - Version] Pybricks version information:", usys.version_info)
|
|
||||||
print("[Hub Diagnostics - MicroPython - Version] MicroPython information:", usys.implementation)
|
|
||||||
def performMemoryDiagnostics():
|
|
||||||
print("[Hub Diagnostics - MicroPython - Memory] Memory information (retrieved from the MicroPython environment):")
|
|
||||||
micropython.mem_info(1)
|
|
||||||
print("[Hub Diagnostics - MicroPython - Memory] Testing heap lock and unlock.")
|
|
||||||
print("[Hub Diagnostics - MicroPython - Memory] Allocating memory while heap is unlocked:")
|
|
||||||
try:
|
|
||||||
x = 5000
|
|
||||||
print("[Hub Diagnostics - MicroPython - Memory] [SUCCESS] There was no MemoryError raised. The value of the new variable x is", x)
|
|
||||||
except MemoryError:
|
|
||||||
print("[Hub Diagnostics - MicroPython - Memory] [FAIL] Allocation failed. Your memory may be faulty.")
|
|
||||||
print("[Hub Diagnostics - MicroPython - Memory] Locking the heap:")
|
|
||||||
micropython.heap_lock()
|
|
||||||
print("[Hub Diagnostics - MicroPython - Memory] Heap was locked. Attempting to allocate memory (this should fail):")
|
|
||||||
try:
|
|
||||||
y = 10000
|
|
||||||
print("[Hub Diagnostics - MicroPython - Memory] [FAIL] There was no MemoryError raised. Heap lock failed.")
|
|
||||||
except MemoryError:
|
|
||||||
print("[Hub Diagnostics - MicroPython - Memory] [SUCCESS] Allocation failed. Test successful. The heap was successfully locked.")
|
|
||||||
# Attempt to add gc to this for memory diagnostics, in addition test machine.soft_reset() and add that first to reset the heap.
|
|
||||||
print("[Hub Diagnostics - MicroPython - Memory] Unlocking the heap:")
|
|
||||||
micropython.heap_unlock()
|
|
||||||
print("[Hub Diagnostics - MicroPython - Memory] Heap was unlocked. Attempting to allocate memory (this should succeed):")
|
|
||||||
try:
|
|
||||||
z = 17000
|
|
||||||
print("[Hub Diagnostics - MicroPython - Memory] [SUCCESS] There was no MemoryError raised. The value of the new variable y is", x)
|
|
||||||
except MemoryError:
|
|
||||||
print("[Hub Diagnostics - MicroPython - Memory] [FAIL] Allocation failed. The heap failed to unlock.")
|
|
||||||
def printAll():
|
|
||||||
printVersionDiagnostics()
|
|
||||||
performMemoryDiagnostics()
|
|
||||||
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
def log(string, verbose):
|
|
||||||
if(verbose):
|
|
||||||
print("[LOG (verbose)]", string)
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
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())
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
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())
|
|
||||||
Reference in New Issue
Block a user