|
|
|
![]() |
|
|||||||
|
||||||||
![]() |
|
|
Thread Tools |
Rating:
|
Display Modes |
|
|
|
#1
|
||||
|
||||
|
PID Control Loop Assistance
Greetings, all.
My team has requested that we programmers code an automated lift this year, because of the fine control required to consistently pick up totes during a match. We decided to use a PID control loop, since it would help us hone in on the positions we want on the lift, and consistently reach those positions. However, once the lift reaches that spot, I have it cut off, to prevent it from oscillating back and forth around the spot. Unfortunately, this has a side effect of having the lift fall down under the weight of the totes. Is there a way to fix this, code-wise? Finally, I personally have been wrestling with automation and PID control for all 4 years of my time on the team, and I still have trouble implementing it. I understand (most) of the logic behind it, but I am only somewhat familiar with the calculus behind it, and any help in actually writing a PID loop into a program would be incredibly useful. For reference: We code in C++. The lift uses one Talon SR speed controller. The PID loop receives input from a 10-turn potentiometer, and outputs to the motor. Code:
Talon *lifter = new Talon(6); //lift motor
AnalogPotentiometer *pot = new AnalogPotentiometer(0, 360, 0); //potentiometer
PIDController *autolift = new PIDController(0,1, 0.001, 0.0, pot, lifter); //PID controller
void LiftParameters() //sets parameters for the lift PID control loop
{
autolift->SetAbsoluteTolerance(0.5);
autolift->SetOutputRange(0.4, -0.4);
autolift->SetSetpoint(325.0);
}
void PLift() //PID control loop for automating the lift
{
if(rstick->GetRawButton(1))
{
PID = true;
autolift->SetOutputRange(0.4, -0.4);
autolift->Enable();
autolift->SetSetpoint(325.0); //ground level
//lift = true;
}
else if(rstick->GetRawButton(2))
{
PID = true;
autolift->SetOutputRange(0.4, -0.4);
autolift->Enable();
autolift->SetSetpoint(234.0); //1st position
}
else if(rstick->GetRawButton(3))
{
PID = true;
autolift->SetOutputRange(0.4, -0.4);
autolift->Enable();
autolift->SetSetpoint(300.0); //second position
}
else if(rstick->GetRawButton(4))
{
PID = true;
autolift->SetOutputRange(0.4, -0.4);
autolift->Enable();
autolift->SetSetpoint(340.0); //third position
}
if(autolift->OnTarget())
{
autolift->Disable();
autolift->SetOutputRange(0.25, -0.25);
PID = false;
}
if(rstick->GetRawButton(9))
{
autolift->Disable();
PID = false;
}
}
|
|
#2
|
||||
|
||||
|
Re: PID Control Loop Assistance
You have to leave the PID enabled. You need to tune it by adjusting the three gains so that it settles into place. In the past, we have used three analog inputs (scaled of course) to adjust the gains. We cranked the knobs until it worked as well as it could, and then read the values and put them into code. Looks like you have 0 for Kp, definitely need Kp. Ki is probably too large. You can set Kd to 0 to start.
The proportional gain should get it close. If its too high, then it will oscillate around the set point. Once its close, the integral gain kicks in and will slowly increase the power to the motor to counteract gravity and hold it in place. A word of caution - Cim motors holding like that will get hot. You cant do that forever. Depending on the mechanics of your system, you might get away with it for a match and then it will have to cool down. The best solution is to have enough gearing (work drive, etc), so that the lifter will stay in place with the motor off. |
|
#3
|
|||||
|
|||||
|
Re: PID Control Loop Assistance
Second best is a brake that you engage when you reach the set point, then disable the PID.
|
|
#4
|
||||
|
||||
|
Re: PID Control Loop Assistance
That does make sense. I see why my P was so low--I meant to add a period, and instead put a comma. But thanks to both of you for your assistance. Hopefully there will be time to tune it before competition.
|
![]() |
| Thread Tools | |
| Display Modes | Rate This Thread |
|
|