Another great facility built into the BitBot is that it comes with two light sensors built into the underside so that we can sense changes in light reflection coming from the floor. The sensors report a binary value depending on whether they are “seeing” a reflection (white) or no reflection (black). They are arranged on separate sides of the vehicle chassis so that we can build a track using printable squares and use the sensors to keep us on the straight and narrow.
The two sensors are wired to two different digital input pins on the microbit and we can query each individually. If we can see equal reflections from both sensors we assume we are travelling in a roughly straight line (or at least not hit an edge).
When we see a difference in sensors we know we have hit an edge and need to correct by turning in the opposite direction.
class LineSensor: def __init__(self, sense_pin): self.pin = sense_pin def read(self): return self.pin.read_digital() class LineSensors: def __init__(self, left_pin, right_pin): self.left_sensor = LineSensor(left_pin) self.right_sensor = LineSensor(right_pin) # return value depending on orientation: # -1 for left # 0 for straight # +1 for right def read_position(self): too_far_left = -1 straddling_line = 0 too_far_right = 1 left = self.left_sensor.read() right = self.right_sensor.read() no_line = 0 line_detected = 1 if left == no_line and right == line_detected: return too_far_left elif left == line_detected and right == no_line: return too_far_right return straddling_line
Building the line sensors into the BitBot class we can switch it to autonomous mode and watch while it “feels” its way around any sort of track we can devise.
class BitBot: def __init__(self, sense_pin): # ...other stuff... self.line_sensors = LineSensors(pin11, pin5) def autonomous_mode(self): motor_speed_fast = 20 motor_speed_slow = 10 while True: direction = self.line_sensors.read_position() if direction == 0: # straddling_line self.forward(motor_speed_fast) elif direction < 0: # too far left self.circle_right(motor_speed_slow) sleep(250) self.stop() elif direction > 0: # too far right self.circle_left(motor_speed_slow) sleep(250) self.stop() sleep(100)
Here is the finished vehicle running around a test track at one of our work open days.
Occasionally the vehicle would leave the track (I think the reflectivity of the sellotape holding the tiles together was to blame) and meander away, reading the colours of the floor tiles and the varying surfaces under its wheels until it was eventually rescued.