Hi, I’m from 98709C in and we are trying to use a PID Loop to program our inertial sensor for our autonomous programs. The code works great for driving forwards however, when we use a negative value to drive backwards, it just turns in circles or does some other random thing. We also can’t get it to turn towards the left, and this is super important because our previous programs all rely on turning to the left. Here is of my PID Loop code with a little bit of our autonomous underneath all of it, it basically repeats after a while. Thanks for the help!
#include “vex.h”
using namespace vex;
//Tuning Constants for Distance
double kP = 2.0;
double kI = 0.0;
double kD = 3.6;
//Tuning Constants for Turn
double turnkP = 1.7;
double turnkI = 0.0;
double turnkD = 0.465;
//Establish a Maximum Power; Avoid Going Too Fast
double voltageThreshhold = 8;
//Establish Variables Used in Control Loop
int desiredValue = 0;
int turnDesiredValue = 0;
int error;
int prevError = 0;
int derivative;
int totalError = 0;
int turnError;
int turnPrevError = 0;
int turnDerivative;
int turnTotalError = 0;
//Allows You to Reset Your Loop
bool resetDriveSensors = false;
//Allows You to Turn Off PID Control in Driver Control
bool enableDrivePID = true;
int drivePID()
{
while(enableDrivePID)
{
if(resetDriveSensors)
{
resetDriveSensors = false;
BackLeft.setPosition(0,degrees);
BackRight.setPosition(0,degrees);
Inertial.setHeading(0,degrees);
}
int leftMotorPosition = BackLeft.position(degrees);
int rightMotorPosition = BackRight.position(degrees);
////////////////////////////////////////////////////
//Drive PID
////////////////////////////////////////////////////
int averagePosition = (leftMotorPosition + rightMotorPosition)/2;
error = desiredValue - averagePosition;
derivative = error - prevError;
totalError = totalError + error;
double motorPower = (error * kP + derivative * kD + totalError * kI)/12.0;
if (fabs(motorPower) > voltageThreshhold)
{
motorPower = voltageThreshhold;
}
///////////////////////////////////////////////////
//Turn PID
///////////////////////////////////////////////////
//int turnDifference = leftMotorPosition - rightMotorPosition;
//turnError = turnDesiredValue - turnDifference;
turnError = turnDesiredValue - Inertial.heading(degrees);
turnDerivative = turnError - turnPrevError;
turnTotalError = turnTotalError + turnError;
double turnMotorPower = (turnError * turnkP + turnDerivative * turnkD + turnTotalError * turnkI)/12.0;
if (fabs(turnMotorPower) > voltageThreshhold)
{
turnMotorPower = voltageThreshhold;
}
///////////////////////////////////////////////////
//Motor Commands
///////////////////////////////////////////////////
double powerScaler = 1.0;
double leftMotorPower = powerScaler * (motorPower + turnMotorPower);
double rightMotorPower = powerScaler * (motorPower - turnMotorPower);
FrontLeft.spin(forward, leftMotorPower, voltageUnits::volt);
FrontRight.spin(forward, rightMotorPower, voltageUnits::volt);
BackLeft.spin(forward, leftMotorPower, voltageUnits::volt);
BackRight.spin(forward, rightMotorPower, voltageUnits::volt);
prevError = error;
turnPrevError = turnError;
vex::task::sleep(20);
}
return 1;
}
int InertialReading()
{
while(true)
{
Brain.Screen.clearLine(1,color::black);
Brain.Screen.print(“Inertial Heading: %f”, Inertial.heading(degrees));
}
}
//////////////////////////////////////////auton starts here/////////////////////////////////////////////////////////
int main()
{
// Initializing Robot Configuration. DO NOT REMOVE!
int fastspeed=100;
int slowspeed=50;
int encoders=0;
int speed=90;
// Initializing Robot Configuration. DO NOT REMOVE!
vexcodeInit();
Inertial.calibrate();
while(Inertial.isCalibrating())
{
wait(100,msec);
}
TopRoller.spin(fwd,fastspeed,vex::velocityUnits::pct); //shooting preload into goal in middle against wall
wait(700,msec);
BottomRoller.spin(fwd,fastspeed,vex::velocityUnits::pct);
TopRoller.spin(fwd,fastspeed,vex::velocityUnits::pct);
vex::task::sleep(2000);
vex::task runDrivePID(drivePID);
vex::task InertialReadingTask(InertialReading);
resetDriveSensors = true;
desiredValue = 1000;
turnDesiredValue= 0;
vex::task::sleep(3000);
resetDriveSensors = true;
desiredValue = 0;
turnDesiredValue= 180;
vex::task::sleep(3000);