3. Infrared Emitter/Detector Tutorial

     

Your Bit:Bot has 2 TCRT5000 reflective optical sensors (infrared) on its bottom. If you have a look at the bottom of your Bit:Bot you will see them. The lighter blue one is an infrared emitter and the dark one is the infrared receiver. They are analogue devices so they would usually work in a similar way to the light detectors however when 4Tronix developed the Bit:Bot they decided to connect them to digital i/o pins so we will interact with them like a digital device. When they see a lot of IR reflected they will return a logic 0. When they see no IR reflected they will return a logic 1.

Dark colours will reflect less IR than light colours; this means that we can use these sensors to detect a black line on a white background. In this example we will create a program that will light the NeoPixles of the Bit:Bot when a black line is detected and the NeoPixles will alter their brightness depending on the ambient light. These sensors have no filters on them meaning that they’re susceptible to interference from the sun; because of this this type of IR sensor should not be used for object detection; either ultrasonic or IR TOF (infrared lasers) sensors would be a better solution for that.

Open Mu and start a new project; copy and paste the below code into the new project (its code from the previous example).

Code from Previous Example to Light the LEDs
# IR sensor example for the 4tronix Bit:Bot and BBC Micro:Bit
# Author David Bradshaw 2017
# Demonstrates how to use the IR sensors TCR5000

from microbit import *
import neopixel # Neopixel Library so we can control the NeoPixels lights

np = neopixel.NeoPixel(pin13, 12)

# Both light sensor are on the same pin so we also use a select pin
lightSensor = pin2
sensorSelect = pin16

# Set the pin number of the IR detectors
leftLineSensor = pin11
rightLineSensor = pin5


def leftLights(Red, Green, Blue):
for pixel_id in range(0, 6):
np[pixel_id] = (Red, Green, Blue)
np.show()


def rightLights(Red, Green, Blue):
for pixel_id in range(6, 12):
np[pixel_id] = (Red, Green, Blue)
np.show()


def setBrightness(minValue):
sensorSelect.write_digital(0)
brightnessLeft = lightSensor.read_analog()
sensorSelect.write_digital(1)
brightnessRight = lightSensor.read_analog()

brightness = int((brightnessLeft + brightnessRight) / 2)
brightness = int(brightness / 25)
if(brightness < minValue):
brightness = minValue
return brightness

while True:

I have deleted the code from the program loop, I have added 2 variables for the left and right line sensors and I have changed the comments at the top slightly to reflect the new project.

Now we’re going to create a method that will take readings from both left and right IR sensors. Under the lightSense() method ensure that their is 2 blank lines with no white space and type;

Just a Line Detector Function
def lineDetector(side):  # side == 0 is left, side == 1 is right
if(side == 0):
isLine = leftLineSensor.read_digital()
else:
isLine = rightLineSensor.read_digital()
if(isLine == 1): # Sensor can see the line
return True
else:
return False

I have introduced some new concepts here. Firstly we have used some conditional statements known as if statements (you would have seen these in the previous example for the setBrightness() method) and secondly our method returns a boolean value depending on what the IR detector sees.

The if statements are quite easy to understand; if the condition is true, for example if side is equal to 0 then execute the code indented underneath the if statement. If the condition is false then skip to the else clause. When writing if statements everything indented under the if statement is part of the true condition. You don’t have to have else clauses with statements if you don’t need them.

The boolean data type will hold one of 2 values either True of False. This method will return a True value if a line is detected and a False value if not. When writing conditional statements we use 2 equal signs rather than 1. This is so the Micro:Bit knows that we are comparing two values rather than assigning a value to a variable.

Now we have a method to interpret the data coming back from our IR detectors all we need to do is write some code for the program loop to make the LEDs light when no IR is reflected; when its over a non reflective surface such as a black line, or when the Bit:Bot is picked up.

Put the following code in the program loop;

Decide Which LEDs to Light
while True:
if(lineDetector(1) is True):
rightLights(setBrightness(3), 0, 0)
else:
rightLights(0, 0, 0)

if(lineDetector(0) is True):
leftLights(setBrightness(3), 0, 0)
else:
leftLights(0, 0, 0)

Notice that where the light intensity is normally entered for the red colour component I have use the setBrightness() method instead with a minimum brightness of 3. This will make sure that the LEDs are dim in low light and bright in bright light. The above code will check each IR detector in turn to see if a line is detected and either turn lights off or on depending on the results.

Below is all of the code from this example;

Full Code Example
# IR sensor example for the 4tronix Bit:Bot and BBC Micro:Bit
# Author David Bradshaw 2017
# Demonstrates how to use the IR sensors TCR5000

from microbit import *
import neopixel # Neopixel Library so we can control the NeoPixels lights

np = neopixel.NeoPixel(pin13, 12)

# Both light sensor are on the same pin so we also use a select pin
lightSensor = pin2
sensorSelect = pin16

# Set the pin number of the IR detectors
leftLineSensor = pin11
rightLineSensor = pin5


def leftLights(Red, Green, Blue):
for pixel_id in range(0, 6):
np[pixel_id] = (Red, Green, Blue)
np.show()


def rightLights(Red, Green, Blue):
for pixel_id in range(6, 12):
np[pixel_id] = (Red, Green, Blue)
np.show()


def setBrightness(minValue):
sensorSelect.write_digital(0)
brightnessLeft = lightSensor.read_analog()
sensorSelect.write_digital(1)
brightnessRight = lightSensor.read_analog()

brightness = int((brightnessLeft + brightnessRight) / 2)
brightness = int(brightness / 25)
if(brightness < minValue):
brightness = minValue
return brightness


def lineDetector(side):
if(side == 0):
isLine = leftLineSensor.read_digital()
else:
isLine = rightLineSensor.read_digital()

if(isLine == 1): # Sensor can see the line
return True
else:
return False


while True:
if(lineDetector(1) is True):
rightLights(setBrightness(3), 0, 0)
else:
rightLights(0, 0, 0)

if(lineDetector(0) is True):
leftLights(setBrightness(3), 0, 0)
else:
leftLights(0, 0, 0)

The code is starting to look more complicated now. We have the main building blocks of our line following robot all we need now is a way to control the motors and to decide how the robot will behave when it either sees or doesn’t see a line. We will also need to think of what we can do to stop the robot from getting stuck if it gets confusing data back from the sensors.

Check your code and Flash it to the Micro:Bit, if you have errors copy and paste the code from above or download the files from the bottom of this page. Have a play with it and see how the Bit:Bot behaves. Pick your Bit:Bot up off the floor and the LEDs will come on because no IR will be reflected then point the IR detectors towards a bright window and you will see the LEDs turn off. This is because the IR light coming from the sun is interfering with the IR detectors. Finally with the LEDs on vary the amount of light getting to the light sensors and you will notice how the LEDs brightness changes.

Well done for completing this example. Now we can start having some fun in the next example with a line following robot utilising all the code we have developed up to now.

Code Files

The link below is the above code that can be downloaded and loaded into Mu.

IRexample.zip

For the code to work unzip the file, open in Mu and upload to the Micro:Bit.