Line following with the Photoreflector sensor bar


For this example we will show you how to build a simple (but cool) line following bot, using the BoxBot robot chassis. This will hopefully give you an understanding of simple logic and connecting sensors to your microcontroller.

Items you will need for this project



BoxBot robot chassis

BoxBot Photoreflector Sensor Bar

Arduino

Servos

Jump Wire Kit

You will also need 4 AAA Batteries, and one 9v PP3 rectangular battery.

Prerequisits


This example assumes you are familiar with the Arduino IDE, connection and uploading. If not we suggest you visist www.arduino.cc and read their getting started and learning guides.


Overview & Descripton


A line following bot normally uses a sensor placed on the chassis to detect the presence of a certain coloured line - normally black or white. For this example we are using 2 Photreflectors to detect different changes in the colour underneath it. Photoreflectors work by emitting an invisible infreared light and the detecting the intensity recieved on a infrared detector.

The sensor is essentially a variable resistor. Rather than you manually turning a knob to change the resistance (power throughput), the amount of refelected light does. The more light reflected the lower resistance, and vice versa.

For example a black line absorbes some of the light so the sensor sees less of the light return, and gives a lower voltage (higher resistance). A white line or surface will bounce more light back and we see a higher voltage retured (less resistance).

For this project we are going to monitor the amount of 5v returned to one of the Arduino's analogue inputs. We are going to use analogue rather then digital because digital is either on or off, and analogue is a sliding scale. The sensors report back a value from 0 to 1024 (for 5v). We calibrate the code so that we know that white = X and black = X. For example when the sensor is on a white surface the sensor receives a value of 500 from the sensor. A black surface may report 100.

So, we can easily say that when the value is < (less than) 300 (we add a buffer because a white surface may fluctuate as the bot is on it's travels) we are on a black line.

Using these rules:
  • < 300 = black line
  • > 300 = white surface

We can build some code to turn the bot when it detects it is off the black line. As the sensor bar has 2 sensors we can detect if the bot is on the line or not for both left and right turns.

Project video


Here is the result of this project in video. (note the circuit does not include the additional LEDs on the breadboard).



The circuit


White wires are shown in grey for clarity.


Make up this circuit on your breadboard. The wire colours are just for clarity on the diagram and do not relate to the jump wire kit colours, however the wires on the servos and sensors are true. The circuit connects the Arduino to the servos, and attaches the photo reflective sensors to the analogue pins on the Arduino via pull-up resistors. The pull-up resistors do exactly what it sounds like, they "pull up" the value to 5 volts. The reason they pull up is to eliminate the effects of a drifting circuit. If the output is floating so could the value the Arduino reads thus giving erroneous readings. So when no signal is present the output the Arduino sees is pulled up to 5V. When the sensor does send a signal it has enough current to overcome the pull-up resistor and ground (0 Volts) the output.

Pay attention to the polarity, and the servo connections. Double check all your connections are correct before connecting power. Short circuits and reverse polarity can damage the Arduino, sensors and servos.

Setting up the sensor bar


As you should already have constructed your sensor bar, all you need to do is correclty position the sensors. In this example we found the optimum position for the sensors was with the bottom of the sensor flush with the bottom of the sensor bar. The sensor bar has mountings to move the sensors up and down, if you need to adjust your sensors height position to get the best readings then simply loosen the nut and bolt, position and re-tighten..

The setup calibration code


(Arduino only) Use this code to get the ideal sensor values for the black line values. Enter the code below into the IDE and upload it to the Arduino. Start the serial monitor (refer to the Arduino help if you are unsure how to do this) and set it to 9600.

// Bot builder BoxBot line follower code for the Photoreflector sensor bar calibration. int LeftOpto = 0; // Create a variable called LeftOpto on analog pin 0 so we can read the value of the Left Photosensor. int RightOpto = 1; // Create a variable called RightOpto on analog Pin 1 so we can read the value of the Right Photosensor. int lval = 0; // Initialise a variable called lval, this is used to store the Left sensors value, set it to 0. int rval = 0; // Initialise a variable called rval, this is used to store the Left sensors value, set it to 0. void setup() { Serial.begin(9600); // Start the serial service @ 9600 baud rate. } void loop() { lval = analogRead(LeftOpto); // Read the value incoming from the photoreflector on pin 0 and assign it to the variable lval. Serial.print("Left"); Serial.println(lval); // Print to the serial port the lval value so you can see what it is. rval = analogRead(RightOpto); // Read the value incoming from the photoreflector on pin 1 and assign it to the variable rval. Serial.print("Right:"); Serial.println(rval); // Print to the serial port the rval value so you can see what it is. } delay(1000); // Delay 1 second on each read so you have a chance to see the value. }
If everything is connected up properly you will now start to see:

Left: XXX
Right: XXX

Being repeated in the serial monitor. Place the bot on a clear light/white surface and wait a second (remember the code updates every second) record whatever number you see for both left & right. Now move the sensors onto the black line, again wait a second and then record the number you see in the serial monitior.

The fist set of numbers should be greater then the 2nd set. Now you need to figure out what the ideal value to make your bot know it is no longer on the black line. For example, if your white value was 700 and the black value was 200 a good trigger is about 400 - 500. When you think you have a good value you can now move onto the main code example below. You can always change the values if your bot does not follow the line correctly.

The main code


(Arduino only)

// Bot builder BoxBot line follower code for the Photoreflector sensor bar int LeftOpto = 0; // Create a variable called LeftOpto on analog pin 0 so we can read the value of the Left Photosensor. int RightOpto = 1; // Create a variable called RightOpto on analog Pin 1 so we can read the value of the Right Photosensor. int TurnLED = 13; // We need to declare that we are using pin 13 for our turn indicator LED. int lval = 0; // Initialise a variable called lval, this is used to store the Left sensors value, set it to 0. int rval = 0; // Initialise a variable called rval, this is used to store the Left sensors value, set it to 0. #include <Servo.h> // Include the servo library, so we can easily use servos. Servo LeftServo; // Tell the library that we want to create a servo called LeftServo. Servo RightServo; // Tell the library that we want to create a servo called RightServo. void setup() { pinMode(TurnLED, OUTPUT); // Set the turn LED pin to be an output (so we can turn it on and off). LeftServo.attach(9); // Tell the servo object to attach the LeftServo to Pin 9. RightServo.attach(10); // Tell the servo object to attach the LeftServo to Pin 10. } void loop() { lval = analogRead(LeftOpto); // Read the value incoming from the photoreflector on pin 0 and assign it to the variable lval. if (lval > 550) { // If lval is greater that the threshold of what we determined the black line is - ie. we are on white. digitalWrite(TurnLED, HIGH); // Turn on the Turn LED on pin 13. LeftServo.write(90); // Stop the left servo by centering it. } else { digitalWrite(TurnLED, LOW); // Turn off the turn LED on pin 13. LeftServo.write(120); // Drive the left servo forward. } rval = analogRead(RightOpto); // Read the value incoming from the photoreflector on pin 1 and assign it to the variable rval. if (rval > 550) { // If rval is greater that the threshold of what we determined the black line is - ie. we are on white. digitalWrite(TurnLED, HIGH); // Turn on the Turn LED on pin 13. RightServo.write(90); // Stop the right servo by centering it. } else { digitalWrite(TurnLED, LOW); // Turn off the turn LED on pin 13. RightServo.write(50); // Drive the right servo in reverse (makes the bot go forward, as the servos are inverted). } delay(200); // Delay 200 microseconds, just to smooth out any jerky movements. }

Testing


Make up a path for your bot to follow. We have designed the sensor bar to accept paths made using standard 20mm electrical insulation tape. This is available in black, is easy to create paths with and cheap. Create your path nice gentle curves. The code does not allow the bot to follow sharp bends. The more contrast you have between the surface colour and the line colour, the better the sensors performance and ultimately your bot's.

Once your path has been made, power the Arduino with the DC plug, and then power the servos. Place your bot on the path with the line passing between the sensors. It should now start to follow the path.

If it is missing turns, try to re-position the sensors, and check that the path does not cause both sensors to be over the black line.

If you are still having problems making the bot follow the line, step back to the "setup calibration code" section and double check your sensor values.

Other things to try


This example shows you have to follow a black line. If you want it to follow a white line on a dark surface, use the < (less than) operator in the "if" code, eg.

if (lval < 550) {