Slow down teh motors!

Hi; How would I cap the maximum value of each PWM using 1 joystick configuration?

Basically when I hit the z trigger using the one joystick defualt code I want the controls to be less sensitive.

Thanks!

hint:

#define max_speed 200

if(motor_speed >= max_speed) motor_speed = max_speed;

The above limits the speed of a single direction. :slight_smile:

I would tack onto that a #define min_speed 55, just so you’re backwards movement has the sam limit (notice: the limit is in terms of power given to the motor, not directly its speed. We’re working with shaft encoders this year to code in speed.)

-Guy

Disclaimer: I’ve never done programming for a FIRST robot, although I have done it for other projects (including other robots) before.

The techniques described above would limit the maximum speed of the robot, but it sounds to me like you want a mode that would decrease the sensitivity of the controls at any range. I would take the PWM signal, subtract 127 (so the range is -127 to 127, not 0 to 255) and multiply that new number by a constant, say .5. I would then add 127 to this new value to get your new PWM signal. The robot will now be half as fast, and half as twitchy.

EDIT: I wasn’t thinking/typing clearly.

Shouldn’t that be a 127, to bring the scale back to 0-255?

Thats exactly what i was doing:
defualt code here

if (ztrigger pressed)
{
pwm13 = (pwm13-127)/2 + 127
pwm14 = (pwm14-127)/2 +127
and so on…

And this did not work. The robot went wild–if the joystick was shifted even slightly after ztrig was pressed robot would fly outta control.

You’re doing absolutely the right thing. However, that’s obviously not the code you actually tried (it won’t compile properly without semicolons). Post the exact lines of code and we can see if we can find the problem.

pwm13 = pwm14 = Limit_Mix(2000 + p1_y + p1_x - 127);
pwm15 = pwm16 = Limit_Mix(2000 + p1_y - p1_x + 127);

if (p1_sw_trig == 1)
{
pwm13 = (pwm13-127)/2+127;
pwm14 = (pwm14-127)/2+127;
pwm15 = (pwm15-127)/2+127;
pwm16 = (pwm16-127)/2+127;
}

I’d suggest a completely different method of reducing sensitivity, exponential control with a deadband. That way you don’t need to have your driver remember to press a switch, as well as not amplifying the area where joystick motion is not translated into robot motion (which dividing does). I made a long post about exponential control and how to implement it here.

Give this a try, and let me know if it works. (I don’t have a robot handy to test this on.)

pwm13 = pwm14 = Limit_Mix(2000 + p1_y + p1_x - 127);
pwm15 = pwm16 = Limit_Mix(2000 + p1_y - p1_x + 127);

if (p1_sw_trig == 1)
{
pwm13 = ((int)pwm13-127)/2+127;
pwm14 = ((int)pwm14-127)/2+127;
pwm15 = ((int)pwm15-127)/2+127;
pwm16 = ((int)pwm16-127)/2+127;
}

If my memory serves me right, all pwm values are usigned chars (which gives them the 0 - 255) range. If you subract 127 from anything less than 127, it is going to wrap around to 255 because it cant handle negative signs.

If I am right about the pwm variables all being unsigned chars, then your problem is subtracting the 127 from the value. The fix would to be create a temporary integer variable, give it the value of the pwm, do the math, and then reassign it.

int temp13 = pwm13;
int temp14 = pwm14;
int temp15 = pwm15;
int temp16 = pwm16;
if (p1_sw_trig == 1)
{
pwm13 = (temp13-127)/2+127;
pwm14 = (temp14-127)/2+127;
pwm15 = (temp15-127)/2+127;
pwm16 = (temp16-127)/2+127;
}

Also, as posted above, you could just cast it to an int.

I’m so excited…something I can respond to.

We had the same problem with our robot. I doesn’t give you the same variability as the other methods but it let us drive the robot.
Our driver motors are pwm01 and 02. The values that you set them for are the actual speed that you end up going. You are basically partitioning different areas of joystick placement to different output voltages (speed). Be carefull how you order each statement since its an if else if statement and it checks stuff in order that you put it in. You will also notice that the minimum amount of joystick movement before the robot actually moves is 27
going backward and 18 going forward. That way there was a little bit of dead stick in the middle since the sticks were too sensitive at the start. You can add more else if statements to put in more drive speeds. You could make the extreme ends ( 0 and 254) to actually go 0 and 254 (100% forward and backward).

if (p1_y < 50) //back fast
{
pwm01 = 120; //ange these values to the actual speed you want
pwm02 = 120; //“speed” is how far forward and backward you go
}
else if (p1_y < 100) // back slow

{
pwm01 = 123;
pwm02 = 123;
}

else if (p1_y >200) //forward fast
{
pwm01 = 155;
pwm02 = 155;
}

else if (p1_y > 155)//forward slow
{
pwm01 = 145;
pwm02 = 145;
}

else //stop and idle
{
pwm01=127; //left motor
pwm02=127; //right motor
}

Joey probably has it right. The pwm values are unsigned char, and it’s likely that the compiler isn’t accounting for the possibility of underflow when subtracting 127. If your joystick puts out 125, the result wraps around to 254, which gets divided down to 127 and shifted back up to 254 by the final addition. Forward control on the joystick will work okay, but the slightest backward movement will cause the robot to go full speed forward. Using 1-stick control, barely moving the joystick to either side will make it circle madly in the opposite direction.

Adding the cast to (int) will force the compiler to deal properly with the signed values, and everything should be okay.

MrE: your code will not allow me to make use of all the joystick intervals.

Thanks for the help. Alan, that was exactly what was happening with 1 joystick control. Barely moving the joystick caused the bot to circle wildly.

I shall try this when I get home.

You are right, you loose the variability that the other solutions give, but if you want to use this to drive the robot, the different speeds that the robot goes, it works well. You can always add more speeds to your robot. When we put the code in the robot, it saved our walls from too eager drivers driving too fast. I didn’t notice the difference very much when I put the code.

Thanks for the support. I seem to remember smashing a mentor into the tool cabinet a couple years back because any input value less than 127 would send the output to 0, and thus sent the robot into full reverse as soon as I touched the joystick. I’m pretty sure that was the quick-and-dirty way of fixing it. Good luck, brennerator.

We tried the same thing with the same results last year…

Thats when we learned why the FIRST code always added 2000 calucations then subtracted it from the final result in their mix limit. It prevented sign and overflow issues.

Another project for you to consider is to ramp the motor commands to the new speed when your driver slams the stick from one direction to the other.(or pushed the button). With 26 Ms between pwm updates your motor could be commanded to go full forward at one update and then full backwards at the next up date. Your poor drive train won’t last to long doing that.

Good Luck
BC

I did this a couple of days ago. here’s the jist of it:

if (buttonpressed)
motorspeed = transmission
else
motorspeed = joystickinput

transmission(){
speed -= 127;
speed /= divider;
speed +=127;
}

p.s. you’ll have to modify this to make it work with your robot, but this should help you. Also, in binary, division is better than multiplication for using the transmission.

{edit}
you can have the motors running through the transmission normally, and have when the buttonpressed equals transmission bypass. Have fun playing around with it.
{/edit}

A dead zone is a very good idea for your input controls. If you establish this zone in the input from 125-129 on each input it helps, keeps from jerking the drive back and forth. Test if the input is in the zone and if true set the value to 127, if not then the input value would be used as Full_Speed. Now set scaled values for speeds such as ½ by using the value of Full_Speed. Therefore: Half_Speed = 127 - ( 127 - Full_Speed ) / 2. You would need to do this for each side/motor. If you wanted ¼ speed just divide by 4 instead of 2 and so on. Now test for the inputs of the triggers and set the output to the desired value either the Full_Speed or Half_Speed results. This has been tested and works, hope it helps. Remember you can test for either trigger or even both to form an “AND” so you can have multiple speeds. :cool:

If using the Vector 884 speed controllers, these already have a built-in deadband from 117-137.

http://www.ifirobotics.com/victor-884-speed-controller-robots.shtml