4. Sensors Tutorial

The GiggleBot comes with a couple of onboard sensors:

  1. Two light sensors, near the front eyes LEDs.
  2. Two line sensors, on the underside of the line follower.

4.1. Light Sensors

The GiggleBot comes with two light sensors right in front of the LED on each eye. They are very small and easy to miss. However, they are more versatile than the Micro:Bit’s light sensor as they can be read together to detect which side is receiving more light.

https://i.imgur.com/WsLwsDG.jpg

The main method to query the light sensors is read_sensor(). The same method is used for both light sensors and line sensors.

Here’s how to read both light sensors in one call:

right, left = read_sensor(LIGHT_SENSOR, BOTH)

And here’s how to read just one side at a time:

right = read_sensor(LIGHT_SENSOR, RIGHT)

4.1.1. Chase the Light

This tutorial will turn the GiggleBot into a cat, following a spotlight on the floor. Many cats do that when you shine a flashlight in front of them, they will try to hunt the light spot. When running this code, you will be able to guide your GiggleBot by using a flashlight.

This is how to use this project:

  1. Start GiggleBot and wait for sleepy face to appear on the Micro:Bit.
  2. Press button A to start the Chase the Light game (heart will replace the sleepy face).
  3. Chase the light as long as you want.
  4. Press button B to stop the GiggleBot and display sleepy face again.

First, a bit of explanation on the algorithm being used here.

On starting the GiggleBot, the Micro:Bit will:

  1. Assign a value to the diff variable (here it is using 10).
  2. Display a sleepy face image.
  3. Resets whatever readings from the buttons it might have had.
  4. Start a forever loop.

This forever loop only waits for one thing: for the user to press button A, and that’s when the light chasing begins.

As soon as button A is pressed, the Micro:Bit will display a heart as it’s quite happy to be active! And then it starts a second forever loop! This second forever loop is the actual Light Chasing game. It will end when button B is pressed by the user.

How to Chase a Light:

  1. Take reading from both light sensors.
  2. Print the readings every 50 ms.
  3. Compare the readings, using diff to allow for small variations. You will most likely get absolutely identical readings, even if the light is mostly equal. Using a differential value helps stabilize the behavior. You can adapt to your own lighting conditions by changing this value.
  4. If the right sensor reads more than the left sensor plus the diff value, then we know it’s brighter to the right. Turn right.
  5. If the left sensor reads more than the right sensor plus the diff value, then it’s brighter to the left. Turn left.
  6. If there isn’t that much of a difference between the two sensors, go straight.
  7. If button B gets pressed at any time, stop the robot, change sleepy face, and get out of this internal loop. The code will fall back to the first loop, ready for another game.
from microbit import *
from gigglebot import *

# value for the differential between the two sensors.
# you can change this value to make it more or less sensitive.
diff = 10
# display sleepy face
display.show(Image.ASLEEP)
# the following two lines resets the 'was_pressed' info
# and discards any previous presses
button_a.was_pressed()
button_b.was_pressed()
# and also make sure the robot is stopped
stop()

# variable to control how fast
# the sensors get printed
counter = running_time()

# start first loop, waiting for user input
while True:
    # test for user input
    if button_a.was_pressed():
        # game got started! Display much love
        display.show(Image.HEART)

        # start game loop
        while True:
            # read both sensors
            right, left = read_sensor(LIGHT_SENSOR, BOTH)
            # and print these values every 50 ms
            if running_time() - 50 > counter:
                counter = running_time()
                print((left, right))

            # test if it's brighter to the right
            if right > left+diff:
                turn(RIGHT)

            # test if it's brighter to the left
            elif left > right+diff:
                turn(LEFT)

            # both sides being equal, go straight
            else:
                drive(FORWARD)

            # oh no, the game got interrupted
            if button_b.is_pressed():
                stop()
                display.show(Image.ASLEEP)

                # this line here gets us out of the game loop
                break
https://i.imgur.com/X4MdLOm.gif

What else can be done with the light sensors?

You could modify this code to turn the GiggleBot into a night insect? Those would avoid light instead of chasing it.

You could detect when it gets dark or bright. Imagine the GiggleBot inside your closet. When someone opens the door, the sudden light can be detected. The GiggleBot can let you know someone went through your things while you were away.

4.2. Line Sensors

In front of GiggleBot, attached to the body, there is a line follower sensor. It contains two line sensors. You can spot them from the top of the line follower by two white dots. And from the bottom, they are identified as R and L (for right and left)

_images/GigglebotLineFollowingSensors.JPG

photo courtesy of Les Pounder

The easiest way of reading the sensors is as follow:

from gigglebot import *
right, left = read_sensor(LINE_SENSOR, BOTH)

The lower the number, the darker it is reading. Values can go from 0 to 1023 and depend a lot on your environment. If you want to write a line follower robot, it is best to take a few readings first, to get a good idea of what numbers will represent a black line, and what numbers represent a white line.

4.2.1. Calibrating the Line Follower

Calibrating the line follower means figuring out which numbers get returned when it’s over a black line, so that you can later code an actual line follower robot.

The best approach for this is to get readings in various parts of your line, from both sensors, for both the black line and the background color.

The following code will display the values onto the microbit leds when you press button A, allowing you to manually position your robot around your circuit and take readings.

from microbit import *
from gigglebot import *

# reset all previous readings of button_a
# strictly speaking this is not necessary, it is just a safety thing
button_a.was_pressed()
while True:
    if button_a.is_pressed():
        right, left = read_sensor(LINE_SENSOR, BOTH)
        display.scroll(left)
        display.scroll(right)

4.2.2. Follow the Line

Once you have gotten readings from the line sensors, you are ready to code a line follower robot.

Here we are coding for a line that is thick enough that both sensors can potentially be over the line. The robot will stop if it loses track of the line, in other words, if both sensors detect they’re over the background color.

The logic will be as follow:

  1. If both sensors detect a black line, forge straight ahead.
  2. If neither sensor detects a black line, give up and stop.
  3. If the right sensor detects a black line but not the left sensor, then steer to the right.
  4. If the left sensor detects a black line but not the right sensor, then steer to the left.

We are also using the LEDs on the LED smile to indicate what is going on while we follow the line.

from microbit import *
from gigglebot import *

# reset all previous readings of button_a, and button_b
# strictly speaking this is not necessary, it is just a safety thing
button_a.was_pressed()
button_b.was_pressed()
display.show(Image.YES)
strip=init()
# speed needs to be set according to your line and battery level.
# do not go too fast though.
set_speed(60, 60)
# threshold is a little over the highest number you got that indicates a
# black line.
threshold = 90
while True:
    # if both buttons are pressed, run calibration code
    if button_a.is_pressed() and button_b.is_pressed():
        right, left = read_sensor(LINE_SENSOR, BOTH)
        display.scroll(left)
        display.scroll(right)
    # if button A is pressed run line following code until button B gets pressed
    # or until we're over white/background
    if button_a.is_pressed():
        while not button_b.is_pressed():
            right, left = read_sensor(LINE_SENSOR, BOTH)
            if left < threshold and right < threshold:
                # both sensors detect the line
                strip[2]=(0,255,0)
                strip[8]=(0,255,0)
                strip.show()
                drive(FORWARD)
            elif right > threshold and left > threshold:
                # neither sensor detects the line
                stop()
                strip[2]=(255,0,0)
                strip[8]=(255,0,0)
                strip.show()
                break
            elif left > threshold and right < threshold:
               # only the right sensor detects the line
                strip[2]=(0,255,0)
                strip[8]=(0,0,0)
                strip.show()
                turn(RIGHT)
            elif right > threshold and left < threshold:
                # only the left sensor detects the line
                strip[2]=(0,0,0)
                strip[8]=(0,255,0)
                strip.show()
                turn(LEFT)
        stop()
https://i.imgur.com/ZYFwQ0l.gif

photo courtesy of Lisa Rode