The aim of this project is to create a line following robot programmed in micropython. The robot will use an array of infra-red reflectance sensors to follow a black line on a white background.
Required Libraries:
TB6612FNG - For the adafruit TB6612FNG dual motor driver
TheoryIn order to detect the presence of a line, a row of 5 infra-red reflectance sensors needs to be placed at the front of the robot. These sensors consist of a matched IR LED and IR photodiode. The infra-red light emitted by the LED is reflected by the surface below it and is then measured by the photodiode. Darker coloured surfaces reflect less light than lighter coloured sensor. For this reason a black line is required on a white background (or vice-versa).
By sensing which of the 5 sensors are over a dark surface and which are over a light surface we can determine the position of the robot relative to the black line. If the left hand sensors are over black the robot needs to needs to turn left, and the same for the right hand side. If the robots centre sensor is the only one over a dark surface we know the robot is now correctly on the line and should travel forward.
ConstructionTrack
For the track we used the back of a wall mounted whiteboard, but any light coloured surface will do. For the black line we used black electrical tape. Electrical tape stretches easily making curved corners easy to make. Sharp corners should be avoided as this can confuse the sensor.
Robot
For the robot we use the E.R.N.I.E robot chassis & sensor bar, an Adafruit TB6612FNG dual motor driver (any other dual motor driver will suffice), a 6xAA battery pack and a Pycom LoPy development module (Any of the Pycom modules could be used for this project e.g the WiPy). Assembly instructions for the chassis can be found here.
CodeCalibration
The first thing we need to do before the robot is able to follow the line, is calibrate the IR sensors for the current environment. The reason for this calibration is two fold: Since the sensors detect light they must be calibrated be for the environment that they are in to ensure accurate detection; Secondly due to manufacturing differences no two sensors will read the same values. The function below will look for the maximum reading from the sensors for 5 seconds, it will then set the sensors threshold to 80% of that value. When this calibration routine is running, the sensor bar of the robot should be moved across the line side to side to ensure all sensors cross the line.
Class Robot(object):
def calibrate_sensor(self):
print("Calibrating")
pycom.rgbled(0xFF0000)
maxs = [0] * 5
# Look for maximum (black) value for 5s
for _ in range(500):
for i, pin in enumerate(self.sensors):
new_val = pin.value()
maxs[i] = max(maxs[i], new_val)
time.sleep_ms(10)
# Save new thresholds
self.sensor_threshold = [0.8 * th for th in maxs]
print("Finished calibrating")
pycom.rgbled(0x00FF00)
Reading sensors
Reading from the sensors is quite trivial, we just need to read from the ADC pin the sensor is connected too and then check if the value is below or above the sensors threshold
def read_sensors(self, raw=False):
out = []
for pin, threshold in zip(self.sensors, self.sensor_threshold):
val = pin.value()
if raw:
out.append(val)
elif val > threshold:
out.append(True)
else:
out.append(False)
return tuple(out)
Position
Once we can read the sensor bars state we can turn this into a position. Each sensor is given a weighting, the sensors on the left hand side have a negative weighting while the ones on the right hand side have a positive weighting. The further the sensor is from the middle of the bar the larger its weighting. By summing the weightings of the sensors which are detecting black, we can determine the position of the robot like so:
def get_position(self):
vals = self.read_sensors()
weightings = [-4, -2, 0, 2, 4]
total = 0
num_on_line = 0
for v, w in zip(vals, weightings):
if v:
total += w
num_on_line += 1
if num_on_line == 0:
return None
return total
The above function will output a value between -6 and 6 depending on the robots position relative to the line with 0 being directly on the line.
Note: We have a special case above where if none of the sensors detects black the function returns None. This will later be used to stop the robot if it looses the line to prevent it driving away.
Line following
All that is left to do now is to turn the robots motors accordingly to the detected position
r = Robot()
while True:
pos = r.get_position()
if pos is None:
r.forward(0)
elif pos < 0:
r.turn_right(1)
elif pos > 0:
r.turn_left(1)
else:
r.forward(0.3)
Comments
Please log in or sign up to comment.