This is a guide meant to be read by FLL coaches/teachers (or aspirant students) to create, in plain language, some of the more robust line following techniques (such as the much-hyped PID). All of these will only use one light sensor for the actual line following. I am going to feature three, single light sensor line followers: a binary (on/off) controller, a P (proportional) controller, and a PID controller. There is a great resource on these already available, but I thought I might try taking a shot at making the material a bit more accessible.
True to the spirit of FLL, I will not include explicit NXT code examples, but will try to make it so that constructing your own code after reading this will be as painless as possible (including posting pictures of code where suitable). I will however assume that you know how to make a program to display the light sensor's raw value. If you need help with this please just ask, I will be happy to help.
Herein I am using the Smart Move (2009) mat to follow along with the guide I am writing. Because of this, I am making a few assumptions about the line we are trying to follow. Most notably, the line turns to the left. For reasons I will cover later, mount your light sensor so that it is on the inside of the curve you want to follow. Placing it in front of the drive wheel is also a good idea.
Before we can make a full-fledged PID, we must first understand how the light sensors work, so that is where we start.
To avoid any confusion, the light sensors detect the intensity of light. It is not a color sensor, and it probably doesn't work solely in the visible spectrum of light. This means that external lighting conditions, while a factor to be considered, do not interfere as much as you'd believe they would. In fact, all of my '09 Smart Move teams' line followers worked regardless of light, even in total darkness.
Imagine that you point a light sensor at the sun, will it read black or white? White, of course. Now imagine that an ordinary black housefly is several feet from the light sensor, but directly between it and the sun. The light sensor is pointed straight at this black housefly, with the sun behind it. What will the light sensor read? White, in the same way that your eyes couldn't look at the sun under the same conditions without being blinded.
What does this tell us? That the light sensor detects brightness over a (small) area. Turn the light sensor on (so that it emits light), and point it at a desk or other flat surface. Notice how it projects a few red rings? The innermost one that is clearly visible (about the half the size of a pinky nail when you hold the light sensor an inch away) is approximately the polling area.
What this means is that, effectively, what the light sensor will detect is the average brightness in the polling area. If the polling area is half pitch black, and half pure white, then you can safely assume that the light sensor will read halfway between whatever it would in pitch black, and pure white conditions. This does not mean that the light sensor will return 50% (or 512 raw value), just halfway between those two numbers.
So what value does your light sensor read in pitch black, or pure white? Well, those two values don't matter, but what matters is what your light sensor reads on the white of the board, and the black of the board. So let us figure out what those values are!
But first a word on set up. Because your light sensor works in an area (a cross section of a cone of emitted light) if you change how far your light sensor is from the board, it can have nasty consequences. In my experiences, keeping the light sensor within 2 centimeters of the board is ideal. Keep the light sensor perpendicular to the board. Changing where your light sensor is on the robot will result in a need to recalibrate so what I am saying is calibrate your robot in the same configuration you will run it in. Things like attachments typically shouldn't matter, though.
Create a program that polls the light sensor continually, and prints it's raw value to the display (make sure you tell it to clear the display, else wise you might write down the wrong values). We are using the uncalibrated, raw value of the light sensor because it is the most accurate representation of how the light sensor perceives the world.
Now take your robot, with the program running, to the board and place it over a wide open, white area. Write this value down, and be sure to label it WHITE. Then place the robot so the light sensor is directly over the blackest part of the line you want to follow (this is where its handy to have a light sensor near the ground, so the sensor doesn't accidentally get some white inside its polling area). Record the number and label it BLACK. When doing this, be sure you aren't touching the robot, or blocking its light with your shadow, etc – keep it as close to competition conditions as you know how.
On my table, I got 444 as the WHITE value, and 666 as the BLACK value. (yes, actual values) Perhaps counter intuitively the value of the black line is larger than the white background. You may notice that even when the environment was unchanging, your values were not perfectly constant, and instead variable within a small range. This is normal behavior, and it shouldn't really matter what number you choose within that range.
Another important concept is that our line follower will not be following a line. Instead, it will be following the EDGE of the line. This is because the light sensor only knows what its looking at, but by looking at the edge of the line we will get a value between WHITE and BLACK that will let us infer a second piece of information, how far we are from where we want to be. Trying to be on pure black all the time doesnt work because what happens when you go to white – should you turn left or right? Depends on if you overshot too much to the left or right... but the robot doesnt know which its done.