Slowly accelerating motor speeds in autonomous

Hi I had a question about making gradually increasing motor speeds.

I would like to gradually increase the speed or power my motors run at for one of our robots for the college challenge.

The code I used previously:

 

void acclerator(int powerLevel, int time, float rate) 
{ 
    for(int i = 1; i < time; i+=10) 
    { 

        motor[left] = powerLevel; 
        motor[right] = powerLevel; 
        wait1Msec(time/i);
        powerLevel = powerLevel * rate + powerLevel; 
     }
}

This achieves the affect of running the motors, but it’s not gradually ramping the motors as I desired. What happens is after about a fraction of a second the motors jump to max speed and continue running. What’s a better way of having a progressive ramping of the motors?

Hi there,

Would you mind explaining how your code is supposed to work? I am unsure why you are multiplying by rate and then adding power level again, also should “time” be compared to a timer value or is it simply a placeholder for how many loops it should do? Some untested code to do something similar I wrote is here:

void accelerate(int maxPower, float rate)
{
	for(float powerLevel= 0, float speedChange = rate;  powerLevel < maxPower; )
	{
		speed += speedChange;
		motor[left] = powerLevel; 
                motor[right] = powerLevel; 
        }
}

This function adds the amount set in rate to the power level each time, and should have the effect I think you are after.

This is the code I use for acceleration however:


float speedChangePerLoop = 0.06;

float leftPower = 0, rightPower = 0;

void accelerateDrive(int leftTargetPower, int rightTargetPower)
{
	if(leftTargetPower < leftPower)
	{
		leftPower -= speedChangePerLoop;
	}
	else if(leftTargetPower > leftPower)
	{
		leftPower += speedChangePerLoop;
	}
	else{}
	
	if(rightTargetPower < rightPower)
	{
		rightPower -= speedChangePerLoop;
	}
	else if(rightTargetPower > rightPower)
	{
		rightPower += speedChangePerLoop;
	}
	else{}
	
}

This seems more versatile to me as the variables leftPower and rightPower can be used outside the function itself and the target value could be changed before it is called again, allowing you to read sensor values in between.

Both of these methods increase power with loops of the program rather than with time though, there is most probably far more effective solutions around.

1 Like

I am not a programmer (although I used to know RobotC), but here is what I would do and what we used in FLL.

Start with X motor power and power the motors with that. Then add a small amount to the motor, wait a short while, and repeat it. That would be looping while the motor power is less than desired level.

I can’t really figure out how your code is supposed to work?

How the code was supposed to work was increase the power level by a specified rate in a small time slot. It didn’t work as intended.

I do mine similar to how Jack explained his.

I start with having a speed set point and accelerate up to that speed by adding +1 count or -1 (in backwards) to a variable every time the loop went through. Every time the loop runs though, this -1 or +1 was added to a variable called “counter.” Then I simply set the motor speed to the variable “counter.”
This was too fast of acceleration so I changed the program to multiply a float (because the variable needs to be <1.0) variable by the “counter” and then just send that number to the motors.

Looking at your code I think you can figure this out without example code, but if you have any questions feel free to PM me if you’d like. Jack has a great example though and mine is similar to how his works.

This is basically what we use, with your original function added in. Note the differences in input types for “accelerator(a,b,c,d)”

int slew(int target, int curr, int rate) {
    int delta = target - curr;
    if (abs(delta) > rate) delta = rate*sgn(delta);
    return (curr + delta);
}

void accelerator(int targetLeft, int targetRight, int time, int rate) {
    rate = abs(rate); //Make sure it is positive
    for (int i = 1; i < time; i+=10) {
        motor[left] = slew(targetLeft, motor[left], rate); 
        motor[right] = slew(targetRight, motor[right], rate); 
        wait1Msec(time); //Do not divide by i, the delay should be constant
    }
}

Disclaimer: Untested.

What if you use a timer and establish a linear function between motor output and time? That’s something I always wanted to do but never got a chance to apply.

Do you mean just sending the time to the motor? What would a linear function have to do with that?

You cannot directly send the time to the motor. The motor goes maximally 127 while time goes 1000 for each second. For example, if you want your robot to accelerate from 0 to 127 in 5 secs, the function would be motor output= (127/5000)*time when time =<5000
Although this might be a more complicated method, which involves timer, i think you can get a completely smooth acceleration like this. And no offense, comparing to counter, i think this is more stylish…