Subversion Repositories FlightCtrl

Rev

Rev 980 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
966 MikeW 1
/*
2
Copyright 2008, by Michael Walter
3
 
4
All functions written by Michael Walter are free software and can be redistributed and/or modified under the terms of the GNU Lesser
5
General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but
6
WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7
See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public
8
License along with this program. If not, see <http://www.gnu.org/licenses/>.
9
 
10
Please note: The software is based on the framework provided by H. Buss and I. Busker in their Mikrokopter projekt. All functions that
11
are not written by Michael Walter are under the license by H. Buss and I. Busker (license_buss.txt) published by www.mikrokopter.de
12
unless it is stated otherwise.
13
*/
14
 
15
/*****************************************************************************
16
  INCLUDES
17
**************************************************************************** */
838 MikeW 18
#include "main.h"
19
#include "kafi.h"
20
#include "mymath.h"
21
#include "mm3.h"
970 MikeW 22
#include "FlightControl.h"
966 MikeW 23
 
24
/*****************************************************************************
25
(SYMBOLIC) CONSTANTS
26
*****************************************************************************/
27
 
838 MikeW 28
#define sin45 -0.707106
29
#define cos45 0.707106
30
 
966 MikeW 31
/*****************************************************************************
32
  VARIABLES
33
*****************************************************************************/
34
extern int RCQuality;
985 mikew 35
int RemoteLinkLost = 0;
36
int InvalidAttitude = 0;
966 MikeW 37
extern unsigned long maxDistance;
838 MikeW 38
unsigned char EEPromArray[E2END+1] EEMEM;
966 MikeW 39
 
40
void TestRemote(void);
41
void IMU_Main(void);
42
void TestBattery(void);
43
void SendDebugData(void);
44
void InitPorts(void);
45
void GenerateDefaults(void);
46
void TestIC2Link(void);
47
void GetAirPressureOffset(void);
48
void DeployRescue(void);
49
 
838 MikeW 50
extern void InitOSD(void);
51
extern void InitGPS(void);
52
extern void SendOSD(void);
966 MikeW 53
extern void RemoteControl(void);  
838 MikeW 54
extern void SendMotorData(void);
966 MikeW 55
extern void GetMeasurements(void);
838 MikeW 56
extern void AttitudeEstimation(void);
966 MikeW 57
extern void PD_Regler(void);
838 MikeW 58
extern void SetNeutral(void);
59
 
60
/* ****************************************************************************
966 MikeW 61
Functionname:     main                      */ /*!
62
Description:      Hauptprogramm
63
 
64
  @return           void
65
  @pre              -
66
  @post             -
67
  @author           Michael Walter
68
**************************************************************************** */
69
int main (void)
70
{
71
  /* Controler Init */
72
  InitPorts();
73
  Kafi_Init();
74
  Timer_Init();
75
  UART_Init();
76
  InitGPS();
77
  rc_sum_init();
78
  ADC_Init();
79
  i2c_init();
80
#ifdef USE_COMPASS
81
  MM3_Init();
82
#endif
83
  /* Enable Interrupts */
84
  sei();
85
 
86
  /* Generate Default Values */
87
  GenerateDefaults ();
88
  /* Get Air Pressure Offset */
89
  GetAirPressureOffset();
90
  /* Determine Gyro / ACC Offsets */
91
  SetNeutral();
92
 
93
  DebugIn.Analog[1] = 1000;
94
  DebugIn.Digital[0] = 0x55;
95
 
96
#ifdef USE_COMPASS
97
  /* Calibrate the MM3 Compass? */
98
  if((PPM_in[EE_Parameter.Kanalbelegung[K_GAS]] > 80) &&
99
    (PPM_in[EE_Parameter.Kanalbelegung[K_GIER]] < -75) &&
100
    (MotorenEin == 0))
101
  {
102
    printf("\n\rCalibrating Compass");
103
    MM3_Calibrate();
104
  }
105
#endif 
106
 
107
#ifdef USE_OSD
108
  /* Init the Bob-4 OnScreen Display */
109
  InitOSD();
110
#endif
111
 
112
  /* Start the main Task */
113
  IMU_Main();
114
  return (1);
115
}
116
 
117
 
118
/* ****************************************************************************
119
  Functionname:     IMU_Main                      */ /*!
120
  Description:      
121
 
122
  @param[in]        
123
 
124
  @return           void
125
  @pre              -
126
  @post             -
127
  @author         Michael Walter  
128
**************************************************************************** */
129
void IMU_Main()
130
{
131
  ROT_ON
132
  I2CTimeout = 5000;
133
 
134
  while (1)
135
  {
972 MikeW 136
    static i32_t OldTime = 0;
966 MikeW 137
    if (UpdateMotor)
138
    {
139
      UpdateMotor=0;
140
 
141
#ifdef USE_OSD
142
      /* G e n e r a t e   O S D   D a t a */
143
      static char CntOSD = 0;
144
      if (CntOSD % 6 == 1)
145
      {
146
        SendOSD();
147
      }
148
      CntOSD++;
149
#endif
150
 
151
      /* Set the cycle Time to 120ms / 125ms */
152
      if (OldTime != 0)
153
      {
154
        while (((Count8Khz - OldTime) *10) / 8 < 120);
155
        DebugOut.Analog[14] = ((Count8Khz - OldTime) *10) / 8;
156
      }
157
      OldTime = Count8Khz;
158
 
974 MikeW 159
      /* GetMeasurements()*/
966 MikeW 160
      GetMeasurements();
974 MikeW 161
 
162
      /* EstimateFlightAttitude */
966 MikeW 163
      FlightAttitudeEstimation();
974 MikeW 164
 
966 MikeW 165
      /* Set Nominal Value */
166
      RemoteControl();  
974 MikeW 167
 
168
      /* PD Control */
966 MikeW 169
      PD_Regler();
974 MikeW 170
 
966 MikeW 171
      /* Send Motor Data */
172
      SendMotorData();
974 MikeW 173
 
966 MikeW 174
      /* TestRemote */
175
      TestRemote();
974 MikeW 176
 
966 MikeW 177
      /* Test IC2- / RC-Link */
178
      TestIC2Link();
179
    }
180
    /* Send Debug Data over RS232 */
181
    SendDebugData();
182
    /* Check the Batery for Undervoltage */
183
    TestBattery();
184
    /* DeployRescue */
980 mikew 185
    DeployRescue();
966 MikeW 186
  }
187
}
188
 
189
/* ****************************************************************************
190
Functionname:     DeployRescue                      */ /*!
191
Description:       Deploy a rescue parachute using a servo
192
 
193
  @return           void
194
  @pre              -
195
  @post             -
196
  @author           Michael Walter
197
**************************************************************************** */
198
void DeployRescue()
199
{
980 mikew 200
  /* Yaw or pitch are greater than 90 Deg abs */
201
  if (((abs(status.iTheta10) > 900) || (abs(status.iPhi10) > 900)) &&
202
     ((abs(AverageRoll) > 400) ||
203
      (abs(AverageNick) > 400) ||
204
      (abs(AverageGier) > 400) ))
966 MikeW 205
  {
980 mikew 206
    //MotorenEin = 0;
207
    Delay_ms(500);
208
    InvalidAttitude = 1;
966 MikeW 209
  }
980 mikew 210
 
211
  if (InvalidAttitude)
212
  {
213
    ServoValue = 150;
214
  }
215
  else
216
  {
217
    ServoValue = 0;
218
  }
966 MikeW 219
}
220
 
221
/* ****************************************************************************
838 MikeW 222
Functionname:     ReadParameterSet                      */ /*!
223
Description:      -- Parametersatz aus EEPROM lesen ---
224
                  number [0..5]
225
 
226
  @return           void
227
  @pre              -
228
  @post             -
229
  @author           H. Buss / I. Busker
230
**************************************************************************** */
231
void ReadParameterSet(unsigned char number, unsigned char *buffer, unsigned char length)
232
{
966 MikeW 233
  if (number > 5)
234
  {
235
    number = 5;
236
  }
237
  eeprom_read_block(buffer, &EEPromArray[EEPROM_ADR_PARAM_BEGIN + length * number], length);
838 MikeW 238
}
239
 
240
/* ****************************************************************************
241
Functionname:     WriteParameterSet                      */ /*!
242
Description:      -- Parametersatz ins EEPROM schreiben ---
243
                  number [0..5]
244
 
245
  @return           void
246
  @pre              -
247
  @post             -
248
  @author           H. Buss / I. Busker
249
**************************************************************************** */
250
void WriteParameterSet(unsigned char number, unsigned char *buffer, unsigned char length)
251
{
966 MikeW 252
  if(number > 5)
253
  {
254
    number = 5;
255
  }
256
  eeprom_write_block(buffer, &EEPromArray[EEPROM_ADR_PARAM_BEGIN + length * number], length);
257
  eeprom_write_byte(&EEPromArray[EEPROM_ADR_ACTIVE_SET], number);      // diesen Parametersatz als aktuell merken
838 MikeW 258
}
259
 
260
/* ****************************************************************************
261
Functionname:     GetActiveParamSetNumber                      */ /*!
262
Description:      
263
 
264
  @return           void
265
  @pre              -
266
  @post             -
267
  @author           H. Buss / I. Busker
268
**************************************************************************** */
269
unsigned char GetActiveParamSetNumber(void)
270
{
966 MikeW 271
  unsigned char set;
272
  set = eeprom_read_byte(&EEPromArray[EEPROM_ADR_ACTIVE_SET]);
273
  if(set > 5)
274
  {
275
    set = 2;  
276
    eeprom_write_byte(&EEPromArray[EEPROM_ADR_ACTIVE_SET], set);      // diesen Parametersatz als aktuell merken
277
  }
278
  return(set);
838 MikeW 279
}
280
 
966 MikeW 281
/* ****************************************************************************
282
Functionname:     GetAirPressureOffset                      */ /*!
283
Description:      
838 MikeW 284
 
966 MikeW 285
  @return           void
286
  @pre              -
287
  @post             -
288
  @author           H. Buss / I. Busker
289
**************************************************************************** */
290
void GetAirPressureOffset(void)
291
{
292
 unsigned int timer;
293
 ReadParameterSet(GetActiveParamSetNumber(), (unsigned char *) &EE_Parameter.Kanalbelegung[0], STRUCT_PARAM_LAENGE);
294
  printf("\n\rBenutze Parametersatz %d", GetActiveParamSetNumber());
295
  if(EE_Parameter.GlobalConfig & CFG_HOEHENREGELUNG)
296
  {
297
    printf("\n\rAbgleich Luftdrucksensor..");
298
    timer = SetDelay(1000);  
299
    SucheLuftruckOffset();
300
    while (!CheckDelay(timer));
301
    printf("OK\n\r");
302
  }
303
}
304
 
838 MikeW 305
/* ****************************************************************************
966 MikeW 306
Functionname:     GenerateDefaults                      */ /*!
307
Description:      Generate the Default Paramter
838 MikeW 308
 
309
  @return           void
310
  @pre              -
311
  @post             -
312
  @author           H. Buss / I. Busker
313
**************************************************************************** */
966 MikeW 314
void  GenerateDefaults()
838 MikeW 315
{
966 MikeW 316
  VersionInfo.Hauptversion = VERSION_HAUPTVERSION;
317
  VersionInfo.Nebenversion = VERSION_NEBENVERSION;
318
  VersionInfo.PCKompatibel = VERSION_KOMPATIBEL;
319
 
320
#define EE_DATENREVISION 66 // wird angepasst, wenn sich die EEPROM-Daten geändert haben
321
  if(eeprom_read_byte(&EEPromArray[EEPROM_ADR_VALID]) != EE_DATENREVISION)
322
  {
323
    printf("\n\rInit. EEPROM: Generiere Default-Parameter...");
324
    DefaultKonstanten1();
325
    for (unsigned char i=0;i<6;i++)  
326
    {
327
      if(i==2) DefaultKonstanten2(); // Kamera
328
      if(i==3) DefaultKonstanten3(); // Beginner
329
      if(i>3)  DefaultKonstanten2(); // Kamera
330
      WriteParameterSet(i, (unsigned char *) &EE_Parameter.Kanalbelegung[0], STRUCT_PARAM_LAENGE);
331
    }
332
    eeprom_write_byte(&EEPromArray[EEPROM_ADR_ACTIVE_SET], 3); // default-Setting
333
    eeprom_write_byte(&EEPromArray[EEPROM_ADR_VALID], EE_DATENREVISION);
334
  }
335
}
838 MikeW 336
 
337
 
966 MikeW 338
/* ****************************************************************************
339
Functionname:     InitPorts                      */ /*!
340
Description:      Init the IO Ports
838 MikeW 341
 
966 MikeW 342
  @return           void
343
  @pre              -
344
  @post             -
345
  @author           H. Buss / I. Busker
346
**************************************************************************** */
347
void  InitPorts()
348
{
349
  unsigned int timer = 0;
350
  DDRB  = 0x00;
351
  PORTB = 0x00;
352
  for(timer = 0; timer < 1000; timer++); // verzögern
353
  DDRC  = 0x81; // SCL
354
  PORTC = 0xff; // Pullup SDA
355
  DDRB  = 0x1B; // LEDs und Druckoffset
356
  PORTB = 0x01; // LED_Rot
357
  DDRD  = 0x3E; // Speaker & TXD & J3 J4 J5
358
  DDRD  |=0x80; // J7
359
  PORTD = 0xF7; // LED
360
 
361
  MCUSR &=~(1<<WDRF);
362
  WDTCSR |= (1<<WDCE)|(1<<WDE);
363
  WDTCSR = 0;
364
}
365
 
366
/* ****************************************************************************
367
Functionname:     TestIC2Link                      */ /*!
368
Description:      Test IC2- / RC-Link
369
 
370
  @return           void
371
  @pre              -
372
  @post             -
373
  @author           H. Buss / I. Busker
374
**************************************************************************** */
375
void TestIC2Link()
376
{
377
  if(PcZugriff)
378
  {
379
    PcZugriff--;
380
  }
381
 
382
  if(SenderOkay)  
383
  {
384
    SenderOkay--;
385
  }
386
 
387
  if(!I2CTimeout)
388
  {
389
    I2CTimeout = 5;
390
    i2c_reset();
391
    if((BeepMuster == 0xffff) && MotorenEin)
392
    {
393
      beeptime = 10000;
394
      BeepMuster = 0x0080;
395
    }
396
  }
397
  else
398
  {
399
    I2CTimeout--;
400
  }
401
}
402
 
403
 
404
/* ****************************************************************************
405
Functionname:     SendDebugData                      */ /*!
406
Description:      Send Debug Data over RS232
407
 
408
  @return           void
409
  @pre              -
410
  @post             -
411
  @author           H. Buss / I. Busker
412
**************************************************************************** */
413
void SendDebugData()
414
{
415
  if(SIO_DEBUG)
416
  {
417
    DatenUebertragung();
418
    BearbeiteRxDaten();
419
  }
420
  else
421
  {
422
    BearbeiteRxDaten();
423
  }
424
}
425
 
426
 
427
/* ****************************************************************************
428
Functionname:     TestBattery                      */ /*!
429
Description:      Check the Battery Voltage
430
 
431
  @return           void
432
  @pre              -
433
  @post             -
434
  @author           H. Buss / I. Busker
435
**************************************************************************** */
436
void  TestBattery()
437
{
438
  unsigned int timer = 0;
439
  if(CheckDelay(timer))
440
  {  /* Voltage is Below Threshhod ? */
441
    if(UBat < EE_Parameter.UnterspannungsWarnung)
442
    {    
443
      if(BeepMuster == 0xffff)
444
      {
445
        beeptime = 6000;
446
        BeepMuster = 0x0300;
447
      }
448
    }
449
    timer = SetDelay(100);  
450
  }
451
  DebugOut.Analog[15] =  UBat;
452
}
453
 
454
/* ****************************************************************************
455
  Functionname:     TestRemote                      */ /*!
456
  Description:      
457
 
458
  @param[in]        
459
 
460
  @return           void
461
  @pre              -
462
  @post             -
463
  @author         Michael Walter  
464
**************************************************************************** */
465
void TestRemote()
466
{
467
  /*--- (SYMBOLIC) CONSTANTS ---*/
468
 
469
  /*--- VARIABLES ---*/
470
  static unsigned int TimeSinceRC_BelowThreshhold = 0;
471
  static unsigned int TimeSinceRC_AboveThreshhold = 0;
472
 
473
  if (MotorenEin == 1)
474
  {
475
    if (RemoteLinkLost == 0)
476
    {
477
      if (RCQuality < 60)
478
      {
479
        if (TimeSinceRC_BelowThreshhold < 10000)
480
        {
481
          TimeSinceRC_BelowThreshhold++;
838 MikeW 482
        }
966 MikeW 483
      }
484
      else
485
      {
486
        TimeSinceRC_BelowThreshhold = 0;
487
      }
488
      if ((TimeSinceRC_BelowThreshhold > 500) || /* aprox. 5 seconds */
489
        (SenderOkay < 100))
490
      {
491
        RemoteLinkLost = 1;
492
        TimeSinceRC_AboveThreshhold = 0;
493
      }
494
    }
495
    else
496
    {
497
      if (RCQuality > 80)
498
      {
499
        if (TimeSinceRC_AboveThreshhold < 10000)
500
        {
501
          TimeSinceRC_AboveThreshhold++;
502
        }
503
      }
504
      else
505
      {
506
        TimeSinceRC_AboveThreshhold = 0;
507
      }
508
      if (TimeSinceRC_AboveThreshhold > 100) /* aprox. 1 seconds */
509
      {
510
        RemoteLinkLost = 0;
511
        TimeSinceRC_BelowThreshhold = 0;    
512
      }
513
    }
514
  }
515
  else
516
  {
517
    RemoteLinkLost = 0;
518
    TimeSinceRC_BelowThreshhold = 0;
519
    TimeSinceRC_AboveThreshhold = 0;
520
  }
521
  /*DebugOut.Analog[14] = TimeSinceRC_BelowThreshhold;*/
522
  /*DebugOut.Analog[15] = TimeSinceRC_AboveThreshhold;*/
838 MikeW 523
}