Motor Ramp Up/Ramp Down Function

As many of you know, our robot runs on brecoflex belts. We have always been fine in the past, but this year we are experiencing some problems with stretching the steel fibers that hold the belts together. We have broken 2 belts already, and at $150 a pop, are trying to do everything possible to not break any more.

We have watched videos of the belts breaking and have traced the problem back to accelerating to full speed from a stop. We are running an open loop control system, so if the driver mashes the joystick to its maximum, the motor is going to go from a dead stop to full voltage in a very short amount of time. When this happens, we believe an excess amount of torque is being applied to the belt, and causing it to break.

We have also decided the easiest way to save our belts (and our battery too!) is to have our motor’s PWM output ramp up and down when joystick input values are changing rapidly. So far, I have thought of 2 plausible ideas on how to solve this problem, and would like to see which one would work better, or if other teams have solved the problem in a different way.

Choice 1: Velocity based PI Control
Intuition tells me I can accomplish what I want by setting the proportional gain very small and setting the integral gain somewhat high. As the error between the input (joystick) and output (wheel speed) changes, the low p term will cause the output signal to change slowly. As time elapses, the Integral stage will pick up on the accumulated error due to the low P gain, and increase the output signal exponentially. I tried simulating in LabVIEW, but I didn’t get the results I expected. Can someone tell me why?

Here is an image explaining what I want compared to what LabVIEW spit back at me.

Choice 2: Write a custom function
I would need to look at the difference in input values across program loops (delta input). If this value is small, leave motor outputs directly mapped to that input. If the change in input values over time is higher than a pre defined limit, keep the old output value and add or subtract a certain amount of values until the wanted output speed is achieved. It may look something like this…

static int capture_value, output, mode, oldInput;

//rate of change in joystick values.
delta = input - oldInput;

//is joystick being moved too fast?
if(delta >= DELTA_LIMIT) { 
	mode=RAMPING_UP; 
	capture_value = input;
}else if(delta <= -DELTA_LIMIT) { 
	mode=RAMPING_DOWN; 
	capture_value = input;
} 

//output integration
switch(mode){
	case RAMPING_UP: 
		output+= RAMP_UP_CONSTANT;
		if(output >= capture_value) { mode = NORMAL; }
		break;
		
	case RAMPING_DOWN:
		output-= RAMP_DOWN_CONSTANT;
		if(output <= capture_value) { mode = NORMAL; }
		break;
		
	case NORMAL:
		output = input;
		break;
	case default: break;
}

Motor = output;

//Keep values for next loop
oldInput = input;

What do you think? Which one of these solutions is better fit for my cause? Do you have something that will work better, or that you have used in the past?

I personally favor the second solution, the custom function, as it’s simpler to understand exactly what is happening and controlling the ramping. Another way to limit the acceleration is to implement a moving average filter. This might be simpler to program.

Do you already have a transfer function between the joystick input and the PWM output to the motor to account for the nonlinearity in the Victor response? If not, this would reduce some of the operator heavy handedness but they could still jerk things around.

Depending on the performance you’re looking for, the ramping is probably more important at low speeds than higher but would complicate the programming to implement.

you only need like 3 variables in a function: target(the joystick value), output value(the current pwm value), rate(the rate of change).

if((target - output) > rate)
output += rate;
if((output - target) > rate)
output -= rate;
else
output = output;

this is just to explain how to do it.
Make sure all the variable being compared in the if statement are int. Otherwise it will execute for example if it results as (-5 > 4), if they are unsinged variables.

just write a function and you can use it anywhere.

#2 is what our team has used for the past two years; from experience I say it works fairly well. We designed the function so that we currently run all our motors through this algorithm; just with different delta limits depending on how fast it needs to run and what it is operating. The only problem we’ve run into with it is that it is rather annoying to have the drive motors stop more than a second after you center the joystick; we fixed it by just increasing the allowed delta, but the function could be customized more so it allows you to slow down faster than you are allowed to speed up.

Our team has no experience with PIDs, so I’m not sure how well our ramping function would compare with the first design.

I am not sure if this is what the functions above are doing, but you could find the difference between the joystick and pwm values, divide that number by a constant, and apply that to the pwm value. This operates similar to KW’s tracking.c code.

Just make sure differences can be signed, and watch out for overflow due to rounding.

BTW, what labview app is that?

Thanks in advance,
Robinson

ripping of belt.

this is a big problem with a lot of power. if you hit anything and come to a stop. you will rip your belts. if you turn while someone is pushing you, you will rip belts. I can not see you ripping your belt on just a quick power up. the torque you are getting to go full speed should not be enough to rip your tracks. there is no resistance to rip the track. unless you have the belts too tight. for a 150lb robot to go forward should be very easy for tracks.

Make sure you have the strong belts from Breco Flex. those belts run about $340 a pop. they will give you about twice the torque. Even with those belt we have ripped them. But none have been because of the joystick going full power.

We have some of those tracks if you would like to try them out. with different backing. I am pretty sure it is the same length you are using now.

e-mail me or pm me and we will see if we can hook you up.

If it works, I’d go with the KISS solution.

Team 237’s ramp:
MOTOR += ( (signed char) (JOYSTICK - MOTOR) / RAMP_CONSTANT);

Our current RAMP_CONSTANT is 8, tune to your liking.

Another option could be a FIR low pass filter. Easy to code and highly configurable

An integrator like the one mike mentions above works well too. I have used the integrator approach on an electric wheelchair and it worked well.

What Tom meant to say was , flooring the sticks from a stop when we are on the angle from the ramp to the flat top, is when/where we stretch our tracks.

Just a tip: whatever ramping function you use, make sure it is getting called at even intervals. In autonomous, cycles are much, much faster than the 26.2ish millisecond user mode cycles, and the same function will give you different results in autonomous, where it is getting called much more quickly than user mode. I didn’t think this through all the way before re-coding my autonomous, and rendered our ramping functions useless. OOPS!

I am currently working on a timer-based ramping function that will filter everything going to the motors instead of only being used in auton. We’ll see how that works out…

JBot

I use a look up table to ramp my motors up and down. It’s pretty clean and allows easy software gear changing.

Here’s how I’d do it:


//In user_routines.h, just an example value
#define ramp_speed 3 

//In user_routines.c
if(pwm01 > (p1_y+ramp_speed))
{
     pwm01 += ramp_speed;
}
else if (pwm01 < (p1_y-ramp_speed))
{
     pwm01 -= ramp_speed;
}
else
{
     pwm01 = p1_y;
}

(replacing p1_y with the value you ultimately want the pwm to have, and pwm01 with the actual port connected to the motor)
(similar to what was posted earlier I believe)

Although it might seem too simple this should work fine; taking into account the rate of change seems unnecessary to me because the ramping should/will only have a difference when the rate of change is large.

So despite this being a rather old thread, I’ll add an important comment for any future readers of this thread.

Using the I term in a PID controller is a monumentally stupid way to do this. I will now explain why this is, and why the results were not what your inuition lead you to expect. Integral control is slow. You’ve noted this yourself, but failled to appreciate the consequences. As the error remains and is integrated, you build up a rather large number to add to your command. Unfortunately, this number is still there when the error reaches zero, it won’t go away until the system errs on the other side for a while. Of course then it starts adding up in the other direction… So, mostly, you should never depend on integral control to get you most of the way to where you want to go, just use a small amount of it to take care of any errors that are left from your P term. In fact, though, increasing your I term like you did would simply increase the input from your I term by a heck of a lot. That is, it would make your robot accelerate a whole lot after a small delay.

If you were set on using the PID control for this, you’d actually just want to increase your D gain. The D term adds damping and slows down the response of the system, which is presumably what you’re looking for.