Parking Brake Using a P Controller


#1

I’ve made a few attempts at creating a parking brake with a P controller before, but haven’t found much success yet, and I just finished another attempt at a parking brake. I just wanted to get some feedback on my code, so that I can get it right this time and hopefully use it at our next competition this Wednesday.

Here is the part in the main program that includes and starts the parking brake task.

// Global Variables
int setpoint;
bool brake = false;

// Included files
#include "Deadzone Drive.c";
#include "PID Parking Brake.c";

task usercontrol()
{
	while (true)
	{
		if (vexRT(Btn7D) == 1)
		{
			setpoint = SensorValue(rightEnc); // Sets current location as the target for PID
			startTask (pBrake);
			brake = !brake; // Toggles brake on
			wait1Msec(10); // Waits 10 miliseconds to prevent the toggle from switching off again before the button is released
		}

And here is my actual parking brake task.

#pragma systemFile

task pBrake()
{
	// Local Variables
	int kP = 0;
	int error;
	int power;

	while(brake == true)
	{
		error = setpoint - SensorValue(rightEnc); // Error is calculated
		power = abs(error)*kP; // Proportional component is implemented

		// Deadband is set since integral and derivative components are not implemented
		if(error > 20 || error < -20)
		{
			motor[frontRight] = power;
			motor[midRight] = power;
			motor[backRight] = power;
			motor[frontLeft] = power;
			motor[midLeft] = power;
			motor[backLeft] = power;
		}
		// Give other tasks some time to run
		wait1Msec(10);
	}
	stopTask(pBrake);
}

I do realize that the controller only calculates values for the right side of the drive, but assigns them to both sides. I wanted to get the right side perfect before copying it over to the left, so for now that is what I’m doing.


#2

You’re not going to get any help unless you tell us what’s wrong with it.


#3

I didn’t look too mych at your code, but I can share the code I used for my parking brake in a minute


#4

here you are, its probably not the best, but it did the job. I used a boolean named Brakes to keep track of whether or not the brakes are active, and an integer named BrakeTimer that I use to wait a little bit after I release the joysticks before activating the brakes to avoid jerky stops.

if(!(vexRT[Ch2] > 10 || vexRT[Ch2] < -10) && !(vexRT[Ch3] > 10 || vexRT[Ch3] < -10) && !Brakes){
			SensorValue[LeftEncoder] = 0;
			SensorValue[RightEncoder] = 0;
			BrakeTimer++;
			if(BrakeTimer > 500){
				Brakes = true;
			}
		}
		if((vexRT[Ch2] > 10 || vexRT[Ch2] < -10) && (vexRT[Ch3] > 10 || vexRT[Ch3] < -10)){
			BrakeTimer = 0;
			Brakes = false;
		}
		if(Brakes){
			motor[rightJoy] = (SensorValue[LeftEncoder]);
			motor[rightJoy2] = (SensorValue[LeftEncoder]);
			motor[leftJoy] = (SensorValue[RightEncoder]);
			motor[leftJoy2] = (SensorValue[RightEncoder]);
		}
		else{
			motor[leftJoy] = vexRT[Ch3];
			motor[leftJoy2] = vexRT[Ch3];
			motor[rightJoy] = -vexRT[Ch2];
			motor[rightJoy2] = -vexRT[Ch2];
		}

#5

One thing I like to do in debugging is to walk through my code and just make sure the logic works right. Let’s pretend our encoder value is 1000, and our setpoint is 0.

0 minus 1000 is -1000, so that seems good. And then we take the absolute value of that, which gives us positive 1000. We then multiply that by our kP value, which is 0. That makes our power 0. Well that’s no good. Despite us being far away from what our target, it doesn’t move. In fact, our power will always be zero. As anything times zero is zero. So that’s your primary problem.

Set kP to 1 and see how that affects things (identitive property of multiplication). If the robot is oscillating back and forth, slowly lower the value of kP. Some oscillation is fine if your not trying to be precise. If it is too slow (doesn’t oscillate and you want it to go faster), try increasing kP. If you want it to move faster but it oscillates too much to be useful, probably time for a full PID. You may find the wiki link for different methods of tuning PID controllers useful. It has a nice little animated graph and stuff.

Another problem is you are taking the absolute value of your error. This means your robot will only drive in one direction (which ever direction is positive) even if you fix your kP problem. If you miss your target its going to drive faster and faster away instead of reversing back to the target. If you just want to reverse the motor, multiply your power/error by -1 instead of using absolute value.

Also your deadband doesn’t have any condition if its inside the deadband. So if the motors get assigned something elsewhere in the program (say a drive program), it should be fine. But with the code you have provided it will always have the motors moving (as they never get turned off, kinda defeats the point of a deadzone). But when implemented with the rest of your code it will probably work fine.

Unrelated to the P-loop but I prefer grabbing the last value of the button instead of timers for button toggles. Example. I find it nicer to drive but thats just up to you and your drivers. You can also add a little timer so that you have to press it for X milliseconds before turning on too like Xenon did (only for a button instead of a deadband), which can prevent ghost inputs (idk if the cortex filters these out or not).

Good luck.


#6

Thank you, this feedback will help a ton. My P controller should work since its already implemented in a program with drive code, but yes it will only move one direction, so I’ll fix that. Also your example code for the toggle was great. Also thank you Xenon for your example code, I really like the brake timer idea.