View unanswered posts | View active topics It is currently Wed Jul 30, 2014 11:25 pm






Reply to topic  [ 11 posts ] 
PID Line Follower 
Author Message
Rookie

Joined: Tue Nov 09, 2010 4:42 pm
Posts: 12
Post PID Line Follower
Greetings!

I'm attempting to put together a simple PID line following program. Of course I've got no experience with RobotC and minimal programming in C. I've done some searching on the web (hence my customized line folowing program :lol: ) and still can't get a good grasp of the PID control program portion.The issue I'm having is that I need to be able to manipulate the P, I, and D variables. I found this in the forums, viewtopic.php?f=1&t=1430 but it's quite complicated... is there an easy way to simplify it?

The embedded PID control in RobotC

nMotorPIDSpeedCtrl[motorA] = mtrSpeedReg;

does not allow for variable manipulation. I also looked into the debug windows and the PID section under the NXT device was apparently put in for testing and not user input.

This is what I have so far:

const tSensors lightSensor = (tSensors) S1; //sensorLightActive

task main()
{
while(true) //an infinite while loop is declared with"true" as its condition
{
if(SensorValue(lightSensor) < 45) //if the lightsensor reads a value less than 45 the if code will be run
{
motor[motorA] = 75; //motor A is run at a 75 power level
motor[motorB] = 0; //motor B is stopped with a 0 power level
}

else //if the lightsensor reads a value greater than or equal to 45 the the else's code will be run
{
motor[motorA] = 0; //motor A is stopped with a 0 power level
motor[motorB] = 75; //motor B is run at a 75 power level
}
}
}

I'm not interested in getting the robot to stop or do anything else at the moment. The students just need to see how changing the P, I, and D variables affect the movement of the robot.

Thanks!


Tue Nov 09, 2010 5:45 pm
Profile
Expert
User avatar

Joined: Mon Oct 06, 2008 6:30 pm
Posts: 176
Location: Netherlands
Post Re: PID Line Follower
Hi,

This link might be useful.
The program you point to seems overcomplicated, a PID control can be coded in 10 lines. Here is an example put together from memory (not tested, no warranty).
Code:
While(true){
  Float p, I, d, kp=1, ki=1, kd=1,, lasterror, black=1023, remember=.9;
  p=black-sensorValue[lightsensor]; // change to your needs;
  I=remember*I+p;
  D=p-lasterror;
  Lasterror=p;
  Correction=kp*p+ki*I+kd*d;
  Motor[motorA]=correction; //change to your needs;
  Wait1msec(20);
}


The k values should be tuned. Memory helps "forgetting" past errors.

Ps My iPhone has randomly capitalized some letters in the code, this will give compiler warnings.

_________________
My most recent blog: A grain of sugar


Wed Nov 10, 2010 3:28 am
Profile WWW
Rookie

Joined: Tue Nov 09, 2010 4:42 pm
Posts: 12
Post Re: PID Line Follower
That was helpful! So I tried putting together what I could figure out... do I need to duplicate the PID code for the else statement at the bottom? or will all the movement be taken care of in the if statement?

const tSensors lightSensor = (tSensors) S1; //sensorLightActive
float Kp = 1000.0; // REMEMBER we are using Kp*100 so this is really 10 !
float Ki = 100; // REMEMBER we are using Ki*100 so this is really 1 !
float Kd = 10000.0; // REMEMBER we are using Kd*100 so this is really 100!
float offset = 45.0; // Initialize the variables
float Tp = 50.0;
float error = 0.0;
float Turn = 0.0;
float integral = 0.0; // the place where we will store our integral
float lastError = 0.0; // the place where we will store the last error value
float derivative = 0.0; // the place where we will store the derivative
float powerA = 0.0;
float powerB = 0.0;

task main()
{
while(true) //an infinite while loop is declared with"true" as its condition
{
if(SensorValue(lightSensor) < 45) //if the lightsensor reads a value less than 45 the if code will be run
{
error = SensorValue(lightSensor) – offset; // calculate the error by subtracting the offset
integral = integral + error; // calculate the integral
derivative = error – lastError; // calculate the derivative
Turn = Kp*error + Ki*integral + Kd*derivative; // the "P term" the "I term" and the "D term"
Turn = Turn/100; // REMEMBER to undo the affect of the factor of 100 in Kp, Ki and Kd!
powerA = Tp + Turn; // the power level for the A motor
powerB = Tp – Turn; // the power level for the B motor
motor[motorA] = powerA; // moves motor A
motor[motorB] = powerB; //moves motor B
lastError = error; // save the current error so it can be the lastError next time around
}

else //if the lightsensor reads a value greater than or equal to 45 the the else's code will be run
{
motor[motorA] = 0; //motor A is stopped with a 0 power level
motor[motorB] = 75; //motor B is run at a 75 power level
}
}
}


Wed Nov 10, 2010 11:15 am
Profile
Expert
User avatar

Joined: Mon Oct 06, 2008 6:30 pm
Posts: 176
Location: Netherlands
Post Re: PID Line Follower
Hi,

Your on your way!

The article you based your code on assumes that only integers can be used, like in NXT-G 1.x.
Robotc however does have floating point values. So you don't need the trick of multiplying and deviding values by 100. I would suggest removing this from your code to make it more clear. You will have to change the variables from int to float then.

About the else statement. This deals with the situation where the line follower is right on the black line. 45 is the threshold for pure black. The code shuts down the PID controller in this case and holds one motor to make it turn away from the black line. When it is of the black line again it reactivates the controller again. Basicly you have a controller to go left and hard coded values to go right.

A better solution would be not to aim for pure black but to aim for a value between black and white. Your robot would the try to drive right over the edge of the black line. The controller can then be used to correct for deveations to the left and to the right and there would no longer be the need to shut it off.

_________________
My most recent blog: A grain of sugar


Wed Nov 10, 2010 1:22 pm
Profile WWW
Rookie

Joined: Tue Nov 09, 2010 4:42 pm
Posts: 12
Post Re: PID Line Follower
So to do that I could delete the else statement and change the sensor value from 45 to say, 30?


Thu Nov 11, 2010 8:35 am
Profile
Expert
User avatar

Joined: Mon Oct 06, 2008 6:30 pm
Posts: 176
Location: Netherlands
Post Re: PID Line Follower
To do so you need to get rid off both the if and the else statement. Keep the code within the if statement and delete the code within the else statement.
The value of offset should be the mean of the sensor value corresponding to white and the sensor value corresponding to black.

_________________
My most recent blog: A grain of sugar


Thu Nov 11, 2010 3:59 pm
Profile WWW
Rookie

Joined: Tue Nov 09, 2010 4:42 pm
Posts: 12
Post Re: PID Line Follower
10 and 28 are the light and dark readings, so the offset value will be 19.

const tSensors lightSensor = (tSensors) S1; //sensorLightActive
float Kp = 100.0;
float Ki = 10;
float Kd = 1000.0;
float offset = 45.0; // Initialize the variables
float Tp = 50.0;
float error = 0.0;
float Turn = 0.0;
float integral = 0.0; // the place where we will store our integral
float lastError = 0.0; // the place where we will store the last error value
float derivative = 0.0; // the place where we will store the derivative
float powerA = 0.0;
float powerB = 0.0;

task main()
{
while(true) //an infinite while loop is declared with"true" as its condition
{
if(SensorValue(lightSensor) < 19) //if the lightsensor reads a value less than 19 the if code will be run
{
error = SensorValue(lightSensor) – offset; // calculate the error by subtracting the offset
integral = integral + error; // calculate the integral
derivative = error – lastError; // calculate the derivative
Turn = Kp*error + Ki*integral + Kd*derivative; // the "P term" the "I term" and the "D term"
powerA = Tp + Turn; // the power level for the A motor
powerB = Tp – Turn; // the power level for the B motor
motor[motorA] = powerA; // moves motor A
motor[motorB] = powerB; //moves motor B
lastError = error; // save the current error so it can be the lastError next time around
}


}
}


Sofar, the robot spins in a circle...?


Tue Nov 16, 2010 2:54 pm
Profile
Expert
User avatar

Joined: Mon Oct 06, 2008 6:30 pm
Posts: 176
Location: Netherlands
Post Re: PID Line Follower
Hi,

Remove this line: if(SensorValue(lightSensor) < 19) //if the lightsensor reads a value less than 19 the if code will be run

Now your code will always run. The error should be able to get a negative value. Dropping this code can make that happen. A positive error will cause a correction to one side, negative error will cause a correction in the opposite direction. You need that as well.

The spinning could well be caused by a correction to the wrong side (left instead of right). Changing the sign of the error will correct this.
There could be other causes as well. Look very carefully at the motors behavior, try to analyze what they do and what they should do. Then look at the code and try to find out why they do want they do.

For initial tests you could set the I and P to zero. The Pid will be less accurate but more predictable.

Also, to calculate the error you still use the variable offset, this still has the value of 45, where it should be 19.

One last tip. Display the error on screen with nxtDisplaytextline(1,"error: %d", error);

_________________
My most recent blog: A grain of sugar


Tue Nov 16, 2010 8:37 pm
Profile WWW
Rookie

Joined: Tue Nov 09, 2010 4:42 pm
Posts: 12
Post Re: PID Line Follower
If I wanted to display or keep track of offshoot, settling time, or overshoot quantitatively, how would I do that? is there a simple display function for that? Something that I could measure and compare to what the robot calculates.


Tue Nov 16, 2010 11:32 pm
Profile
Rookie

Joined: Thu Dec 08, 2011 12:13 pm
Posts: 10
Post Re: PID Line Follower
I am new in robotics.I want to create a PID line follower but it iss not workig out.On the verge of givin up plz help!!written a program which is enclosed :cry:


Attachments:
jata1.txt [5.23 KiB]
Downloaded 284 times
Mon Dec 12, 2011 5:36 am
Profile
Moderator
Moderator
User avatar

Joined: Wed Mar 05, 2008 8:14 am
Posts: 3165
Location: Rotterdam, The Netherlands
Post Re: PID Line Follower
Why are you posting code for an AVR processor on a ROBOTC forum? I think you'll much better luck on an AVR forum.

Also, please don't post the same thing on multiple threads.

- Xander

_________________
| Professional Conduit of Reasonableness
| (Title bestowed upon on the 8th day of November, 2013)
| My Blog: I'd Rather Be Building Robots
| ROBOTC 3rd Party Driver Suite: [Project Page]


Mon Dec 12, 2011 10:25 am
Profile WWW
Display posts from previous:  Sort by  
Reply to topic   [ 11 posts ] 

Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  



Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.