Robotex-Rally/rally.py
2025-06-27 21:51:57 +03:00

121 lines
3.2 KiB
Python

import time
import math
import board
import adafruit_hcsr04
import pwmio
import digitalio
import rotaryio
from adafruit_motor import motor
# Mathematics
diameter = 0.047 # 47mm wheel diameter
circumference = diameter * math.pi
target_dist = 5
# Encoder constants
GEAR_RATIO = 50 # The gear ratio of the motor
COUNTS_PER_REV = 12 * GEAR_RATIO # The counts per revolution of the motor's output shaft
ENCODER_NAMES = ["A", "D"]
# Motor constants
FREQUENCY = 25000
DECAY_MODE = motor.SLOW_DECAY
UPDATE_RATE = 100 # Hz
SLEEP_TIME = 1 / UPDATE_RATE
BASE_THROTTLE = 0.85 # Base throttle for both motors
Kp_sync = 1.5 # Proportional gain for sync correction
Kd_sync = 0.04
prev_error = 0
# Create a digitalinout object for the user switch
user_sw = digitalio.DigitalInOut(board.USER_SW)
user_sw.direction = digitalio.Direction.INPUT
user_sw.pull = digitalio.Pull.UP
# Set the pwm and motor pins
pwm_a_p = pwmio.PWMOut(board.MOTOR_A_P, frequency=FREQUENCY)
pwm_a_n = pwmio.PWMOut(board.MOTOR_A_N, frequency=FREQUENCY)
pwm_d_p = pwmio.PWMOut(board.MOTOR_D_P, frequency=FREQUENCY)
pwm_d_n = pwmio.PWMOut(board.MOTOR_D_N, frequency=FREQUENCY)
mot_right = motor.DCMotor(pwm_a_p, pwm_a_n)
mot_left = motor.DCMotor(pwm_d_p, pwm_d_n)
mot_right.decay_mode = DECAY_MODE
mot_left.decay_mode = DECAY_MODE
# Create the encoder objects
enc_right = rotaryio.IncrementalEncoder(board.ENCODER_A_B, board.ENCODER_A_A, divisor=1)
enc_left = rotaryio.IncrementalEncoder(board.ENCODER_D_B, board.ENCODER_D_A, divisor=1)
enc_right.position = 0
enc_left.position = 0
lastrevleft = 0
lastrevright = 0
revleft = 0
revright = 0
# Set the sensor pins
sonar = adafruit_hcsr04.HCSR04(trigger_pin=board.TRIG, echo_pin=board.ECHO)
def to_revs(position):
return position / COUNTS_PER_REV
def vel(rev, last_rev):
return (rev - last_rev) / UPDATE_RATE
while sonar.distance < 20:
print("I am waiting...", sonar.distance)
if sonar.distance >= 20:
break
print(">>>>> Starting movement!!!")
while True:
# Find the motor revolutions
lastrevleft = revleft
lastrevright = revright
revleft = to_revs(enc_left.position)
revright = to_revs(enc_right.position)
vel_left = vel(revleft, lastrevleft)
vel_right = vel(revright, lastrevright)
# Encoder error due to friction.
error = vel_left - vel_right
derivative = (error - prev_error) / UPDATE_RATE
prev_error = error
correction = (Kp_sync * error) #+ (Kd_sync * derivative)
left_throttle = BASE_THROTTLE - correction
right_throttle = BASE_THROTTLE + correction
left_throttle = max(min(left_throttle, 1.0), -1.0)
right_throttle = max(min(right_throttle, 1.0), -1.0)
distleft = revleft * circumference
distright = revright * circumference
avg = (abs(distleft) + abs(distright)) / 2
print(f"Distance traveled: {avg:.3f} m")
if avg >= target_dist:
print("Target reached!!!")
mot_left.throttle = 0
mot_right.throttle = 0
break
mot_right.throttle = right_throttle
mot_left.throttle = - left_throttle
print(right_throttle, left_throttle)
time.sleep(0.05)
print("Finished!!!")