Build a mini robotBeginnerLesson 2666 min read

Line follower in code

Two small light sensors and a few if-statements are enough to follow a curving black line. Write the classic line-follower and learn what to do when the robot loses the line.

Lesson in motion

In 60 seconds

Line follower in code

Two small light sensors and a few if-statements are enough to follow a curving black line. Write the classic line-follower and learn what to do when the robot loses the line.

1/4
In simple words
Imagine walking along a painted line on a playground with your eyes on your feet. If your left foot steps off the line, you move a little right. If your right foot steps off, you move a little left. If both feet are on it, you keep walking. That is all a line-following robot does.
A line follower is one of the most popular first robots. It follows a black tape path on a light floor. Some robotics competitions for school students use line-following tracks, and many factories and warehouses have used robots that follow lines or markers on the floor to carry things.

The two-sensor rule

Our robot has two IR sensors at the front, 4 cm apart, over a 6 cm wide tape. When the robot is centred, both see the tape. As it drifts, one sensor leaves the tape first.
Left sensorRight sensorWhat it meansWhat to do
1 (tape)1 (tape)Centred on the lineGo straight
1 (tape)0 (floor)The tape is to the leftTurn left: slow the left wheel
0 (floor)1 (tape)The tape is to the rightTurn right: slow the right wheel
0 (floor)0 (floor)Lost the lineKeep turning the way you last turned

Remembering the last turn

The last row matters. On a sharp curve, the robot can overshoot so both sensors see the floor. If it then drives straight, it leaves the line forever. A better robot remembers which way it last turned and keeps turning that way to search for the line. This needs a small piece of memory outside the function, such as a global variable.
Python: the rule table as codepython
last_turn = "left"          # memory: which way we turned last

def line_rule(left, right):
    global last_turn
    if left and right:
        return "straight"
    if left:
        last_turn = "left"
        return "left"
    if right:
        last_turn = "right"
        return "right"
    return "search " + last_turn

for l, r in [(1, 1), (0, 1), (0, 0), (1, 1), (1, 0), (0, 0)]:
    print(l, r, "->", line_rule(l, r))

Choosing speeds

Common mistakes
  • Full speed everywhere: the robot flies off curves
  • Turning by stopping a wheel completely every time: jerky, slow progress
  • Driving straight when the line is lost
  • Testing only on a straight line
Better habits
  • A moderate base speed, such as 0.6
  • Slow one wheel, do not stop it, for small corrections
  • Remember the last turn and search that way
  • Test on curves, and on the curve that goes the other way
Note
Our two-sensor robot is a bang-bang controller: each wheel is either "fast" or "slow", nothing in between. It works, but it wiggles. In lesson 7 you will use a sensor that says how far the line is, and steer smoothly with PID.
Real example
Picture a school robotics club in Pune. It makes its track from black insulation tape on white chart paper taped to the floor. The first robot flew off the first bend. The fix was not new parts: the students lowered the base speed, added the "remember the last turn" rule, and adjusted the sensor threshold screw for the classroom's tube lights.
Try this. In the code above, what does the robot do if it sees (0, 0) at the very start, before it has ever turned? Is "left" a good default? What else could it do?

Watch and read more

Lab

A two-sensor line follower that stays on the curving tape all the way along the track.

~25 min

The problem

This runs in your browser. The tape starts straight and then curves up and down. Your robot starts on the tape, facing along it.

  1. Run the starter. The robot drives straight and leaves the tape at the first curve.
  2. Change decide to use only s["left"] and s["right"] (the check hides the other readings). Follow the rule table from the lesson.
  3. Add a global variable to remember the last turn, for when both sensors see the floor.
  4. Goal: after 150 steps, no crash, the robot has reached at least x = 140 cm, and its middle was never more than 5 cm from the tape.
  5. Try base speeds of 0.4, 0.6 and 0.8 and write down what changes.

Practice lab

Edit the code and run it. Python runs in your browser — nothing is sent to our server.

Output

No output. Add print(...) to see values.

You are done when

Hard questions

Try to answer before you reveal. If you can answer these, you understood the lesson.

Q1Your line follower passes in the simulator at speed 0.6. Why might the same logic fail on a real robot at the same speed?Reveal

The simulator reacts every 0.1 s with perfect sensors and motors. A real robot has motors that speed up and slow down gradually, sensors that need the right height and threshold, a floor that may be shiny or bumpy, and one motor that is often a little stronger. Each adds delay or error, so the robot overshoots more. Start slower on the real robot and tune up.

Q2The track has a sharp right-angle corner. Why can the "remember the last turn" rule still fail there, and what could help?Reveal

At a right angle the robot may still be driving straight when both sensors leave the tape, so its last turn could be the wrong way, or the turn is too gentle to find the line in time. Helpful ideas: slow down when a sensor first loses the tape, spin in place (one wheel back, one forward) while searching, or add a third sensor in the middle or further to the sides.

Please sign in to continue.

Questions people ask

Why use two sensors? Would one be enough?

One sensor can follow the edge of the line: turn one way when it sees dark, the other way when it sees light. It works, but it wiggles more and gets lost more easily. Two sensors tell you which side the line is on. Robots built for speed often use a row of five or more sensors.

What width of tape should I use on a real track?

Match the tape to your sensor spacing. If both sensors should see the tape when centred, the tape must be a bit wider than the gap between them. Try your tape first and adjust the sensor positions.

Why do I need a global variable?

The decide function is called fresh every step. Anything it should remember between steps, like the last turn, must live outside it: in a global variable, a dictionary or a class. In C++ on a real board, you would use a variable declared outside loop().

My robot follows the line but very slowly. What should I change first?

Raise the base speed a little at a time, and make the turns gentler (slow the inner wheel instead of stopping it). Test after each change. The fastest settings are usually just below the point where the robot starts losing the line on the sharpest curve.

Lesson test

5 questions. Get 3 right (60%) to pass and complete this lesson.

Sign in to take the test and save your progress