Monday, September 9, 2013

Line Follower


Tasked to build a robot, using a Mega 2560 Arduino board, that followed about a half inch thick black line. I came up with the specimen in the gif above. A total of about 8 hours was spent wiring, coding, and debuging (4 hours of this was spent frustratingly examining/tweaking my not-working code only to find out that the robot hadn't been connected to ground, thereby negating any powerflow).

Wiring:



In this photo we can observe the physical connections to the Arduino Mega 2560. The servos, left and right, go into PWM ports 9 and 10, respectively. Left Outside Line Follower sensor is in PWM port 2, Left Inside Line Follower sensor is in PWM port 3, Right Inside Line Follower sensor is in port 4, and Right Outside Line Follower sensor is in port 5. A better view of the connections between Arduino board and sensors can be seen below. The pushbutton sensor (opted for this as the flip switch did not fit in the breadboard) is in PWM port 8.


Here we see the better angle of the wires going between the sensors and the Arduino board. Also note that there is a 10kOhm resistor connected to the ground of the push button in order to enable positive logic, pulling the button naturally towards 0, or off.


It is also important to note here that the Line Follower sensors are wired differently that one might intuitively assume. In most circuits, red stands for the "hot" wire in which voltage flow is considered to go through to get to the "ground" wire, black. However, in these sensors the white is used for the "hot" and black is reserved for "ground," while the red is used for data acquisition. Plugging the inputs in the wrong areas could result in a broken sensor, so this is something to be wary of.


Code:

#include <Servo.h>

Servo rightServo;
Servo leftServo;

int leftOutside = 2; //assigns left outside sensor as 2 for easy pinmoding
int leftInside = 3; //assigns left inside sensor as pin 3
int rightInside = 4; //assigns right inside sensor as pin 4
int rightOutside = 5; //assigns right outside sensor as pin 5
int movePos = 180; //value makes motors go
int stopPos = 90; //value makes motors stop
int color = 15; //arbitrary value above determined highest received value for white
int buttonPin = 8; //assigns button as pin 8 for easy pinmoding
int buttonValue = 0; //establishes a button value as 0

void forward()  //this function makes the robot go forward
{
  rightServo.write(-movePos);
  leftServo.write(movePos);  
}

void leftTurn()  //this function makes the robot turn left

  rightServo.write(-movePos);
  leftServo.write(-movePos);
}

void rightTurn()  //this function makes the robot turn right

  rightServo.write(movePos);
  leftServo.write(movePos);
}

void stopRobot()  //this function stops the robot
{
  rightServo.write(stopPos);//90 is the servo stop point
  leftServo.write(stopPos);
  
}

void setup() {
  Serial.begin(115200);
  rightServo.attach(10);
  leftServo.attach(9);
  delay(10);
  pinMode(buttonPin, INPUT);
}

void loop() 
{
  stopRobot();
  
  buttonValue = digitalRead(buttonPin);
  
  while(buttonValue == 1)
  { 
    while(true)
    {
      Serial.print("Button value is: ");            
      Serial.println(buttonValue);                  //shows button value
      
      Serial.print("Left inside value: ");
      Serial.println(RCTime(leftInside));    //shows left inside follower value
  
      Serial.print("Right inside value: ");
      Serial.println(RCTime(rightInside));          //shows right inside follower value
  
      Serial.print("Left outside value: ");
      Serial.println(RCTime(leftOutside));    //shows left outside follower value
      
      Serial.print("Right outside value: ");
      Serial.println(RCTime(rightOutside));         //shows right outside follower value
      
      Serial.println("___________________");        //prints line to separate data values
      
      delay(10);    // Wait 10 ms
  
     if (RCTime(rightInside) > color || RCTime(leftInside) > color && RCTime(leftOutside) < color && RCTime(rightOutside) < color)  //goes straight
     {
        forward();
     }
     
     if (RCTime(rightInside) < color && RCTime(leftInside) < color && RCTime(leftOutside) > color)  //corrects left
     {
        leftTurn();
     }
     
     if (RCTime(rightInside) < color && RCTime(leftInside) < color && RCTime(rightOutside) > color)  //corrects right
     {
        rightTurn();
     }
    } 
  }
}

long RCTime(int sensorIn)         //Copied this function from the arduino website
 {
   long duration = 0;
   pinMode(sensorIn, OUTPUT);     // Make pin OUTPUT
   digitalWrite(sensorIn, HIGH);  // Pin HIGH (discharge capacitor)
   delay(1);                      // Wait 1ms
   pinMode(sensorIn, INPUT);      // Make pin INPUT
   digitalWrite(sensorIn, LOW);   // Turn off internal pullups
   while(digitalRead(sensorIn))
   {  // Wait for pin to go LOW
      duration++;
   }
   return duration;

 }

Issues:
The most notable issue with this was getting the sensors to read properly. The causation of this was my own inattentiveness in not providing proper power flow. After about 4 hours of head scratching, forum browsing, and reprogramming, I found that I had neglected to connect a ground. After this was remedied the next biggest problem was that my robot was jittering, sweeping for a value. I found that the issue that caused this was the statement: 

  if (RCTime(rightInside) > color && RCTime(leftInside) > color && RCTime(leftOutside) < color && RCTime(rightOutside) < color)  //goes straight
     {
        forward();
     }

Which was later remedied and works as such,

  if (RCTime(rightInside) > color || RCTime(leftInside) > color && RCTime(leftOutside) < color && RCTime(rightOutside) < color)  //goes straight
     {
        forward();
     }

in the program above. After this, the robot was able to complete the course with realistic reliability, however it would still sometimes go off course. The irregularity of its path, I then found, was caused by it wiggling the paper out of the sensors' reading area. This problem, however, cannot be corrected outside of reinforcing the paper. 


No comments:

Post a Comment