Initial push
This commit is contained in:
@@ -0,0 +1,177 @@
|
||||
#!/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)
|
||||
Reference in New Issue
Block a user