Subversion Repositories FlightCtrl

Rev

Rev 779 | Rev 782 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 779 Rev 781
1
#include <inttypes.h>
1
#include <inttypes.h>
2
#include <stdlib.h>
2
#include <stdlib.h>
3
#include "fc.h"
3
#include "fc.h"
4
#include "ubx.h"
4
#include "ubx.h"
5
#include "mymath.h"
5
#include "mymath.h"
6
#include "timer0.h"
6
#include "timer0.h"
7
#include "uart.h"
7
#include "uart.h"
8
 
8
 
9
#define TSK_IDLE                0
9
#define TSK_IDLE                0
10
#define TSK_HOLD                1
10
#define TSK_HOLD                1
11
#define TSK_HOME                2
11
#define TSK_HOME                2
12
 
12
 
13
#define GPS_STICK_SENSE         20              // must be at least in a range where 90% of the trimming does not switch of the GPS function
13
#define GPS_STICK_SENSE         20              // must be at least in a range where 90% of the trimming does not switch of the GPS function
14
#define GPS_STICK_LIMIT         45              // limit of gps stick control to avoid critical flight attitudes
14
#define GPS_STICK_LIMIT         45              // limit of gps stick control to avoid critical flight attitudes
15
#define GPS_D_LIMIT_DIST        500     // for position deviations grater than 500 cm (20m) the D-Part of the PD-Controller is limited
15
#define GPS_D_LIMIT_DIST        500     // for position deviations grater than 500 cm (20m) the D-Part of the PD-Controller is limited
16
#define GPS_D_LIMIT                     50              // PD-Controntroller D-Limit.
16
#define GPS_D_LIMIT                     50              // PD-Controntroller D-Limit.
17
 
17
 
18
int16_t GPS_Pitch = 0;
18
int16_t GPS_Pitch = 0;
19
int16_t GPS_Roll = 0;
19
int16_t GPS_Roll = 0;
20
 
20
 
21
int32_t GPS_P_Factor = 0, GPS_D_Factor = 0;
21
int32_t GPS_P_Factor = 0, GPS_D_Factor = 0;
22
int32_t GPSPosDev_North = 0, GPSPosDev_East = 0;
-
 
-
 
22
 
23
 
23
 
24
 
24
 
25
typedef struct
25
typedef struct
26
{
26
{
27
        int32_t Northing;
27
        int32_t Longitude;
28
        int32_t Easting;
28
        int32_t Latitude;
29
        uint8_t Status;
29
        uint8_t Status;
30
 
-
 
31
} GPS_Pos_t;
30
} GPS_Pos_t;
32
 
31
 
33
// GPS coordinates for hold position
32
// GPS coordinates for hold position
34
GPS_Pos_t HoldPosition  = {0,0, INVALID};
33
GPS_Pos_t HoldPosition  = {0,0, INVALID};
35
// GPS coordinates for home position
34
// GPS coordinates for home position
36
GPS_Pos_t HomePosition  = {0,0, INVALID};
35
GPS_Pos_t HomePosition  = {0,0, INVALID};
37
 
36
 
38
 
37
 
39
// ---------------------------------------------------------------------------------
38
// ---------------------------------------------------------------------------------
40
 
39
 
41
// set home position to current hold positon
40
// set home position to current positon
42
void GPS_SetHomePosition(void)
41
void GPS_SetHomePosition(void)
-
 
42
{
-
 
43
        if( ((GPSInfo.status == VALID) || (GPSInfo.status == PROCESSED)) && GPSInfo.satfix == SATFIX_3D)
43
{
44
        {
44
                HomePosition.Northing = HoldPosition.Northing;
45
                HomePosition.Longitude = GPSInfo.longitude;
45
                HomePosition.Easting = HoldPosition.Easting;
46
                HomePosition.Latitude = GPSInfo.latitude;
46
                HomePosition.Status = HoldPosition.Status;
47
                HomePosition.Status = VALID;
-
 
48
                BeepTime = 1000; // signal if new home position was set
-
 
49
        }
-
 
50
        else
-
 
51
        {
-
 
52
                HomePosition.Status = INVALID;
-
 
53
        }
-
 
54
}
-
 
55
 
-
 
56
// set hold position to current positon
-
 
57
void GPS_SetHoldPosition(void)
-
 
58
{
-
 
59
        if( ((GPSInfo.status == VALID) || (GPSInfo.status == PROCESSED)) && GPSInfo.satfix == SATFIX_3D)
-
 
60
        {
-
 
61
                HoldPosition.Longitude = GPSInfo.longitude;
-
 
62
                HoldPosition.Latitude = GPSInfo.latitude;
-
 
63
                HoldPosition.Status = VALID;
-
 
64
        }
-
 
65
        else
-
 
66
        {
-
 
67
                HoldPosition.Status = INVALID;
47
                if(HomePosition.Status == VALID) BeepTime = 1000; // signal if new home position was set
68
        }
48
}
69
}
49
 
70
 
50
// clear home position
71
// clear home position
51
void GPS_ClearHomePosition(void)
72
void GPS_ClearHomePosition(void)
52
{
73
{
53
                HomePosition.Status = INVALID;
74
                HomePosition.Status = INVALID;
54
}
75
}
55
 
76
 
56
// disable GPS control sticks
77
// disable GPS control sticks
57
void GPS_Neutral(void)
78
void GPS_Neutral(void)
58
{
79
{
59
        GPS_Pitch = 0;
80
        GPS_Pitch = 0;
60
        GPS_Roll = 0;
81
        GPS_Roll = 0;
61
}
82
}
62
 
83
 
63
// calculates the GPS control sticks values from the deviation to target position
84
// calculates the GPS control sticks values from the deviation to target position
64
void GPS_PDController(GPS_Pos_t *TargetPos)
85
void GPS_PDController(GPS_Pos_t *TargetPos)
65
{
86
{
66
        int32_t coscompass, sincompass;
87
        int32_t coscompass, sincompass;
-
 
88
        int32_t GPSPosDev_North, GPSPosDev_East; // Position deviation in cm
67
        int32_t P_North = 0, D_North = 0, P_East = 0, D_East = 0;
89
        int32_t P_North = 0, D_North = 0, P_East = 0, D_East = 0;
68
        int32_t PD_North = 0, PD_East = 0;
90
        int32_t PD_North = 0, PD_East = 0;
-
 
91
        static int32_t cos_target_latitude = 1;
-
 
92
 
69
 
93
 
70
        if( (TargetPos->Status == VALID) && (GPSInfo.status == VALID) && (GPSInfo.satfix == SATFIX_3D))
94
        if( (TargetPos->Status != INVALID) && (GPSInfo.status == VALID) && (GPSInfo.satfix == SATFIX_3D))
-
 
95
        {
71
        {
96
                // calculate position deviation from latitude and longitude differences
-
 
97
                GPSPosDev_North = (GPSInfo.latitude - TargetPos->Latitude); // to calculate real cm we would need *111/100 additionally
-
 
98
                GPSPosDev_East  = (GPSInfo.longitude - TargetPos->Longitude); // to calculate real cm we would need *111/100 additionally
-
 
99
                // recalculate the target latitude projection only if the target data are updated
-
 
100
                // to save time
-
 
101
                if (TargetPos->Status != PROCESSED)
-
 
102
                {
-
 
103
                        cos_target_latitude = (int32_t)c_cos_8192((int16_t)(TargetPos->Latitude/10000000L));
-
 
104
                        TargetPos->Status = PROCESSED;
-
 
105
                }
72
                GPSPosDev_North = GPSInfo.utmnorth - TargetPos->Northing;
106
                // calculate latitude projection
-
 
107
                GPSPosDev_East  *= cos_target_latitude;
73
                GPSPosDev_East  = GPSInfo.utmeast  - TargetPos->Easting;
108
                GPSPosDev_East /= 8192;
74
 
109
 
75
                DebugOut.Analog[12] = GPSPosDev_North;
110
                DebugOut.Analog[12] = GPSPosDev_North;
76
                DebugOut.Analog[13] = GPSPosDev_East;
111
                DebugOut.Analog[13] = GPSPosDev_East;
77
 
112
 
78
                //DebugOut.Analog[12] = GPSInfo.velnorth;
113
                //DebugOut.Analog[12] = GPSInfo.velnorth;
79
                //DebugOut.Analog[13] = GPSInfo.veleast;
114
                //DebugOut.Analog[13] = GPSInfo.veleast;
80
 
115
 
81
                //Calculate PD-components of the controller (negative sign for compensation)
116
                //Calculate PD-components of the controller (negative sign for compensation)
82
                P_North = -(GPS_P_Factor * GPSPosDev_North)/2048;
117
                P_North = -(GPS_P_Factor * GPSPosDev_North)/2048;
83
                D_North = -(GPS_D_Factor * GPSInfo.velnorth)/512;
118
                D_North = -(GPS_D_Factor * GPSInfo.velnorth)/512;
84
                P_East =  -(GPS_P_Factor * GPSPosDev_East)/2048;
119
                P_East =  -(GPS_P_Factor * GPSPosDev_East)/2048;
85
                D_East =  -(GPS_D_Factor * GPSInfo.veleast)/512;
120
                D_East =  -(GPS_D_Factor * GPSInfo.veleast)/512;
86
 
121
 
87
                if( (abs(GPSPosDev_North) > GPS_D_LIMIT_DIST) ||  (abs(GPSPosDev_East) > GPS_D_LIMIT_DIST) )
122
                if( (abs(GPSPosDev_North) > GPS_D_LIMIT_DIST) ||  (abs(GPSPosDev_East) > GPS_D_LIMIT_DIST) )
88
                {
123
                {
89
                        if (D_North > GPS_D_LIMIT) D_North = GPS_D_LIMIT;
124
                        if (D_North > GPS_D_LIMIT) D_North = GPS_D_LIMIT;
90
                        else if (D_North < -GPS_D_LIMIT) D_North = -GPS_D_LIMIT;
125
                        else if (D_North < -GPS_D_LIMIT) D_North = -GPS_D_LIMIT;
91
                        if (D_East > GPS_D_LIMIT)  D_East  = GPS_D_LIMIT;
126
                        if (D_East > GPS_D_LIMIT)  D_East  = GPS_D_LIMIT;
92
                        else if (D_East  < -GPS_D_LIMIT) D_East  = -GPS_D_LIMIT;
127
                        else if (D_East  < -GPS_D_LIMIT) D_East  = -GPS_D_LIMIT;
93
                }
128
                }
94
 
129
 
95
                // PD-controller
130
                // PD-controller
96
                PD_North = P_North + D_North;
131
                PD_North = P_North + D_North;
97
                PD_East  = P_East  + D_East;
132
                PD_East  = P_East  + D_East;
98
 
133
 
99
                // GPS to pitch and roll settings
134
                // GPS to pitch and roll settings
100
 
135
 
101
                //A positive pitch angle moves head downwards (flying forward).
136
                //A positive pitch angle moves head downwards (flying forward).
102
                //A positive roll angle tilts left side downwards (flying left).
137
                //A positive roll angle tilts left side downwards (flying left).
103
 
138
 
104
                // If compass heading is 0 the head of the copter is in north direction.
139
                // If compass heading is 0 the head of the copter is in north direction.
105
                // A positive pitch angle will fly to north and a positive roll angle will fly to west.
140
                // A positive pitch angle will fly to north and a positive roll angle will fly to west.
106
                // In case of a positive north deviation/velocity the
141
                // In case of a positive north deviation/velocity the
107
                // copter should fly to south (negative pitch).
142
                // copter should fly to south (negative pitch).
108
                // In case of a positive east position deviation and a positive east velocity the
143
                // In case of a positive east position deviation and a positive east velocity the
109
                // copter should fly to west (positive roll).
144
                // copter should fly to west (positive roll).
110
 
145
 
111
                // The influence of the GPS_Pitch and GPS_Roll variable is contrarily to the stick values
146
                // The influence of the GPS_Pitch and GPS_Roll variable is contrarily to the stick values
112
                // in the fc.c. Therefore a positive north deviation/velocity should result in a positive
147
                // in the fc.c. Therefore a positive north deviation/velocity should result in a positive
113
                // GPS_Pitch and a positive east deviation/velocity should result in a negative GPS_Roll.
148
                // GPS_Pitch and a positive east deviation/velocity should result in a negative GPS_Roll.
114
 
149
 
115
                // rotation transformation to compass heading to match any copter orientation
150
                // rotation transformation to compass heading to match any copter orientation
116
                if (CompassHeading < 0) // no valid compass data
151
                if (CompassHeading < 0) // no valid compass data
117
                { // disable GPS
152
                { // disable GPS
118
                        GPS_Neutral();
153
                        GPS_Neutral();
119
                }
154
                }
120
                else
155
                else
121
                {
156
                {
122
                        coscompass = (int32_t)c_cos_8192(CompassHeading);
157
                        coscompass = (int32_t)c_cos_8192(CompassHeading);
123
                        sincompass = (int32_t)c_sin_8192(CompassHeading);
158
                        sincompass = (int32_t)c_sin_8192(CompassHeading);
124
                        GPS_Roll  =    (int16_t)((coscompass * PD_East - sincompass * PD_North) / 8192);
159
                        GPS_Roll  =    (int16_t)((coscompass * PD_East - sincompass * PD_North) / 8192);
125
                        GPS_Pitch = -1*(int16_t)((sincompass * PD_East + coscompass * PD_North) / 8192);
160
                        GPS_Pitch = -1*(int16_t)((sincompass * PD_East + coscompass * PD_North) / 8192);
126
                }
161
                }
127
                // limit GPS controls
162
                // limit GPS controls
128
                if (GPS_Pitch >  GPS_STICK_LIMIT) GPS_Pitch =  GPS_STICK_LIMIT;
163
                if (GPS_Pitch >  GPS_STICK_LIMIT) GPS_Pitch =  GPS_STICK_LIMIT;
129
                else if (GPS_Pitch < -GPS_STICK_LIMIT) GPS_Pitch = -GPS_STICK_LIMIT;
164
                else if (GPS_Pitch < -GPS_STICK_LIMIT) GPS_Pitch = -GPS_STICK_LIMIT;
130
                if (GPS_Roll  >  GPS_STICK_LIMIT)  GPS_Roll =  GPS_STICK_LIMIT;
165
                if (GPS_Roll  >  GPS_STICK_LIMIT)  GPS_Roll =  GPS_STICK_LIMIT;
131
                else if (GPS_Roll  < -GPS_STICK_LIMIT)  GPS_Roll = -GPS_STICK_LIMIT;
166
                else if (GPS_Roll  < -GPS_STICK_LIMIT)  GPS_Roll = -GPS_STICK_LIMIT;
132
        }
167
        }
133
        else // invalid input data
168
        else // invalid input data
134
        {
169
        {
135
                BeepTime = 50;
170
                BeepTime = 50;
136
                GPS_Neutral();
171
                GPS_Neutral();
137
        }
172
        }
138
}
173
}
139
 
174
 
140
 
175
 
141
void GPS_Main(uint8_t ctrl)
176
void GPS_Main(uint8_t ctrl)
142
{
177
{
143
        static uint8_t GPS_Task = TSK_IDLE;
178
        static uint8_t GPS_Task = TSK_IDLE;
144
        int16_t satbeep;
179
        int16_t satbeep;
145
 
180
 
146
        // ctrl enables the gps feature
181
        // ctrl enables the gps feature
147
        if(ctrl < 70) GPS_Task = TSK_IDLE;
182
        if(ctrl < 70) GPS_Task = TSK_IDLE;
148
        else if (ctrl < 160) GPS_Task = TSK_HOLD;
183
        else if (ctrl < 160) GPS_Task = TSK_HOLD;
149
        else GPS_Task = TSK_HOME; // ctrl >= 160
184
        else GPS_Task = TSK_HOME; // ctrl >= 160
150
 
185
 
151
 
186
 
152
        switch(GPSInfo.status)
187
        switch(GPSInfo.status)
153
        {
188
        {
154
        case INVALID:  // invalid gps data
189
        case INVALID:  // invalid gps data
155
                GPS_Neutral();
190
                GPS_Neutral();
156
                if(GPS_Task != TSK_IDLE)
191
                if(GPS_Task != TSK_IDLE)
157
                {
192
                {
158
                        BeepTime = 100; // beep if signal is neccesary
193
                        BeepTime = 100; // beep if signal is neccesary
159
                }
194
                }
160
                break;
195
                break;
161
        case PROCESSED: // if gps data are already processed
196
        case PROCESSED: // if gps data are already processed do nothing
162
                // downcount timeout
197
                // downcount timeout
163
                if(GPSTimeout) GPSTimeout--;
198
                if(GPSTimeout) GPSTimeout--;
164
                // if no new data arrived within timeout set current data invalid
199
                // if no new data arrived within timeout set current data invalid
165
                // and therefore disable GPS
200
                // and therefore disable GPS
166
                else
201
                else
167
                {
202
                {
168
                        GPS_Neutral();
203
                        GPS_Neutral();
169
                        GPSInfo.status = INVALID;
204
                        GPSInfo.status = INVALID;
170
                }
205
                }
171
                break;
206
                break;
172
        case VALID: // new valid data from gps device
207
        case VALID: // new valid data from gps device
173
                // if the gps data quality is sufficient
208
                // if the gps data quality is good
174
                if (GPSInfo.satfix == SATFIX_3D)
209
                if (GPSInfo.satfix == SATFIX_3D)
175
                {
210
                {
176
                        switch(GPS_Task) // check what's to do
211
                        switch(GPS_Task) // check what's to do
177
                        {
212
                        {
178
                                case TSK_IDLE:
213
                                case TSK_IDLE:
179
                                        // update hold point to current gps position
214
                                        // update hold position to current gps position
180
                                        HoldPosition.Northing = GPSInfo.utmnorth;
-
 
181
                                        HoldPosition.Easting  = GPSInfo.utmeast;
215
                                        GPS_SetHoldPosition(); // can get invalid if gps signal is bad
182
                                        HoldPosition.Status = VALID;
-
 
183
                                        // disable gps control
216
                                        // disable gps control
184
                                        GPS_Neutral();
217
                                        GPS_Neutral();
185
                                        break; // eof TSK_IDLE
218
                                        break; // eof TSK_IDLE
186
                                case TSK_HOLD:
219
                                case TSK_HOLD:
187
                                        if(HoldPosition.Status == VALID)
220
                                        if(HoldPosition.Status != INVALID)
188
                                        {
221
                                        {
189
                                                // if sticks are centered (no manual control)
222
                                                // if sticks are centered (no manual control)
190
                                                if ((MaxStickPitch < GPS_STICK_SENSE) && (MaxStickRoll < GPS_STICK_SENSE))
223
                                                if ((MaxStickPitch < GPS_STICK_SENSE) && (MaxStickRoll < GPS_STICK_SENSE))
191
                                                {
224
                                                {
192
                                                        GPS_PDController(&HoldPosition);
225
                                                        GPS_PDController(&HoldPosition);
193
                                                }
226
                                                }
194
                                                else // MK controlled by user
227
                                                else // MK controlled by user
195
                                                {
228
                                                {
196
                                                        // update hold point to current gps position
229
                                                        // update hold point to current gps position
197
                                                        HoldPosition.Northing = GPSInfo.utmnorth;
-
 
198
                                                        HoldPosition.Easting  = GPSInfo.utmeast;
-
 
199
                                                        HoldPosition.Status   = GPSInfo.status;
230
                                                        GPS_SetHoldPosition();
200
                                                        // disable gps control
231
                                                        // disable gps control
201
                                                        GPS_Neutral();
232
                                                        GPS_Neutral();
202
                                                }
233
                                                }
203
                                        }
234
                                        }
-
 
235
                                        else // invalid Hold Position
-
 
236
                                        {  // try to catch a valid hold position from gps data input
-
 
237
                                                GPS_SetHoldPosition();
-
 
238
                                                GPS_Neutral();
-
 
239
                                        }
204
                                        break; // eof TSK_HOLD
240
                                        break; // eof TSK_HOLD
205
                                case TSK_HOME:
241
                                case TSK_HOME:
206
                                        if(HomePosition.Status == VALID)
242
                                        if(HomePosition.Status != INVALID)
207
                                        {
243
                                        {
208
                                                // update hold point to current gps position
244
                                                // update hold point to current gps position
209
                                                // to avoid a flight back if home comming is deactivated
245
                                                // to avoid a flight back if home comming is deactivated
210
                                                HoldPosition.Northing = GPSInfo.utmnorth;
-
 
211
                                                HoldPosition.Easting  = GPSInfo.utmeast;
-
 
212
                                                HoldPosition.Status   = GPSInfo.status;
246
                                                GPS_SetHoldPosition();
213
                                                // if sticks are centered (no manual control)
247
                                                // if sticks are centered (no manual control)
214
                                                if((MaxStickPitch < GPS_STICK_SENSE) && (MaxStickRoll < GPS_STICK_SENSE))
248
                                                if((MaxStickPitch < GPS_STICK_SENSE) && (MaxStickRoll < GPS_STICK_SENSE))
215
                                                {
249
                                                {
216
                                                        GPS_PDController(&HomePosition);
250
                                                        GPS_PDController(&HomePosition);
217
                                                }
251
                                                }
218
                                                else // manual control
252
                                                else // manual control
219
                                                {
253
                                                {
220
                                                        GPS_Neutral();
254
                                                        GPS_Neutral();
221
                                                }
255
                                                }
222
                                        }
256
                                        }
223
                                        else // bad home position
257
                                        else // bad home position
224
                                        {
258
                                        {
225
                                                BeepTime = 50; // signal invalid home position
259
                                                BeepTime = 50; // signal invalid home position
226
                                                // try to hold at least the position as a fallback option
260
                                                // try to hold at least the position as a fallback option
-
 
261
 
227
                                                // if sticks are centered (no manual control)
262
                                                if (HoldPosition.Status != INVALID)
228
                                                if((MaxStickPitch < GPS_STICK_SENSE) && (MaxStickRoll < GPS_STICK_SENSE) && (HoldPosition.Status == VALID))
-
 
229
                                                {
263
                                                {
-
 
264
                                                        // if sticks are centered (no manual control)
-
 
265
                                                        if((MaxStickPitch < GPS_STICK_SENSE) && (MaxStickRoll < GPS_STICK_SENSE))
-
 
266
                                                        {
230
                                                        GPS_PDController(&HoldPosition);
267
                                                                GPS_PDController(&HoldPosition);
-
 
268
                                                        }
-
 
269
                                                        else // manual control or no reference position
-
 
270
                                                        {
-
 
271
                                                                GPS_Neutral();
-
 
272
                                                        }
231
                                                }
273
                                                }
-
 
274
                                                else
232
                                                else // manual control or no rteference position
275
                                                { // try to catch a valid hold position
233
                                                {
276
                                                        GPS_SetHoldPosition();
234
                                                        GPS_Neutral();
277
                                                        GPS_Neutral();
235
                                                }
278
                                                }
236
                                        }
279
                                        }
237
                                        break; // eof TSK_HOME
280
                                        break; // eof TSK_HOME
238
                                default: // unhandled task
281
                                default: // unhandled task
239
                                        GPS_Neutral();
282
                                        GPS_Neutral();
240
                                        break; // eof default
283
                                        break; // eof default
241
                        } // eof switch GPS_Task
284
                        } // eof switch GPS_Task
242
                } // eof 3D-FIX
285
                } // eof 3D-FIX
243
 
-
 
244
                else // no 3D-SATFIX
286
                else // no 3D-SATFIX
245
                {       // disable gps control
287
                {       // disable gps control
246
                        GPS_Neutral();
288
                        GPS_Neutral();
247
                        if(GPS_Task != TSK_IDLE)
289
                        if(GPS_Task != TSK_IDLE)
248
                        {
290
                        {
249
                                satbeep = 1800 - (int16_t)GPSInfo.satnum * 225; // is zero at 8 sats
291
                                satbeep = 1800 - (int16_t)GPSInfo.satnum * 225; // is zero at 8 sats
250
                                if (satbeep < 0) satbeep = 0;
292
                                if (satbeep < 0) satbeep = 0;
251
                                BeepTime = 50 + (uint16_t)satbeep; // max 1850 * 0.1 ms =
293
                                BeepTime = 50 + (uint16_t)satbeep; // max 1850 * 0.1 ms =
252
                        }
294
                        }
253
                }
295
                }
254
                // set current data as processed to avoid further calculations on the same gps data
296
                // set current data as processed to avoid further calculations on the same gps data
255
                GPSInfo.status = PROCESSED;
297
                GPSInfo.status = PROCESSED;
256
                break;
298
                break;
257
        } // eof GPSInfo.status
299
        } // eof GPSInfo.status
258
        DebugOut.Analog[14] = GPS_Pitch;
300
        DebugOut.Analog[14] = GPS_Pitch;
259
        DebugOut.Analog[15] = GPS_Roll;
301
        DebugOut.Analog[15] = GPS_Roll;
260
}
302
}
261
 
303
 
262
 
304