Pages: [1]   Go Down
Author Topic: Arduino Line following robot using PID  (Read 2867 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 28
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I am trying to use PID algorithm in my line following robot and I don't know why but my robot isn't following the line. I am posting my code here to see if there's any problem. I sure enough that there no problem in my hardware.
Code:
/*
author: crocodile_009
date: 25/07/2013
my first code for autonomous line follower robot with arduino IDE
*/

#define rep(a,b,c) for(int a = b;a<c;a++)

int motor_left[] = {7,8} ;      // ledPin 7 and 8 for turning motor left
int motor_right[] = {2,3} ;    // ledPin 2 and 3 for turning motor right

int sensors[5] = {0, 1, 2, 3, 4} ;         // sensor arrays which are connected to 5 available analog pins
int sensor_reading = 0 ; // count active sensor
int sen[5] = {0};

double sensors_average = 0.00 ;
int right_speed, left_speed ;

double active_sensor = 0.00 ;
double total_sensor = 0.00 ;

double max_speed ;         // get from sensor

double sensors_sum = 0.00;
double position1 = 0.0;
double proportional = 0.00;
double integral = 0.00;
double derivative = 0.00;

double set_point = 4.5  ;         // need to assign value, on which path robot drives, manual ;

double last_proportional = 0.00;
double error_value = 0.00;

bool flag = true ;

/* need to assign value these three variables, at first start equiling with 0,
  tuning Kp first, we will try to set this value less than 10 ;
  when loses the line reduce Kp, if cannot navigate a turn increase Kp;
  after that try to tune Kd then Ki ;
*/

double Kp=72;
double Kd=5;
double Ki=0.00015;     

int light = 4;
/* program initialized */
void setup()
{
        Serial.begin(9600) ; // set up for serial port
        /* set up motors */
        pinMode(light, OUTPUT);
        rep(i,0,2)
        {
                pinMode(motor_left[i], OUTPUT) ;
                pinMode(motor_right[i], OUTPUT) ;
        }
}
/* loop starts */
void loop()
{
        digitalWrite(light, HIGH);
        sensors_read() ;        // Reads sensors values and computes sensors sum and weighted average
       
        PID_Calc() ;            // calculate PID values
        Calc_turn() ;           // select turn
        Motor_drive (right_speed, left_speed) ;        // drive motor
        /* More logics about Threshold tuning, PID tuning, counting gap will be updated later */
}
/* read sensors */
void sensors_read()
{
        total_sensor = 0;
        active_sensor = 0 ;
        sensors_average = 1 ;
        sensors_sum = 1 ;
        rep(i,0,5)
        {
                sensor_reading = analogRead(sensors[i]) ;
                //Serial.print(sensor_reading);
                //Serial.print(" ");
                //delay(1000);
                if(sensor_reading>33)
                { 
                        active_sensor += 1 ;
                        sen[i] = 1 ;
                }
                else
                {
                        sen[i] = 0 ;
                }
               
                //Serial.print(sen[i]);
                //Serial.print(" ");
                //delay(1000);
                //total_sensor = total_sensor + sensor_reading[i] * (i+1) ;// calculate the weighted mean of sensor's reading, 1000 means nothing
                total_sensor += ((i+1) * sen[i]); // calculate the weighted mean of sensor's reading,
                /* to debug */
                /*
                Serial.print(sensors_average);
                Serial.print(' ');
                Serial.print(sensors_sum);
                Serial.print(' ');
                Serial.print(position1);
                Serial.println();
                delay(2000) ;
                */
             
        }
       
        if(total_sensor == 0 && active_sensor == 0)
        {
            total_sensor = 1;
            active_sensor = 100000000;
        }
        sensors_average = total_sensor ;
        sensors_sum = active_sensor ;
        //position1 = sensors_average / sensors_sum;
        /*
        Serial.println();
        Serial.print(sensors_average);
        Serial.print(" ");
        Serial.print(sensors_sum);
        Serial.print(" ");
        Serial.print(position1);
        Serial.print(" ");
        delay(1000);
        */
       
}
/* PID algorithm */
void PID_Calc()
{
        /*
        Serial.print(position1);
        Serial.print(' ');
        Serial.print(set_point);
        Serial.print(' ');
        delay(1000);
        */
        position1 = sensors_average / sensors_sum ;
       
        last_proportional = proportional ;
       
        proportional = position1 - set_point ;
       
        integral = integral + proportional ;
       
        derivative = proportional - last_proportional ;
       
        /* calculate the formula */
        error_value = proportional*Kp + integral*Ki + derivative*Kd ;
       
        /*
        Serial.print(position1);
        Serial.print(' ');
        Serial.print(set_point);
        Serial.print(' ');
        Serial.print(error_value);
        Serial.print(' ');
        delay(1000);
        Serial.println();
        */
}
/* select turn */
void Calc_turn()
{
        /* restricting error value between +/- 256 , it can be any arbitary number depending on my choice */
        if(error_value < -256)
        {
                error_value = -256 ;
        }
        if(error_value > 256)
        {
                error_value = 256 ;
        }
        /* if error_value is less than zero calculate right turn value,
           actually PID is an inverse relationship between motor turning and error_value,
           we know analog pins were introduced from left to right in sensors arrays
           so, if error_values < 0 , bot must turn right as well as increase left_turn values
        */
        if(error_value < 0)
        {
                right_speed = max_speed + error_value ;
                left_speed = max_speed ;
        }
        if(error_value > 0)
        {
                left_speed = max_speed - error_value ;
                right_speed = max_speed ;
        }
}
/* drive motor */
void Motor_drive(int right_speed, int left_speed)
{
        /* based on the width of track, we will trace if difference is too small.
           we will run the bot direct, it may help to tune bot more finely,
           here we set the value 20.
        */
        if((right_speed - left_speed) < 20 || (left_speed - right_speed) < 20)
        {
                drive_forward() ;
        }
        else if(right_speed > left_speed)
        {
                drive_left() ;
        }
        else
        {
                drive_right() ;
        }
        delay(50) ;
}
/* drive logics */
void drive_forward()
{
        digitalWrite(motor_left[0], HIGH) ;
        digitalWrite(motor_left[1], LOW) ;
       
        digitalWrite(motor_right[0], HIGH) ;
        digitalWrite(motor_right[1], LOW) ;
}
void drive_left()
{
        digitalWrite(motor_left[0], HIGH) ;
        digitalWrite(motor_left[1], LOW) ;
       
        digitalWrite(motor_right[0], LOW) ;
        digitalWrite(motor_right[1], HIGH) ;
}
void drive_right()
{
        digitalWrite(motor_left[0], LOW) ;
        digitalWrite(motor_left[1], HIGH) ;
       
        digitalWrite(motor_right[0], HIGH) ;
        digitalWrite(motor_right[1], LOW) ;
}
« Last Edit: August 22, 2013, 03:16:00 pm by syd_xp » Logged

UK
Offline Offline
Shannon Member
****
Karma: 183
Posts: 11129
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

What is your hardware, and how is it connected to the Arduino?

Have you tested the hardware and connections, and if so - how?

Have you verified that your sketch accurately detects where it is relative to the line?

Have you verified that the technique you're using to move and steer the bot produces the effect you intend?
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 238
Posts: 24291
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

What does your serial debug output look like?
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Offline Offline
Newbie
*
Karma: 0
Posts: 28
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@AWOL my output looks like this upto the error value
position1  set_point   error_value
3.00        4.50         -93.00
3.00        4.50         -108.00
3.00        4.50         -108.00
3.00        4.50         -108.00
3.00        4.50         -108.00
3.00        4.50         -108.00

@PeterH
I am using arduino mega, IR sensor array L293D and 2 geared motors

I used the basic line following algorithm and its ok

well the 3rd and 4th ques is my problem.
I mean i think it doesn't try to follow the line it goes straight. So though it is taking reading from sensor but cant execute it in the movement of robot. Can you please explain it how to solved it smiley 
Logged

UK
Offline Offline
Shannon Member
****
Karma: 183
Posts: 11129
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

well the 3rd and 4th ques is my problem.

Perhaps one of them is. If you tried to answer them, it might get us closer to the solution.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Offline Offline
Newbie
*
Karma: 0
Posts: 28
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

First of all I an bit of confused with my error value.. I mean how to drive the DC motors using this error value i got.
Logged

UK
Offline Offline
Shannon Member
****
Karma: 183
Posts: 11129
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

First of all I an bit of confused with my error value.. I mean how to drive the DC motors using this error value i got.

You don't. The error is an input to the PID. You use the PID control output to drive the motor. But it seems premature to worry about that unless/until you know whether your line detection is giving you accurate input data, and that you're capable of driving the motors correctly based on the PID output.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi. you have made mistake in this. 
 if(error_value < -256)
        {
                error_value = -256 ;
        }
        if(error_value > 256)
        {
                error_value = 256 ;
        }


you can use this keyword 'constrain(error_value, -256,256);' instead of it. smiley
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 3
I am a science and robotics enthusiast and I love playing the guitar. Subsequently I have landed in RNS Institute of Technology, doing my 3rd year in Mechanical Engineering. I take interest in organising college events like fests and workshops, because li
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello!
I have made a tutorial on building an Arduino PID controlled line follower and have also explained how PID works in a simple manner. Follow this link:
http://samvrit.tk/tutorials/pid-control-arduino-line-follower-robot/
« Last Edit: December 06, 2013, 02:28:28 pm by samvrit » Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 238
Posts: 24291
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
you can use this keyword 'constrain
"constrain" is not a C keyword
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Pages: [1]   Go Up
Jump to: