View Single Post
  #12   Spotlight this post!  
Unread 07-02-2007, 02:20
AndrewN's Avatar
AndrewN AndrewN is offline
it's alive!
AKA: Andrew Nicholson
FRC #1778 (Chill Out)
Team Role: Mentor
 
Join Date: Jan 2007
Rookie Year: 2006
Location: Edmonds, WA
Posts: 48
AndrewN is just really niceAndrewN is just really niceAndrewN is just really niceAndrewN is just really niceAndrewN is just really nice
Re: Bizarre Driving Issue

p2_x and deadx are (unsigned char), a single byte, and can only hold the values 0 to 255.

unsigned char p2_x;
unsigned char deadx;

We all use them to hold PWM values where 127 is neutral, 255 full forward, 0 full reverse.

For an example set p2_x to be 50, a value less than the 122 that you are having problems with. The code looks like:
deadx = ((p2_x - 122) * 127)/122 + 127;

Now subtract the 122: p2_x = p2_x - 122; /* or p2_x -= 122; or (p2_x-122) */

What's the value of p2_x, it's not -72 like we wanted it's instead now 184. The math overflowed the range of values, the result became 256-72 instead. Think of it as
wrapping around, instead of going from 2, 1, 0, -1, it goes 2, 1, 0, 255, 254, 253 ...

That's the first problem, now imagine we do the multiplication, it's going to wrap around many times and come to rest somewhere unexpected, (n*127 mod 256). Then division will only return 0, 1, 2 and that's all folks.

So how do you fix it? Take care of the typecasting to a (signed int) that is 2 bytes wide
and can be both positive and negative, once you have finished the scaling calculation, cast the result back to an (unsigned char)
deadx = (unsigned char) (( ((int)p2_x - 122) * 127 )/122 + 127 );

C always does math using the widest type (most number of bytes) of the two values.

Aside: The last cast to (unsigned char) is actually unnecessary as we are assigning it
to an unsigned char variable and C will do the typecast for us. However by including the typecast we are making clear our intent and it'll help remind us what is going on.

Short answer: the problem with negative values occurs because all numbers must have a positive result with (unsigned char) or it overflows. The problem with some +ve numbers happens because the result of the *127 won't fit in a single byte. Casting to (int) will fix those problems.

However, the other comments about how to handle a deadzone are correct too., there may still be other problems.

Note: The code that reverses the motors (127-pwm) could be simplifed if you just reverse the motor connection to the victors, of one of the motor pairs. It'll also help getting matched speeds as the speeds 127+n and 127-n are not necessarily the same.

Don't forget that the victors also have a deadband around 127 too.
Happy coding