Problem with implementing anti-wheelspin delay in PID loop - RESPONSE NEEDED QUICK!

Hello, I am trying to implement a delay in my PID loop so that I don’t do a burnout on the start of the program. I seem to have a problem with it though, as it does not slow down as it is supposed to with my “time code”. Here is the code. Any ideas?

#pragma region VEXcode Generated Robot Configuration
// Make sure all required headers are included.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <math.h>
#include <string.h>


#include "vex.h"

using namespace vex;

// Brain should be defined by default
brain Brain;


// START V5 MACROS
#define waitUntil(condition)                                                   \
  do {                                                                         \
    wait(5, msec);                                                             \
  } while (!(condition))

#define repeat(iterations)                                                     \
  for (int iterator = 0; iterator < iterations; iterator++)
// END V5 MACROS


// Robot configuration code.
motor Motor1 = motor(PORT1, ratio18_1, false);

motor Motor2 = motor(PORT2, ratio18_1, true);

sonar RangeFinderA = sonar(Brain.ThreeWirePort.A);


#pragma endregion VEXcode Generated Robot Configuration

#include "vex.h"
using namespace vex;

// A global instance of competition
competition Competition;

void usercontrol(void) {
  // User control code here, inside the loop
  while (1) {
Brain.Screen.clearScreen();  
 
    // display the ultrasonic distance in in on the screen
    Brain.Screen.printAt(1, 40, "distance: %f in", RangeFinderA.distance(distanceUnits::in));


//Ints
  int Target = 24;
  int TotalError = 0;
  int PreventError = 0;
  int Derivative;
//Double
//double kP = .25;
//double kI = .5;
//double kD = .01;

//double kP = .40;
//double kI = .10;
//double kD = .10;
//Zero osolation, .27 of target(19);
double kP;
double kI = .10;
double kD = .10;
int timer;

  
if (timer<10) {
  timer++;
  kP = 0.000001;
  kI = .0001;
  kD = .00001;
  wait(1,seconds);
}
else {
  kP = .40; 
}

double RangeValue = RangeFinderA.distance(inches); 
 
  int Error;
//Potential Error
  Error = RangeValue - Target ;
//Derivative
Derivative = Error - PreventError;

//integral
TotalError += Error;

//defines motor power
  double motorPower = Error * kP + Derivative * kI + TotalError * kD;

  Motor1.spin(reverse, motorPower, volt);
  Motor2.spin(reverse, motorPower, volt);


    PreventError = Error;
wait(20, msec); // Sleep the task for a short amount of time to
                    // prevent wasted resources.
  }
}

int main() {
  // Set up callbacks for driver control period
  Competition.drivercontrol(usercontrol);

  // Prevent main from exiting with an infinite loop.
  while (true) {
    wait(100, msec);
  }
}

Some initial pointers, since I’m just on my phone right now:

  1. Move your variables to be the first things inside your usercontrol function. Putting them inside the while() loop may potentially cause them to be redeclared each time, causing unknown behavior (not terribly likely, but if you don’t 100% know the compiler behavior, move it to the start of the function).

  2. Initialize ALL of your variables, even if it’s just zero. See my previous statement about the compiler.

Start with those two and see if that changes anything.

6 Likes

Thank you so much for the pointers. Would I also declare the timer code before the while loop?

If by ‘timer code’ you mean the ‘if’ check, that should be in the while loop.

PID is in general not a good solution to “driving a fixed distance” problem. Perhaps in your case, it’s not really a fixed distance, since you measure the remaining distance from an object (that could be moving).

Anyway, what are you trying to achieve is an initial ramp-up of the driving speed. You do that by setting ridiculously low kP (which could as well be zero), thus likely relying on windup of the error integral (TotalError * kD, which is wrong naming, integral coefficient is nominally called kI) to actually provide a growing voltage command over time. This should, in theory and when well tuned, behave as a ramp up, but at the end of the ramp, you’re left with large residual integral (PID “wound up”, likely causing significant overshoot of the target in your algorithm).

I would implement a very different strategy, apply an acceleration limit to the command regardless of what the PID says (you’d still need to limit the windup).

3 Likes

I pressume the issue is the there is two much power to the wheels intially. This could be solved by capping the motorpower inside the timer statement instead of changing the varibles. (This is the same as the previously mentioned acceleration cap).
Otherwise this might be solved by upping the timer cut off, upping the derivative term or using a high derivative as a signal for slippage instead of time.

1 Like