View unanswered posts | View active topics It is currently Fri Oct 19, 2018 7:36 am

 Page 1 of 1 [ 11 posts ]
 Print view Previous topic | Next topic
PID Line Follower
Author Message
Rookie

Joined: Tue Nov 09, 2010 4:42 pm
Posts: 12
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 ) 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

{
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
Expert

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

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
Rookie

Joined: Tue Nov 09, 2010 4:42 pm
Posts: 12
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;

{
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
Expert

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

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
Rookie

Joined: Tue Nov 09, 2010 4:42 pm
Posts: 12
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
Expert

Joined: Mon Oct 06, 2008 6:30 pm
Posts: 176
Location: Netherlands
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
Rookie

Joined: Tue Nov 09, 2010 4:42 pm
Posts: 12
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;

{
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
Expert

Joined: Mon Oct 06, 2008 6:30 pm
Posts: 176
Location: Netherlands
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
Rookie

Joined: Tue Nov 09, 2010 4:42 pm
Posts: 12
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
Rookie

Joined: Thu Dec 08, 2011 12:13 pm
Posts: 10
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

Mon Dec 12, 2011 5:36 am

Joined: Wed Mar 05, 2008 8:14 am
Posts: 3654
Location: Rotterdam, The Netherlands
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.

- 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
Display posts from previous:  Sort by
 Page 1 of 1 [ 11 posts ]

#### Who is online

Users browsing this forum: No registered users and 2 guests

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

Search for:
 Jump to:  Select a forum ------------------ ROBOTC Applications    ROBOTC for LEGO MINDSTORMS       Third-party sensors    ROBOTC for CORTEX & PIC    ROBOTC for VEX IQ    ROBOTC for Arduino    Robot Virtual Worlds    Multi-Robot Communications    Issues and Bugs Competitions & Partners    Mini Urban Challenge    CS2N Robot Virtual Worlds Competitions       VEX Skyrise Competition 2014-2015       VEX Toss Up 2013-2014       FTC Block Party! 2013-2014    Competitions using VEX - BEST, TSA, VEX, and RoboFest!    FTC Programming    RoboCup Junior and Other ROBOT Competitions Virtual Brick Robotics Discussions    General Discussions    Project Discussions Off-Topic ROBOTC Forum & ROBOTC.net Suggestions/Feedback    ROBOTC Forums Suggestions/Comments    ROBOTC.net Suggestions/Comments       NXT Programming: Tips for Beginning with ROBOTC       VEX Programming: Tips for Beginning with ROBOTC    2013 Robotics Summer Of Learning       VEX Toss Up Programming Challenge       FTC Ring It Up! Programming Challenge    International Forums       Spanish Forums          ROBOTC for MINDSTORMS          ROBOTC for VEX       French Forums          ROBOTC pour Mindstorms          ROBOTC pour IFI VEX       Japanese Forums （日本語のフォーラム）       German Forums    2015 Spring Carnival Event    PLTW (Project Lead The Way)    Robotics Merit Badge    2014 Robotics Academy Summer of Learning