View Single Post
  #10   Spotlight this post!  
Unread 25-07-2006, 13:21
Matt Krass's Avatar
Matt Krass Matt Krass is offline
"Old" and Cranky. Get off my lawn!
AKA: Dark Ages
FRC #0263 (Sachem Aftershock)
Team Role: Mentor
 
Join Date: Oct 2002
Rookie Year: 2002
Location: Long Island, NY
Posts: 1,187
Matt Krass has a reputation beyond reputeMatt Krass has a reputation beyond reputeMatt Krass has a reputation beyond reputeMatt Krass has a reputation beyond reputeMatt Krass has a reputation beyond reputeMatt Krass has a reputation beyond reputeMatt Krass has a reputation beyond reputeMatt Krass has a reputation beyond reputeMatt Krass has a reputation beyond reputeMatt Krass has a reputation beyond reputeMatt Krass has a reputation beyond repute
Send a message via AIM to Matt Krass
Re: Sample PID code???

Quote:
Originally Posted by EHaskins
Thanks I'll try that, but I have one more question. How do you send a pointer to a function? Do you place a & before the variable name like the code below?
Code:
Getdata(&rxdata);
Putdata(&txdata);
That is the "addressof" operator, it passes the memory address of the variable in question, stick that in an empty pointer and now you have a pointer to that variable.

I recommend using one struct to hold the PID gains, static error variables, and output, and just pass a pointer to the structure when you call your function. This allows you to have multiple PID "objects" which you can then pull the data from it later on for whatever you need it for.

Also, you might consider storing the gains in two unsigned chars each, one as a numerator and a denominator. In doing so you can store fractional math operations in 16 bits instead of 32 (or is it 64 on the PIC?) bit floating point math, and do it much faster

An example:
Code:
unsigned float p_gain = 0.5;
unsigned char p_gain_num = 1;
unsigned char p_gain_den = 2;
signed int p_out = 0;

p_out = magical_p_error_global * p_gain; //Integer math, will round down to 0
                                           //making this useless with any non
                                           //integer gains.

p_out = (float)magical_p_error_global * p_gain; //This is slow and memory
                                           //wasting, not good.

p_out = magical_p_error_global * p_gain_num / p_gain_den; //This is good
In the last example, the error is multiplied up, and then divided down, avoiding floating point math operations but still accomplishing the same as multiplying by 0.5. Also it avoids situations where improper promotion (Such as using integer point over floating point math) can cause rounding down to 0 all the time.

Another example, with an error of 10:

10 * 0.5 = 5
10 * 1 / 2 =
(10) / 2 = 5

See? Same thing!

Using multiplication and division of integer numbers is easier on memory and processing time as the PIC doesn't have any hardware support for floating point math.

This isn't perfect, any decimals on the final result will still be truncated, but in our situations this is hardly noticeable. If it's really that important, I suggest learning about fixed point math, its a compromise between my method and "true" floating point.

I'll look over your function when I have some more time and see if I can recommend any improvements besides using a data structure.
__________________
Matt Krass
If I suggest something to try and fix a problem, and you don't understand what I mean, please PM me!

I'm a FIRST relic of sorts, I remember when we used PBASIC and we got CH Flightsticks in the KoP. In my day we didn't have motorized carts, we pushed our robots uphill, both ways! (Houston 2003!)