I’m not sure if this PID works properly, mainly because I changed it from a task to a void function. My question is
- Will my PID will work if I call the function in auton? (cuz i improvised from the connor 1814D video)
- Would a PID task be better than just a void function?
- I know I made a mistake in exiting the while loop, so any fixes to that?
- The drive and turn variables are inside the loop, making them non-global. Would that cause the code to lag since it is recreating the variables every time I run the function instead of just replacing the value that is stored?
Heres my code:
//PID Settings (when testing constants, make a table of all the numbers tried)
double kP = 0.0; //distance from current to desired; error
double kI = 0.0; //increase precision for steady state error accumluated over time
double kD = 0.0; //speed up or slow down depending on how close you are to the desired position
double turnkP = 0.0;
double turnkI = 0.0;
double turnkD = 0.0;
double threshold = 0.5;
double turnThreshold = 0.5;
//PID Loop
void doPID(int distance, int angle) {
leftDrive.setPosition(0, degrees); //Resets encoders so the robot makes desired position the current position so it doesn't keep going back
rightDrive.setPosition(0, degrees); //if not, then the degrees on the encoders will be affected by the previous turns, messing up the new desired positions
//Drive
int currentPosition;
int desiredPosition = distance;
int error;
int previousError = 0;
int totalError = 0;
int derivative;
//Turn
int currentTurnPosition;
int desiredTurnPosition = angle;
int turnError;
int turnPreviousError = 0;
int turnTotalError = 0;
int turnDerivative;
while(true) {
int leftPosition = leftDrive.position(degrees);
int rightPosition = rightDrive.position(degrees);
//Proportional
currentPosition = (leftPosition + rightPosition)/2; //average position in degrees of both sides of drivetrain
error = currentPosition - desiredPosition;
//Derivative
derivative = error - previousError; // basically change in distance over change in time
//Integral
totalError = totalError + error; //sums up all the tiny errors over time(the space left over or underestimated from LRAM/RRAM) and takes that into account
//Total
double drivePower = (error * kP) + (derivative * kD) + (totalError * kI);
//Turn Proportional
currentTurnPosition = leftPosition - rightPosition;
turnError = currentTurnPosition - desiredTurnPosition;
//Turn Derivative
turnDerivative = turnError - turnPreviousError;
//Turn Integral
turnTotalError = turnTotalError + turnError;
//Turn Total
double turnPower = (turnError * turnkP) + (turnDerivative * turnkD) + (turnTotalError * turnkI);
//Execute
leftDrive.spin(forward, drivePower + turnPower, voltageUnits::volt);
rightDrive.spin(forward, drivePower - turnPower, voltageUnits::volt);
previousError = error;
turnPreviousError = turnError;
vex::task::sleep(20); //20 milliseconds
if(abs(error) < threshold && abs(turnError) < turnThreshold) { //if the error is less than a specific measurement, break the loop or else the pid will keep trying to correct itself
break;
}
}
}
//--------------------------------------------------------------------//
void preAutonomous(void) {
// actions to do when the program starts
Brain.Screen.clearScreen();
Brain.Screen.print("pre auton code");
wait(1, seconds);
}
void autonomous(void) {
Brain.Screen.clearScreen();
Brain.Screen.print("autonomous code");
// place automonous code here
// 1 mat = 2 feet
// positive degrees = turn left
doPID(360, 0);
wait(1, sec);
doPID(0, 90);
wait(1, sec);
doPID(360, 0);
wait(1, sec);
}
You can also ignore the comments and the fact that I still need to test constants. And as context, treat the auton code as if I am trying to make the robot go forward one tile and then turn left 90 degrees and then go forward one more tile. So like what would go wrong if you used my current code and tried to do the context situation.
Thanks.