178 lines
4.9 KiB
Python
178 lines
4.9 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Line following robot for Raspberry Pi 4 using AlphaBot2 and TRSensor
|
|
Ohne LED-Visualisierung
|
|
"""
|
|
import time
|
|
import RPi.GPIO as GPIO
|
|
from AlphaBot2 import AlphaBot2
|
|
from TRSensors import TRSensor
|
|
|
|
MAX_SPEED = 25
|
|
CORRECTION_STRENGTH = 8
|
|
EXTRA_CURVE_CORRECTION = 2
|
|
LINE_DETECTED_THRESHOLD = 650
|
|
|
|
# Liste für gleitenden Durchschnitt
|
|
last_outer = []
|
|
|
|
def setup_gpio():
|
|
GPIO.setmode(GPIO.BCM)
|
|
GPIO.setwarnings(False)
|
|
|
|
def calibrate_sensors(tr, robot):
|
|
print("Auto-calibrating sensors...")
|
|
|
|
for i in range(5):
|
|
tr.calibratedMin[i] = 1023
|
|
tr.calibratedMax[i] = 0
|
|
|
|
for _ in range(3):
|
|
robot.setPWMA(20)
|
|
robot.setPWMB(15)
|
|
robot.forward()
|
|
for _ in range(30):
|
|
raw = tr.AnalogRead()
|
|
for i in range(5):
|
|
tr.calibratedMin[i] = min(tr.calibratedMin[i], raw[i])
|
|
tr.calibratedMax[i] = max(tr.calibratedMax[i], raw[i])
|
|
time.sleep(0.02)
|
|
|
|
robot.backward()
|
|
for _ in range(30):
|
|
raw = tr.AnalogRead()
|
|
for i in range(5):
|
|
tr.calibratedMin[i] = min(tr.calibratedMin[i], raw[i])
|
|
tr.calibratedMax[i] = max(tr.calibratedMax[i], raw[i])
|
|
time.sleep(0.02)
|
|
|
|
robot.stop()
|
|
print("Calibration complete.")
|
|
print(" Min:", tr.calibratedMin)
|
|
print(" Max:", tr.calibratedMax)
|
|
|
|
def detect_line_type(tr):
|
|
sensor_values = tr.readCalibrated()
|
|
center_avg = sum(sensor_values[1:4]) / 3
|
|
outer_avg = (sensor_values[0] + sensor_values[4]) / 2
|
|
white_line = outer_avg < center_avg
|
|
print("Detected line type:", "WHITE on BLACK" if white_line else "BLACK on WHITE")
|
|
return white_line
|
|
|
|
def compute_correction(sensors):
|
|
left = sensors[1]
|
|
right = sensors[3]
|
|
correction = 0
|
|
|
|
if abs(left - right) < 50:
|
|
correction = 0
|
|
elif left < LINE_DETECTED_THRESHOLD and right > LINE_DETECTED_THRESHOLD:
|
|
correction = -CORRECTION_STRENGTH
|
|
elif right < LINE_DETECTED_THRESHOLD and left > LINE_DETECTED_THRESHOLD:
|
|
correction = CORRECTION_STRENGTH
|
|
|
|
if sensors[0] < LINE_DETECTED_THRESHOLD:
|
|
correction -= EXTRA_CURVE_CORRECTION
|
|
elif sensors[4] < LINE_DETECTED_THRESHOLD:
|
|
correction += EXTRA_CURVE_CORRECTION
|
|
|
|
return correction
|
|
|
|
def perform_turn_if_needed(sensors, robot, position):
|
|
global last_outer
|
|
l = sensors[0]
|
|
r = sensors[4]
|
|
last_outer.append((l, r))
|
|
if len(last_outer) > 5:
|
|
last_outer.pop(0)
|
|
|
|
avg_l = sum(x for x, _ in last_outer) / len(last_outer)
|
|
avg_r = sum(y for _, y in last_outer) / len(last_outer)
|
|
delta = avg_r - avg_l
|
|
|
|
print(f"Turn-Check: AvgL={avg_l:.0f}, AvgR={avg_r:.0f}, Δ={delta:.0f}, pos={position:.1f}")
|
|
|
|
if not (1500 <= position <= 2500):
|
|
return False
|
|
if avg_l > 800 and avg_r > 800:
|
|
return False
|
|
|
|
if avg_r > 800 and avg_l < 500 and delta > 400:
|
|
print("→ 90° right-curve detected")
|
|
robot.stop()
|
|
time.sleep(0.1)
|
|
robot.right()
|
|
time.sleep(0.3)
|
|
robot.forward()
|
|
time.sleep(0.35)
|
|
return True
|
|
elif avg_l > 800 and avg_r < 500 and delta < -600 and sensors[2] < LINE_DETECTED_THRESHOLD:
|
|
print("← 90° left-curve detected")
|
|
robot.stop()
|
|
time.sleep(0.1)
|
|
robot.left()
|
|
time.sleep(0.3)
|
|
robot.forward()
|
|
time.sleep(0.35)
|
|
return True
|
|
|
|
return False
|
|
|
|
def line_follow_loop(tr, robot, white_line):
|
|
robot.forward()
|
|
|
|
while True:
|
|
position, sensors = tr.readLine(white_line=white_line)
|
|
|
|
print(f"Sensors: {sensors}, pos={position:.1f}")
|
|
|
|
if perform_turn_if_needed(sensors, robot, position):
|
|
robot.forward()
|
|
time.sleep(0.35)
|
|
robot.stop()
|
|
break
|
|
|
|
if all(s > LINE_DETECTED_THRESHOLD for s in sensors):
|
|
time.sleep(0.05)
|
|
robot.backward()
|
|
time.sleep(0.35)
|
|
robot.stop()
|
|
continue
|
|
|
|
correction = compute_correction(sensors)
|
|
left_speed = min(MAX_SPEED, max(0, MAX_SPEED + correction))
|
|
right_speed = min(MAX_SPEED, max(0, MAX_SPEED - correction))
|
|
|
|
robot.setPWMA(int(left_speed))
|
|
robot.setPWMB(int(right_speed))
|
|
|
|
time.sleep(0.02)
|
|
|
|
def line_follow(tr=None, robot=None):
|
|
if tr is None or robot is None:
|
|
setup_gpio()
|
|
robot = AlphaBot2()
|
|
tr = TRSensor()
|
|
robot.stop()
|
|
calibrate_sensors(tr, robot)
|
|
|
|
white_line = detect_line_type(tr)
|
|
|
|
print("Starting line follow...")
|
|
try:
|
|
line_follow_loop(tr, robot, white_line)
|
|
except KeyboardInterrupt:
|
|
print("Stopping and cleaning up...")
|
|
robot.stop()
|
|
GPIO.cleanup()
|
|
|
|
if __name__ == "__main__":
|
|
setup_gpio()
|
|
robot = AlphaBot2()
|
|
tr = TRSensor()
|
|
robot.stop()
|
|
|
|
calibrate_sensors(tr, robot)
|
|
input("Press Enter to continue...")
|
|
line_follow(tr, robot)
|