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.

Line Sensor

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).

straddling the line

When we see a difference in sensors we know we have hit an edge and need to correct by turning in the opposite direction.

too far left

too far right



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

BitBot

Building the line sensors into the [BitBot class]({ FIX % link _posts/2019-05-16-microbit-motoring.md %}) 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)

Demo

Here is the finished vehicle running around a test track at one of our work open days.

starting off

running round the track

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.