![]() |
Re: Gyroscope Code
Quote:
-Kevin |
Re: Gyroscope Code
1 Attachment(s)
OK, will do! Thanks Kevin!
|
Re: Gyroscope Code
Quote:
-Kevin |
Re: Gyroscope Code
Quote:
|
Re: Gyroscope Code
Kevin,
No worries, we (actually Brian aka Devicenull) figured it out in another thread. The call to update the gyro is performed in Process_Data_From_Local_IO, which is not called during autonomous mode. I never knew that since I've been working with the EDU all this time and it does not seem to run that way. We had to move the update gyro function to the User_Autonomous_Code loop, and everything now works. Again, sorry to bug you with dumb problems! |
Re: Gyroscope Code
Quote:
-Kevin |
Re: Gyroscope Code
Quote:
|
Re: Gyroscope Code
In an effort to learn how to implement an integrator in a PID controller I have studied integration with Kevin's Gyro code and the Gyro example in Eugene Brooks' paper "An Introduction to C Programming for FIRST Robotics Applications". I would expect rate gyro integration to look something like the following.
Angle = Angle_prev_frame [mrad] + angular_rate_gyro [mrad/sec] * dt[sec] Where dt is the time between frames (in our case 26.2 msec). Kevin's Gyro code has the following example. // update the gyro rate gyro_rate = temp_gyro_rate; // integrate the gyro rate to derive the heading gyro_angle += (long)temp_gyro_rate; Eugene's code has the following example #define GYROAVE 511 long newgyrovalue = 0; long oldgyrovalue = 0; long gyrointegral = 0; newgyrovalue = Get_Analog_Value(rc_ana_in10); gyrointegral += ((oldgyrovalue + newgyrovalue) / 2) - GYROAVE; oldgyrovalue = newgyrovalue; I understand the notation += means previous frame + new information; however, I don't see how they are taking the time between frames into account (dt). It seems as though in both cases they are simply adding the rate gyro output to the previous angle. It is obvious to me that due to my lack of experience with C, I am missing something. Can anyone explain how the time between frames is taken into account? I want to know how to apply this trick for the integrator in my PID controller. |
Re: Gyroscope Code
Quote:
|
Re: Gyroscope Code
Quote:
angle += angle + (rate * dt) [expression 1] in the code, which might be okay on a 3.2 GHz Pentium 4, which is not only fast by virtue of it's clock rate, but also has hardware that can do the addition and multiplication in one clock period. I can't be so cavalier with our humble PIC18F8722, which can't hope to keep up with the Pentium 4. One of the optimizations I've done is to minimize the number of multiplications that need to be performed to track the angle. Let's take the expression above and rearrange it to show how this works: angle += angle + (rate_n * dt) angle = (rate_0 * dt) + (rate_1 * dt) + (rate_2 * dt) + ... + (rate_n * dt) angle = dt * (rate_0 + rate_1 + rate_2 + ... + rate_n) [expression 2] The way to visualize that last expression is to take each of those little rate times dt rectangles and stack them on top of each other along the rate (y) axis. So now you've got this rectangle with an area of dt * the sum of the rate samples. It's important to know that the area calculated with expression 1 is exactly the same as that calculated with expression 2. So, just how is this done in the code? Well, take expression 2 and separate it into two calculations: rate_sum = rate_0 + rate_1 + rate_2 + ... + rate_n [expression 3] angle = rate_sum * dt [expression 4] Expression 3 is done in Process_Gyro_Data( ) using this code: gyro_angle += (long)temp_gyro_rate; Expression 4 is done in Get_Gyro_Angle( ) and is buried in this calculation: gyro_angle * GYRO_SENSITIVITY * 5L) / (ADC_RANGE * ADC_UPDATE_RATE)) * GYRO_CAL_FACTOR I've done a dimensional analysis that shows that this convoluted expression does spit-out something in an angular unit. The document can be found here: http://www.chiefdelphi.com/forums/sh...2&postcount=21 Hopefully this gives you some insight on how the code works. -Kevin |
Re: Gyroscope Code
You can modify Kevin's code to do a trapezoidal approximation, to get a better approximation.
On line 55, replace: int gyro_rate; with: int gyro_rate; int gyro_rate_prev; Use this as your Gyro_Angle: Code:
long Get_Gyro_Angle(void)Code:
void Process_Gyro_Data(void) |
Re: Gyroscope Code
Quote:
-Kevin |
Re: Gyroscope Code
I took a look at the assembly output and the modification ended up adding about 8 more instructions to the interrupt, which seemed acceptable to me. Maybe I'm wrong.
As for the actual difference between the rectangular integral and the trapezoidal one: I didn't do any serious testing, but I remember seeing a difference last season when I switched to the trapezoidal approximation. When I returned to zero (after doing a 180 degree turn), it got really darn close. When I opened, in MATLAB, the printf data I logged the graph for the gyro angle was nice and smooth. Not really a solid reason to switch over, I guess. |
Re: Gyroscope Code
Quote:
-Kevin |
Re: Gyroscope Code
Quote:
By the way, I had trouble casting long variables into integers. My guess is that I probably exceeded the maximum integer value along the way somewhere. Is there anything special that I need to be aware of when casting a long into and int? |
| All times are GMT -5. The time now is 16:09. |
Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi