Last active
November 4, 2024 13:43
-
-
Save Xayer/967f1a100c568995ebf8911093338d6e to your computer and use it in GitHub Desktop.
Pybricks algorithm for consistent train speed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# good introduction video to "Pybricks": | |
# https://www.youtube.com/watch?v=Jmh4NLxJ_8c | |
from pybricks.pupdevices import DCMotor, ColorDistanceSensor | |
from pybricks.hubs import CityHub | |
from pybricks.tools import StopWatch | |
from pybricks.parameters import Port, Color | |
# Initialize the motor and the sensor. | |
motor = DCMotor(Port.B) | |
sensor = ColorDistanceSensor(Port.A) | |
# remote = Remote() | |
hub = CityHub() | |
# These are the sensor reflection values in this setup. | |
# Adapt them to match your ambient light conditions. | |
# Values at home on the floor | |
# LIGHT = 57 | |
# DARK = 16 | |
# Moduverse track at home | |
LIGHT = 26 | |
DARK = 17 | |
# Threshold values. We add a bit of hysteresis to make | |
# sure we skip extra changes on the edge of each track. | |
hysteresis = (LIGHT - DARK) / 4 | |
threshold_up = (LIGHT + DARK) / 2 + hysteresis | |
threshold_down = (LIGHT + DARK) / 2 - hysteresis | |
# Initial position state. | |
on_track = True | |
position = 0 | |
# Desired drive speed in mm per second. | |
SPEED = 60 | |
# It's two studs (16 mm) for each position increase. | |
MM_PER_COUNT = 8 | |
# Start a timer. | |
watch = StopWatch() | |
while True: | |
# Measure the reflection. | |
reflection = sensor.reflection() | |
# print(reflection) | |
# If the reflection exceeds the threshold, increment position. | |
if (reflection > threshold_up and on_track) or (reflection < threshold_down and not on_track): | |
on_track = not on_track | |
position += 1 | |
# Compute the target position based on the time. | |
target_count = watch.time() / 1000 * SPEED / MM_PER_COUNT | |
# The duty cycle is the position error times a constant gain. | |
duty = 2*(target_count - position) | |
# Apply the duty cycle. | |
print("New desired speed:") | |
print(duty) | |
motor.dc(duty) | |
# remote.light.on(Color.RED if duty > SPEED else Color.GREEN) - this slows down the train significantly | |
hub.light.on(Color.RED if duty > SPEED else Color.GREEN) | |
# FINDINGS: | |
# The train will move slower when not connected to Pybricks | |
# The train will try to calculate | |
# IDEAS: | |
# Could we make a "calibrate step"? | |
# so you could place the train on the tile, and then blank, track | |
# it could record the track's reflection values on a trial run over the track? |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment