Improving the line following
Improving the line following
The previous line-following program is OK, but the robot can move from side to side quite a lot as it follows the line. To make the movement more elegant, you can slow down the speed of the robot, making the turns smaller and more gradual.
However, the when_line
and when_no_line
events don't allow you to modify the robot's default speed. To have more control over the robot, you can adapt your program so that it considers the states of the line sensors and uses these to choose the actions that are required of the motors.
Setting up the program
1. Copy the code from the last step into a new Python file.
2. Remove all of the code after you have initialised the variables left_sensor
and right_sensor
.
3. After those variables have been defined, initialise the variables for controlling the speed of the motors and the timer:
speed = 0.75
duration = 10
end_time = time() + duration
running = True
The value for each motor will be modified by the speed
multiplier to slow down the robot a little. The value for speed
usually needs to be at least 0.6, otherwise the motors do not have enough momentum to turn on a solid surface; the maximum value is 1.
The other variables are used to create a timer so that the robot doesn't run forever, as with the UDS program last week. Remember that duration
is the number of seconds your program will run for, and you can modify this yourself.
Planning a better program
To have more control over the robot's movement and speed, your program needs to choose how to instruct the motors based on the values received from the line sensors.
Remember that when a line sensor is above a line, it outputs a 1
. When it’s off a line, it outputs a 0
. You can’t simply pass these values straight to the motors, because the motors accept a range of values from -1
to 1
; positive values tell the motor to run forwards and negative values tell it to run in reverse.
Taking this behaviour into account, I am going to define three rules to determine what outputs are sent to the motors.
Three rules to rule them all
Rule 1
If both line sensors output 0
, both motors should receive a positive value to drive forwards.
Rule 2
If the left sensor outputs 1
, the robot has drifted to the right and needs to turn left. In this case, the left motor should run backwards (a negative signal is needed), while the right motor should run forwards.
Rule 3
If the right sensor outputs 1
, the robot has drifted to the left and needs to turn right. Therefore, the right motor should run backwards (a negative signal is needed), while the left motor should run forwards.
Why do you think there is not a rule for both the sensors outputting a 1
simultaneously?
Programming the rules
To start applying these rules, the code needs to read the outputs of the line sensors repeatedly, in a loop.
4. Add a while
loop to the program, after where you initialised the speed and timer variables.
while running:
left_detect = left_sensor.value
right_detect = right_sensor.value
print (left_detect, right_detect)
5. If you run the program now, you should see the binary output from the sensors change when you move the sensors over and off the line, in accordance with the rules stated above.
6. Inside the while
loop, use conditional statements to specify the direction of each motor, depending on the line sensor readings:
while running:
left_detect = left_sensor.value
right_detect = right_sensor.value
# Rule 1
if left_detect == 0 and right_detect == 0:
left_mot = 1
right_mot = 1
# Rule 2
elif left_detect == 1:
left_mot = -1
right_mot = 1
# Rule 3
elif right_detect == 1:
left_mot = 1
right_mot = -1
print (left_mot, right_mot)
7. Run your code and test that the program outputs the correct motor values when you move the robot over and off the line.
8. Inside the loop, remove the print
statement and replace it with:
robin.left_motor.value = left_mot * speed
robin.right_motor.value = right_mot * speed
The value for each motor will be modified by the speed
multiplier, to slow the robot down a little.
Make sure you remove any print
statements within the loop, otherwise these will affect the response time of the program and the robot may overshoot the line.
9. To stop the while
loop from running forever, and to close all the component's connections cleanly, add this code inside the loop, at the end:
if time() >= end_time:
running = False
robin.stop()
robin.close()
left_sensor.close()
right_sensor.close()
Test your program
Now run your code and test your robot over a track.
Try different values for speed
(between 0 and 1) and check how your robot runs.
How does this affect your robot's ability to follow the line?
Share your findings in the comments section.