Tuesday, September 2, 2014

Arduino Light Following Robot [Full Tutorial]

Overview
This instructable will use three photoresistors (light dependent resistors) and an Arduino to control the motion of a robot. Any common robot chassis can be used for the robot. The light sensors will be mounted on the left side, right side and front of the robot. When light of sufficient intensity falls on a sensor, the robot will respond with a left turn, right turn or forward movement, corresponding to the location of the sensor that is activated. The instructable will also pass along some electronics tips that I have found useful and, hopefully, will prove useful to others.

Step 1: List of Materials

List of Materials:
3x Light Dependent Resistors
http://www.jameco.com/webapp/wcs/stores/servlet/Product_10001_10001_202403_-1
3x 250K trimmers (potentiometers)
http://www.jameco.com/webapp/wcs/stores/servlet/Product_10001_10001_2200903_-1
3x Three pin sensor cables
http://www.trossenrobotics.com/robotgeek-3pin-sensor-cable
1x Duemilanove or compatible Arduino board http://www.freetronics.com/collections/arduino/products/eleven#.UzImtdhOWM8
1x DFRobot motor shield
http://www.dfrobot.com/index.php?route=product/product&filter_name=motor shield&product_id=69#.UzInGthOWM8
1x Arduino proto shield
http://www.adafruit.com/products/51
1x Robot Chassis
http://www.hobbyking.com/hobbyking/store/__26248__Simple_Expandable_Robot_Chassis_KIT_.html
2x 4”x6” Proto boards
http://www.elexp.com/ProductDetails.aspx?item_no=03013404&CatId=a936becc-2bfd-49bb-b59b-7c07715dbfea
Various standoffs and hardware. A good kit can be found at
http://www.dfrobot.com/index.php?route=product/product&path=46_99&product_id=700#.UzIrrNhOWM8
The standoffs used in this instructable are from a Trossen Robotics robot kit. The standoffs and hardware are also sold individually
http://www.trossenrobotics.com/standoff-variety-pack
http://www.trossenrobotics.com/nut-and-bolt-pack
1x 6AA battery holder
http://www.digikey.com/product-detail/en/BH26AAW/BH26AAW-ND/66737
1x 9V battery holder with barrel plug
http://www.adafruit.com/products/67
Finally, we will need some male and female headers
http://www.jameco.com/webapp/wcs/stores/servlet/Product_10001_10001_308567_-1
http://www.jameco.com/webapp/wcs/stores/servlet/Product_10001_10001_2076869_-1

Step 2: Robot Platform

Robot platform preparation. As mentioned, any common chassis can be used for the robot, and I chose the Arexx robot chassis listed above. This chassis had a rather small upper deck, thus the need for one of the proto boards. Put four 3cm (or similar) standoffs on the existing holes on the lower deck of the chassis, and then position the proto board on top of the standoffs to form the upper deck. Mark and drill screw holes. See accompanying photo. This gives us a platform that we can drill screw holes into to hold various electronics and sensors. This platform can be reused with other sensors in future robot projects.

Step 3: Light Sensor Platforms

Next we need to construct the light sensor platforms. One proto board was used for the upper deck of the robot. From the second proto board, use a hobby saw or Dremel to cut three 1.5cm by 2.5cm rectangles. In each corner, drill a screw hole. These small boards will hold the electronics of our light sensors. Before we add the electronics, position the small boards on the upper deck of the robot as shown in the accompanying figure. Mark, drill holes, and add 1cm standoffs to attach the small boards to the upper deck. At this time, you may also want to decide on the position of the Arduino board on the upper deck and drill appropriate screw holes. Also add some 1cm standoffs to hold the Arduino. Leave enough room between the Arduino and the light sensors to insert the AA battery holder.

Step 4: Light Sensor Electronics

Now for the electronics for the light sensors. Each light sensor will consist of a voltage divider made from a photoresistor and 250K trimmer. First, from the female header strip, cut three pairs of headers. From the male header strip, cut three sections of three headers each. See accompanying picture. Bend the male headers, if needed, to form a right angle. Before soldering anything, the first thing I did was hot glue one female header pair, one three pin male header and one 250K trimmer to each small proto board. See accompanying figure. On the back of the protoboard there will be two leads from the female header, three leads from the trimmer, and three leads from the male header as seen on the far right in the accompanying figure. Before soldering, it may help to bend the leads of the trimmer as shown in the accompanying photo. Solder the leads as follows. One section of wire (white in the photograph) will connect the wiper lead of the trimmer to the far right leads of the male and female headers. A second section of wire (red in the photograph) will connect the left female header lead to one of the remaining leads of the trimmer and the center lead of the male header. A third section of wire (black in the photo) will connect the remaining lead of the trimmer to the left most lead of the male header. Finally, insert a photoresistor into the female header on each small proto board.
The advantage of this voltage divider is that it can be adjusted with a small screwdriver via the trimmer. Thus the sensitivity of the light sensor can be changed independent of the Arduino code (contained below). Also, these small platforms can now be used as light sensors for future electronics projects. In addition, other types of electronics can be put onto the small 1.5cm x 2.5cm proto boards; LEDs, piezo buzzers, buttons, lasers, etc. Since all the small boards will be the same size, they will be interchangeable on the robot deck, giving many possibilities for different robot configurations. I am currently constructing several such boards and a customized Arduino shield for a future Instructable.

Step 5: Arduino connections

Now we connect the electronics. Screw the three light sensors and the Arduino to the upper deck of the robot chassis. Attach the DFRobot motor shield to the Arduino and attach the motor wires and AA battery holder leads to the appropriate screw terminals on the motor shield. I positioned the battery holder between the light sensors and the Arduino. If it does not fit snuggly, secure it with some double sided tape. Next attach the Arduino proto shield on top of the motor shield. The three-pin cables will now connect the light sensors to the proto shield. The three-pin cables I used were female-female and color coded white, red and black with red in the center. On each light sensor, with the male headers pointing down, connect a three-pin cable with the white wire on the left. From the male header strip, cut three more sets of three pins. Use these to connect the other ends of the cable to the breadboard on the Arduino proto shield as shown in the photo. Connect the black wires to the ground rail on the proto shield and connect the red wires to the 5V rail. Connect the white signal cables as follows: the right sensor to analog pin 0, the center sensor to analog pin 1 and the left sensor to analog pin 2. I also ran a wire from the ground rail of the proto shield to the negative input screw terminal of the DFRobot motor shield.

Step 6: Arduino code

Arduino code and calibration. Upload the code given below to the Arduino and follow the calibration directions given below the code.
/* Flashlight Following Robot Code 3/25/2014

This code uses three light dependent resistors positioned
on the right, front and left sides of a robot to control
motion. When light of sufficient strength falls on one of
the sensors, the robot turns right, moves forward or turns
left.
*/

// Motor control pins
int E1 = 5; // Enable pin for right motor
int M1 = 4; // Speed control pin for left motor
int E2 = 6; // Enable pin for the left motor
int M2 = 7; // Speed control pin for right motor

// The following motor speeds are determined by experiment
// so that the robot moves forward in a straight line.
int leftMotorSpeed = 215;
int rightMotorSpeed = 185;

int sensorPinRight = 0; // Right sensor pin
int sensorPinCenter = 1; // Center sensor pin
int sensorPinLeft = 2; // Left sensor pin

int lightReadingRight;
int lightToleranceRight = 1000; // Sensor reading needed to trigger right turn

int lightReadingCenter;
int lightToleranceCenter = 1000; // Sensor reading needed to trigger forward movement

int lightReadingLeft;
int lightToleranceLeft = 1000; // Sensor reading needed to trigger left turn

int readingDelay = 100; // Delay between readings

void setup()
{
pinMode(M1,OUTPUT);
pinMode(M2,OUTPUT);

// Uncomment the serial feed for calibration purposes
Serial.begin(9600);
}

void loop()
{
// Uncomment the serial print lines for calibration purposes

// Take reading from right sensor
lightReadingRight = analogRead(sensorPinRight);
Serial.print("Right Sensor Reading :");
Serial.println(lightReadingRight);

// Take reading from center sensor
lightReadingCenter = analogRead(sensorPinCenter);
Serial.print("Center Sensor Reading :");
Serial.println(lightReadingCenter);

// Take reading from left sensor
lightReadingLeft = analogRead(sensorPinLeft);
Serial.print("Left Sensor Reading :");
Serial.println(lightReadingLeft);


// Move forward if enought light is detected from center sensor
if (lightReadingCenter > lightToleranceCenter)
{
digitalWrite(M1, HIGH);
digitalWrite(M2, HIGH);
analogWrite(E1, leftMotorSpeed);
analogWrite(E2, rightMotorSpeed);
delay(readingDelay);
// Stop
digitalWrite(M1, LOW);
digitalWrite(M2, LOW);
analogWrite(E1, 0);
analogWrite(E2, 0);
}

// Turn right if enough light is detected from right sensor
if (lightReadingRight > lightToleranceRight)
{
digitalWrite(M1, LOW);
digitalWrite(M2, HIGH);
analogWrite(E1, leftMotorSpeed);
analogWrite(E2, rightMotorSpeed);
delay(readingDelay);
// Stop
digitalWrite(M1, LOW);
digitalWrite(M2, LOW);
analogWrite(E1, 0);
analogWrite(E2, 0);
}

// Turn left if enough light is detected from left sensor
if (lightReadingLeft > lightToleranceLeft)
{
digitalWrite(M1, HIGH);
digitalWrite(M2, LOW);
analogWrite(E1, leftMotorSpeed);
analogWrite(E2, rightMotorSpeed);
delay(readingDelay);
// Stop
digitalWrite(M1, LOW);
digitalWrite(M2, LOW);
analogWrite(E1, 0);
analogWrite(E2, 0);
}
// delay(5000); // Uncomment this long delay for motor calibration purposes
}

With this code uploaded to the robot, disconnect the motors and open the serial monitor to take a look at the readings from the light sensors. I did my calibration in normal room light. Each of the uncovered sensors gave readings in the 1000 to 1100 range. I slowly adjusted the trimmers until each sensor read about 1000. A little bit more or a little bit less is alright. When I covered a sensor up from light, the reading dropped to the high 800s to low 900s. In the Arduino code I then set the three tolerance variables; lightToleranceLeft, lightToleranceRight, and lightToleranceCenter to 1000. Thus, when the robot is in darkness, all readings will be below the trigger level of 1000. When a flashlight is shown on a sensor, the sensor reading will go above the trigger level and activate the appropriate motion of the robot.
The specific numbers I used for my particular sensors are not important. What is important is that you send the sensor readings to the serial monitor to get their ambient light readings. Then slowly adjust the trimmers on the sensors until the readings from all three sensors are about the same. Then cover up each sensor and you should get a lower reading. Set your tolerance variables to some reading near the ambient light reading. A flashlight shining on the sensor should then invoke a reading higher than the tolerance, thus activating the robot.
One last thing regarding calibration. At the very bottom of the Arduino code is a commented line with a delay of five seconds. I uncommented this line to make sure the motors were attached correctly. With the robot suspended off the ground, run the code with the robot in the dark. Shine a light on the front sensor and with your hands feel which way the wheels are turning. If one of them is moving backwards instead of forward, switch the position of the wires of that motor on the motor shield. Next shine a light on the right sensor and feel the wheels. The right wheel should go backwards and the left wheel should go forward. If the opposite happens, swap the motor positions. M1+ becomes M2+ and M1- becomes M2- and vice versa. Lastly, comment out the five second delay and upload the code again. The robot should be ready to go.

0 comments:

Post a Comment