PID Timing issue

My PID loop works perfectly except that it won’t ever stop… I am trying to make it just be able to work so that it will run the PID for a certain sensor value for a certain amount of time and then move on to the next sensor value for the next amount of time. My code is attached but I am not seeing the issue. Screen Shot 2017-11-25 at 9.43.20 PM.png

So the first thing you do is


while (true)

So the function will keep going forever…

I suggest, when I am close


int threshold = 50;
while(abs(error) > threshold || abs(previous_error) > threshold)

but of course if you actually want to go off time


clearTimer[T1];
while(time1[T1]<10000)

This is your issue:

PIDControl(1500); //Never goes past this line
wait1Msec(2000);
PIDControl(2500);

What the robot is trying to with this code is to run the PIDControl function, and then once it’s done, wait 2 seconds. But since the PIDControl function never actually exits out of the while loop, it never finishes, and the rest of your code never runs.

The best solution I could think of in your case is to change this PIDControl to be a task instead of a function. Since you’ll be using it multiple times throughout your program, it would be best to let the same control loop run throughout the entire program, and just change the desired value for the existing loop.

In making this a task instead of a function, your targetValue parameter must become a global variable, so that you can edit it outside of the loop itself.

Then, in your main function, you’d start the PIDControl task once, and let it run throughout the entire program, just changing the targetValue whenever you’d like:

#pragma config(Sensor, dgtl1, encoder, sensorQuadEncoder)
#pragma config(Motor, port2, arm,
tmotorVex393_MC29, openLoop)
//*!!Code automatically generated by 'ROBOTC' configuration
wizard !!*//

int targetValue;

task PIDControl ()
{
float Kp = 1.523443;
float Ki = 0.002582;
float Kd = 0.828143;
int error;
int integral;
int derivative;
int previousError;
int motorSpeed;
while (true)
{
error = (targetValue)-(SensorValue[encoder]);
integral = integral + error;
if (abs(error) > 50)
{
integral = 0;
}
if (error == 0)
{
integral = 0;
}
derivative = error - previousError;
previousError = error;
motorSpeed = (Kp*error) + (Ki*integral) +
(Kd*derivative);
motor[arm] = motorSpeed;
wait1Msec(20)
}
}
task main()
{
targetValue = 1500; //Sets the target value to 1500 for when the loop starts
startTask(PIDControl); //Starts the PIDControl task (which runs alongside the rest of this code, so you don't have to worry about whether or not it exits)
wait1Msec(2000);
targetValue = 2500; //After 2 seconds, change the target value of the loop to 2500
wait1Msec(3000);
}

I think this should be a decent basis for what you’re trying to do.

Thank you both!

hi, let’s see if this works.

oh it did.

I would be careful with the statement that resets your integral to 0 when your error == 0. Some people do this when using PID for wheel control, which is what they use to shut down the output. However, since you are moving an arm, you probably have an opposing force, such as weight, and the reason you got to 0 error is because of your integral, not your proportional. You will probably need to keep it. Otherwise, you may see it bounce at the setpoint as you 0 the integral, it creates an error, and the integral builds back up again.

@TriDragon Whoops, this is just an old template thing I made. My actual code is ridiculously long but the same idea. I forgot to take that bit out! Great eye!