Scaling Values in the Control Program

Posted by Nate Smith.

Other on team #66, GM Powertrain/Willow Run HS, from Eastern Michigan University and GM Powertrain.

Posted on 3/15/2000 10:06 AM MST

Does anybody out there have a foolproof way to scale down values in the control program? Whenever i try it, using different scaling constants for forward and reverse(scaling joystick inputs), I always seem to lose part of the range completely. Help!

Nate

Posted by Joe Johnson.   [PICTURE: SAME | NEW | HELP]

Engineer on team #47, Chief Delphi, from Pontiac Central High School and Delphi Automotive Systems.

Posted on 3/15/2000 10:39 AM MST

In Reply to: Scaling Values in the Control Program posted by Nate Smith on 3/15/2000 10:06 AM MST:

Nate,

Please explain more what you are trying to do and what happens when you try doing it.

It is not clear what ‘scale down’ means. It is equally unclear what ‘lose part of the range completely’ means.

More details will mean better help.

Joe J.

Posted by Nate Smith.

Other on team #66, GM Powertrain/Willow Run HS, from Eastern Michigan University and GM Powertrain.

Posted on 3/15/2000 6:09 PM MST

In Reply to: please explain more… posted by Joe Johnson on 3/15/2000 10:39 AM MST:

: Nate,

: Please explain more what you are trying to do and what happens when you try doing it.

: It is not clear what ‘scale down’ means. It is equally unclear what ‘lose part of the range completely’ means.

: More details will mean better help.

: Joe J.

For those of you who have seen our machine in action, you know about our hook delivery arm for grabbing onto the bar. The extension and positioning functions of that arm are controlled by the X and Y axes of the joystick on port 3. The positioning function was judged to be too quick by our drive team at EMU, so we want to scale the joystick value for that axis down 50% before outputting it to the speed controller.

As for losing part of our range, when I attempted to scale down the drive train output to 50% of the joystick value in order to create our ‘turbo boost’ function, using the code shown below:
(for forward)
p1_yfilt = (p1_yfilt)/2 min 128 max 254
(for reverse)
p1_yfilt = (p1_yfilt*3)/2 min 0 max 126

in one direction, i would lose all output unless the ‘turbo’ function was on, and in the other, it would always act as if the turbo was turned on.

Looking at mike’s code, that might work…will have to try it and see what happens…

Nate

Posted by Jerry Eckert.

Engineer from Looking for a team in Raleigh, NC sponsored by .

Posted on 3/15/2000 8:48 PM MST

In Reply to: Re: please explain more… posted by Nate Smith on 3/15/2000 6:09 PM MST:

: As for losing part of our range, when I attempted to scale down the drive train output to 50% of the joystick value in order to create our ‘turbo boost’ function, using the code shown below:
: (for forward)
: p1_yfilt = (p1_yfilt)/2 min 128 max 254
: (for reverse)
: p1_yfilt = (p1_yfilt*3)/2 min 0 max 126

: in one direction, i would lose all output unless the ‘turbo’ function was on, and in the other, it would always act as if the turbo was turned on.

I don’t have the PBASIC manual handy, but it looks like the problem might be that the precedence of min/max is higher than division. In other words, I suspect PBASIC evaluated your statements as:

p1_yfilt = (p1_yfilt)/(2 min 128 max 254), and
p1_yfilt = (p1_yfilt*3)/(2 min 0 max 126)

Try rewriting them as follows:

p1_yfilt = (p1_yfilt/2) min 128 max 254, and
p1_yfilt = ((p1_yfilt*3)/2) min 0 max 126

Jerry

Posted by Jerry Eckert.

Engineer from Looking for a team in Raleigh, NC sponsored by .

Posted on 3/15/2000 9:43 PM MST

In Reply to: Re: please explain more… posted by Jerry Eckert on 3/15/2000 8:48 PM MST:

:
: : As for losing part of our range, when I attempted to scale down the drive train output to 50% of the joystick value in order to create our ‘turbo boost’ function, using the code shown below:
: : (for forward)
: : p1_yfilt = (p1_yfilt)/2 min 128 max 254
: : (for reverse)
: : p1_yfilt = (p1_yfilt*3)/2 min 0 max 126

: : in one direction, i would lose all output unless the ‘turbo’ function was on, and in the other, it would always act as if the turbo was turned on.

: I don’t have the PBASIC manual handy, but it looks like the problem might be that the precedence of min/max is higher than division. In other words, I suspect PBASIC evaluated your statements as:

: p1_yfilt = (p1_yfilt)/(2 min 128 max 254), and
: p1_yfilt = (p1_yfilt*3)/(2 min 0 max 126)

: Try rewriting them as follows:

: p1_yfilt = (p1_yfilt/2) min 128 max 254, and
: p1_yfilt = ((p1_yfilt*3)/2) min 0 max 126

Let me try this again… (I should know better than to try to do this stuff when I’ve been sitting in front of a computer for 48+ hours. :frowning: )

The min/max precedence MAY be the problem; if it isn’t, the scaling formulas are also wrong.

In forward: (.le. = less than/equal; .ge. = greater than/equal)

Before scaling, 128 .ge. p1_yfilt .le. 254
64 .ge. p1_yfilt/2 .le. 127

Therefore, regardless of the input value, the scaled p1_yfilt will be forced to 128 (no output) by the MIN.

Reverse:

Before scaling: 0 .ge. p1_yfilt .le 126
0 .ge. p1_yfilt*3/2 .le. 189

For reverse you should get some output, but the stick range is going to be heavily biased towards neutral output after the MIN/MAX are applied.

I’d do something like this (please excuse any syntax errors - it’s been a year since I’ve programmed PBASIC):

LOOKDOWN p1_yfilt, (lt)[127,128,255],index (’(lt)’ is less than sign)
BRANCH index,[rev,neutral,fwd]
REV:
p1_yfilt = (126-((126-p1_yfilt)/2)) min 0 max 126
goto common
NEUTRAL:
p1_yfilt = 127
goto common
FWD:
p1_yfilt = (128+((p1_yfilt-128)/2)) min 128 max 254
COMMON:

If the LOOKUP function will accept formulas in the value list, all of the above starting at the BRANCH can be replaced by:

LOOKUP index,((126-((126-p1_yfilt)/2)) min 0 max 126), 127, ((128+((p1_yfilt-128)/2)) min 128 max 254)]

If you want a dead zone around the neutral joystick position, replace the LOOKDOWN with:

LOOKDOWN p1_yfilt,(lt)[127-dead_size, 128+dead_size, 255]

: Jerry

Posted by Jerry Eckert.

Engineer from Looking for a team in Raleigh, NC sponsored by .

Posted on 3/15/2000 10:13 PM MST

In Reply to: Re: please explain more… - Expanded Response posted by Jerry Eckert on 3/15/2000 9:43 PM MST:

In my previous reply I used two formulas to scale the joystick input: one for forward and one for reverse. This can also be accomplished with a single formula:

p1_yfilt = ((p1_yfilt/n) + (127-(127/n))) min 0 max 254

where ‘n’ is the scale factor (e.g., ‘2’ for 1/2 speed; ‘3’ for 1/3 speed, etc.)

: :
: : : As for losing part of our range, when I attempted to scale down the drive train output to 50% of the joystick value in order to create our ‘turbo boost’ function, using the code shown below:
: : : (for forward)
: : : p1_yfilt = (p1_yfilt)/2 min 128 max 254
: : : (for reverse)
: : : p1_yfilt = (p1_yfilt*3)/2 min 0 max 126

: : : in one direction, i would lose all output unless the ‘turbo’ function was on, and in the other, it would always act as if the turbo was turned on.

: : I don’t have the PBASIC manual handy, but it looks like the problem might be that the precedence of min/max is higher than division. In other words, I suspect PBASIC evaluated your statements as:

: : p1_yfilt = (p1_yfilt)/(2 min 128 max 254), and
: : p1_yfilt = (p1_yfilt*3)/(2 min 0 max 126)

: : Try rewriting them as follows:

: : p1_yfilt = (p1_yfilt/2) min 128 max 254, and
: : p1_yfilt = ((p1_yfilt*3)/2) min 0 max 126

: Let me try this again… (I should know better than to try to do this stuff when I’ve been sitting in front of a computer for 48+ hours. :frowning: )

: The min/max precedence MAY be the problem; if it isn’t, the scaling formulas are also wrong.

: In forward: (.le. = less than/equal; .ge. = greater than/equal)

: Before scaling, 128 .ge. p1_yfilt .le. 254
: 64 .ge. p1_yfilt/2 .le. 127

: Therefore, regardless of the input value, the scaled p1_yfilt will be forced to 128 (no output) by the MIN.

: Reverse:

: Before scaling: 0 .ge. p1_yfilt .le 126
: 0 .ge. p1_yfilt*3/2 .le. 189

: For reverse you should get some output, but the stick range is going to be heavily biased towards neutral output after the MIN/MAX are applied.

: I’d do something like this (please excuse any syntax errors - it’s been a year since I’ve programmed PBASIC):

: LOOKDOWN p1_yfilt, (lt)[127,128,255],index (’(lt)’ is less than sign)
: BRANCH index,[rev,neutral,fwd]
: REV:
: p1_yfilt = (126-((126-p1_yfilt)/2)) min 0 max 126
: goto common
: NEUTRAL:
: p1_yfilt = 127
: goto common
: FWD:
: p1_yfilt = (128+((p1_yfilt-128)/2)) min 128 max 254
: COMMON:

: If the LOOKUP function will accept formulas in the value list, all of the above starting at the BRANCH can be replaced by:

: LOOKUP index,((126-((126-p1_yfilt)/2)) min 0 max 126), 127, ((128+((p1_yfilt-128)/2)) min 128 max 254)]

: If you want a dead zone around the neutral joystick position, replace the LOOKDOWN with:

: LOOKDOWN p1_yfilt,(lt)[127-dead_size, 128+dead_size, 255]

: : Jerry

Posted by Mike Gray.

Engineer on team HOT from Huron Valley Schools sponsored by GM Milford Proving Ground.

Posted on 3/16/2000 7:27 AM MST

In Reply to: Re: please explain more… posted by Nate Smith on 3/15/2000 6:09 PM MST:

Nate,

I think I understand now. Your code looks fine, it just doesn’t have an offset, but you don’t necessarily need it. I think that what is happening, is that we are assuming that ‘forward’ ranges from 127 to 255 counts.

If we assume the reverse (inverse?), that reverse ranges from 127 to zero, the result is pretty much what you described. FORWARD is clamped at 128 counts, it never gets lower so the member never moves.

For reverse: Assume that the filtered joystick value ranges from 127 to 255. You multiply by 3 and divide by 2, then clamp at 126, so the member never moves…UNTIL the joystick exceeds 170 counts. Since p1_yfilt is a single byte, it rolls over beyond 255 counts and its value then becomes 0. Full speed, turbo, wrong direction.

Floating point math: 171*3/2=256.5

Integer math: 171*3/2=0

Ain’t integer math a pain? Could this be what’s happening? The solution is a rewrite, or invert the variable before operating on it. Its the asymmetry that’s causing some confusion. If you were to scale symmetrically, you likely would not have a problem until you clamp the value.

I see that you filter p1_y. Are you using my code from the Innovation First white paper page? Do you find that it improves your motion control, or is it detrimental?

: As for losing part of our range, when I attempted to scale down the drive train output to 50% of the

joystick value in order to create our ‘turbo boost’ function, using the code shown below:
: (for forward)
: p1_yfilt = (p1_yfilt)/2 min 128 max 254
: (for reverse)
: p1_yfilt = (p1_yfilt*3)/2 min 0 max 126

: in one direction, i would lose all output unless the ‘turbo’ function was on, and in the other, it would always act as if the turbo was turned on.

: Looking at mike’s code, that might work…will have to try it and see what happens…

: Nate

Posted by Nate Smith.

Other on team #66, GM Powertrain/Willow Run HS, from Eastern Michigan University and GM Powertrain.

Posted on 3/16/2000 7:42 AM MST

In Reply to: Here’s a theory… posted by Mike Gray on 3/16/2000 7:27 AM MST:

: I see that you filter p1_y. Are you using my code from the Innovation First white paper page? Do you find that it improves your motion control, or is it detrimental?

I’m using the code from the white paper, and running both our x and y axes for port 1 through it. Seems to help, however, since we were more interested in keeping it running during EMU, I didn’t have much of an opportunity to adjust the coefficients. That’s going to be one of my tasks in Chicago, and I have also implemented 75% scaling down on our x-axis, to allow for more control when steering. Keep an eye on us in Chicago to find out if it all works together OK…

Posted by Jerry Eckert.

Engineer from Looking for a team in Raleigh, NC sponsored by .

Posted on 3/16/2000 8:26 AM MST

In Reply to: Here’s a theory… posted by Mike Gray on 3/16/2000 7:27 AM MST:

: For reverse: Assume that the filtered joystick value ranges from 127 to 255. You multiply by 3 and divide by 2, then clamp at 126, so the member never moves…UNTIL the joystick exceeds 170 counts. Since p1_yfilt is a single byte, it rolls over beyond 255 counts and its value then becomes 0. Full speed, turbo, wrong direction.

: Floating point math: 171*3/2=256.5

: Integer math: 171*3/2=0

Computations are performed using a 16-bit scratchpad and truncated, if necessary, when the final result is stored. In the example above, evaluation of the expression yields a result of 256. The MAX function then clamps the value at 126 before it is stored in the 8-bit destination.

Posted by Mike Gray.

Engineer on team HOT from Huron Valley Schools sponsored by GM Milford Proving Ground.

Posted on 3/16/2000 9:12 AM MST

In Reply to: Re: Here’s a theory… posted by Jerry Eckert on 3/16/2000 8:26 AM MST:

Yup, you’re right, the MAX function operates on the 16 bit number. So the problem is back to simple scaling.

The slope is where Nate wants it, all his equation needs is an intercept. The biggest p1_yfilt can ever be is 256. Divide it by 2 and you have no motion (128 counts). its clamped at 128 too. Add 64, and the motor runs.

Posted by Jerry Eckert.

Engineer from Looking for a team in Raleigh, NC sponsored by .

Posted on 3/16/2000 9:31 AM MST

In Reply to: Then its simple… posted by Mike Gray on 3/16/2000 9:12 AM MST:

:
: Yup, you’re right, the MAX function operates on the 16 bit number. So the problem is back to simple scaling.

: The slope is where Nate wants it, all his equation needs is an intercept. The biggest p1_yfilt can ever be is 256. Divide it by 2 and you have no motion (128 counts). its clamped at 128 too. Add 64, and the motor runs.

Correct.

In general, if you want to scale by a factor of n, divide the input by n then add (127-(127/n)) to adjust the intercept.

Posted by Mike Gray.

Engineer on team HOT from Huron Valley Schools sponsored by GM Milford Proving Ground.

Posted on 3/15/2000 11:08 AM MST

In Reply to: Scaling Values in the Control Program posted by Nate Smith on 3/15/2000 10:06 AM MST:

Nate:

Not sure exactly what you’re after, so I’ll discuss three methods:

  1. If you want to scale the joystick variable linearly, use slope and intercept.

                     Example:
    
                     p1_y=p1_y / 2 + 64
    

This example assumes that you want to scale the variable to half-scale. You must add
64 counts so that 127 counts still represents center-stick. If you want 1/4 speed, simply
divide by 4 and add 96.

  1. If you want to reduce the authority in one direction only, use the branch statement, and write a routine that scales the joystick variable (as above) only when the raw variable is in a particular range.

  2. If you just want to limit the reverse speed, simply clamp the joystick variable at some minimum or maximum value.

Example:

p1_y=p1_y min 50

This example assumes that zero counts is full reverse (depends upon motor polarity). Experiment with the minimum value. Use the MAX function if 255 counts is full reverse.

Example:

p1_y=p1_y max 200

You can combine these two techniques, scaling and clamping in the same line of code:

Example:

p1_y=p1_y / 2 + 64 min 32 max 160

If you are using a single joystick to control both traction motors, you will find it VERY beneficial to leave the y-axis alone, but scale the x-axis. You then have full authority fore-and-aft, but reduced authority when turning. Much more controllable.

When scaling, remember: power=I squared R. Its always best to optimize the mechanical features so that you make use of all the motor’s potential (times a safety factor) before making software tweaks.

Non-linear scaling is much more complex, and not recommended unless you have a rotating member working against gravity. If that is the case, take a look at SIN and COS functions. Hope some of this helps!

Mike Gray

: Does anybody out there have a foolproof way to scale down values in the control program? Whenever i try it, using different scaling constants for forward and reverse(scaling joystick inputs), I always seem to lose part of the range completely. Help!

: Nate

Posted by Dung Cao.

Engineer on team #397 from Flint Southwestern Academy and Delphi Automotive - E&C.

Posted on 3/16/2000 9:46 AM MST

In Reply to: Scaling Values in the Control Program posted by Nate Smith on 3/15/2000 10:06 AM MST:

Here are some formulas that I’ve been using to scale down the speed of the pwm. These should help you. I also have an excel spreadsheet with graphics to show the speed control. It really helps out to figure these scaling. If you need this spreadsheet, just email me at [email protected]

Speed limit algorithm
100% speed >>>>>> pwm = p_y
75% >>>>>> pwm = 31.75 + ((3/4) * p_y)
50% >>>>>> pwm = 63.50 + (p_y / 2)
33% >>>>>> pwm = 84.66 + (p_y / 3)
25% >>>>>> pwm = 95.25 + (p_y / 4)

Also here is the one-joystick control for x-y control.

'================== DRIVE for joytick 2 ====================================

’ This section modified the output of PWM1, and PWM 2 for control from one
’ joystick (Port 2).
’ Basic Stamp does not recognize negative numbers. Therefore, have to add 2000
’ to algorithm, then delete 2000 for the result
’ p2_y = Y-axis controls speed.
’ p2_x = X-axis turns.
’ pwm1 - Left motor.
’ pwm2 - Right motor.
'-----------------------------------------------------------------------------

If p2_sw_trig 1 then notturbo:
pwm1 = (((2000 + p2_y - p2_x + 127) Min 2000 Max 2254) - 2000)
pwm2 = (((2000 + p2_y + p2_x - 127) Min 2000 Max 2254) - 2000)
Goto NoChange:

notturbo:
If p2_sw_top 1 then regularspeed:
pwm1 = ((2000 + (p2_y/4) - (p2_x/4) + 127) Min 2095 Max 2159) - 2000
pwm2 = ((2000 + (p2_y/4) + (p2_x/4) + 63) Min 2095 Max 2159) - 2000
Goto NoChange:

regularspeed:
pwm1 = ((2000 + (p2_y/2) - (p2_x/2) + 127) Min 2064 Max 2190) - 2000
pwm2 = ((2000 + (p2_y/2) + (p2_x/2)) Min 2064 Max 2190) - 2000

: Does anybody out there have a foolproof way to scale down values in the control program? Whenever i try it, using different scaling constants for forward and reverse(scaling joystick inputs), I always seem to lose part of the range completely. Help!

: Nate

Posted by Nate Smith.

Other on team #66, GM Powertrain/Willow Run HS, from Eastern Michigan University and GM Powertrain.

Posted on 3/16/2000 12:55 PM MST

In Reply to: Scaling Values in the Control Program posted by Nate Smith on 3/15/2000 10:06 AM MST:

Thanks everybody for your help! I’ve got a whole list of different ways to try scaling the values to test out when we get to Chicago, and thanks to this, watch for improved control on the team 66 drive train and hook arm. See everybody there! (1 week left!)

Nate

Posted by Joe Johnson.   [PICTURE: SAME | NEW | HELP]

Engineer on team #47, Chief Delphi, from Pontiac Central High School and Delphi Automotive Systems.

Posted on 3/16/2000 2:32 PM MST

In Reply to: Thanks Everybody! posted by Nate Smith on 3/16/2000 12:55 PM MST:

Nate,

Look us up in Chicago if you have any troubles. Either Jeremy Husic (our PBASIC Prince) or myself should be able to help you.

Others who want some help can stop by as well.

Joe J.

Posted by Nate Smith.

Other on team #66, GM Powertrain/Willow Run HS, from Eastern Michigan University and GM Powertrain.

Posted on 3/16/2000 5:55 PM MST

In Reply to: look us up in Chicago… posted by Joe Johnson on 3/16/2000 2:32 PM MST:

: Nate,

: Look us up in Chicago if you have any troubles. Either Jeremy Husic (our PBASIC Prince) or myself should be able to help you.

: Others who want some help can stop by as well.

: Joe J.

Joe,
I might just have to do that anyway…you were on my list of people to find at EMU, but I never quite got around to it. Mike Martus tracked me down with the help of our head engineer, but I didn’t get a chance to look for you while I was around the pit. See you in Chicago!

Nate