The issue is with your exit condition: Once the inertial reading reaches the target value, it will exit the loop as the condition âinertial rotation >= targetâ is met. When this happens, the motor power will be set to whatever voltage the loop sets on the last iteration instead of zero, causing it to continue turning even though the loop have ended. The issue can be easily solved just by adding codes to set the motor power to 0 after the loop have exited.
However, there are also some other issues within your PID loop. First, Iâll strongly suggest changing all the pid variables (error, derivative etc.) into doubles as according to the vexcode API, .rotation() returns a double, which allows the loop to work with a wider range of values. Also, since you declared the PID variables to be global, be sure to initialize them to 0 at the beginning of each function so variables like integral will not infinitely increase every time you call turn. Personally however, I will simply declare the variables locally including the constants like the following, as there isnât a purpose for the variables to be declared globally, and will only increase the risk of naming collisions
void driver_tr(double target){
double kP = 0.2, kI = 0, kD = 0; // pid constants
double error = 69, derivative = 0, integral = 0, prevError = 0;
Inertial115.setRotation(0, degrees);
// the rest of the code
}
Another problem with your pid loop is with the exiting condition. One of the most important feature of a PID loop is its ability to correct itself even after overshooting. This is possible since the output reverses as the error changes sign. However in your loop, once the turn overshoots, the control loop will instantly end and itâll have no chance to autocorrect. To fix this, simply change the condition to:
std::fabs(error) < 0.1
This will allow the loop to continue to run permanently, until the error is small enough, meaning you are close enough to the target. Note that your error will need to be initialized to something that is larger than the deadband, or else the condition will be evaluated to true the moment you enter the loop an instantly exits. Alternatively, you can also use a do while loop to ensure that at least one iteration is done before the condition is checked.
Iâll also suggest writing a setPower() function which automatically sets the drive motor power based on the input. It will probably look something like this: (youâll have to modify it since I donât think vexcode can take in negative number of spin)
void setPower(double left, double right){
R1.spin(forward, right, voltageUnits::volt);
R2.spin(forward, right, voltageUnits::volt);
L1.spin(forward, left, voltageUnits::volt);
L2.spin(forward, left, voltageUnits::volt);
}
This will make the code a lot less repetitive since you can replace the four line you use to set motor power with just one line.
Also, just a slight question about the code: if youâre trying to turn, why is the motor power all set to the same value? Wouldnât that make the robot drive forward instead of turn?