Subversion Repositories FlightCtrl

Rev

Rev 974 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
Copyright 2008, by Michael Walter

All functions written by Michael Walter are free software and can be redistributed and/or modified under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public
License along with this program. If not, see <http://www.gnu.org/licenses/>.

Please note: The software is based on the framework provided by H. Buss and I. Busker in their Mikrokopter projekt. All functions that
are not written by Michael Walter are under the license by H. Buss and I. Busker (license_buss.txt) published by www.mikrokopter.de
unless it is stated otherwise.
*/


/*****************************************************************************
  INCLUDES
**************************************************************************** */

#include "main.h"
#include "kafi.h"
#include "mymath.h"
#include "mm3.h"
#include "FlightControl.h"

/*****************************************************************************
(SYMBOLIC) CONSTANTS
*****************************************************************************/


#define sin45 -0.707106
#define cos45 0.707106

/*****************************************************************************
  VARIABLES
*****************************************************************************/

extern int RCQuality;
int RemoteLinkLost;
extern unsigned long maxDistance;
unsigned char EEPromArray[E2END+1] EEMEM;

void TestRemote(void);
void IMU_Main(void);
void TestBattery(void);
void SendDebugData(void);
void InitPorts(void);
void GenerateDefaults(void);
void TestIC2Link(void);
void GetAirPressureOffset(void);
void DeployRescue(void);

extern void InitOSD(void);
extern void InitGPS(void);
extern void SendOSD(void);
extern void RemoteControl(void);  
extern void SendMotorData(void);
extern void GetMeasurements(void);
extern void AttitudeEstimation(void);
extern void PD_Regler(void);
extern void SetNeutral(void);

/* ****************************************************************************
Functionname:     main                      */
/*!
Description:      Hauptprogramm

  @return           void
  @pre              -
  @post             -
  @author           Michael Walter
**************************************************************************** */

int main (void)
{
  /* Controler Init */
  InitPorts();
  Kafi_Init();
  Timer_Init();
  UART_Init();
  InitGPS();
  rc_sum_init();
  ADC_Init();
  i2c_init();
#ifdef USE_COMPASS
  MM3_Init();
#endif
  /* Enable Interrupts */
  sei();

  /* Generate Default Values */
  GenerateDefaults ();
  /* Get Air Pressure Offset */
  GetAirPressureOffset();
  /* Determine Gyro / ACC Offsets */
  SetNeutral();

  DebugIn.Analog[1] = 1000;
  DebugIn.Digital[0] = 0x55;
 
#ifdef USE_COMPASS
  /* Calibrate the MM3 Compass? */
  if((PPM_in[EE_Parameter.Kanalbelegung[K_GAS]] > 80) &&
    (PPM_in[EE_Parameter.Kanalbelegung[K_GIER]] < -75) &&
    (MotorenEin == 0))
  {
    printf("\n\rCalibrating Compass");
    MM3_Calibrate();
  }
#endif

#ifdef USE_OSD
  /* Init the Bob-4 OnScreen Display */
  InitOSD();
#endif

  /* Start the main Task */
  IMU_Main();
  return (1);
}


/* ****************************************************************************
  Functionname:     IMU_Main                      */
/*!
  Description:      

  @param[in]        

  @return           void
  @pre              -
  @post             -
  @author         Michael Walter  
**************************************************************************** */

void IMU_Main()
{
  ROT_ON
  I2CTimeout = 5000;
 
  while (1)
  {
    static i32_t OldTime = 0;
    if (UpdateMotor)
    {
      UpdateMotor=0;

#ifdef USE_OSD
      /* G e n e r a t e   O S D   D a t a */
      static char CntOSD = 0;
      if (CntOSD % 6 == 1)
      {
        SendOSD();
      }
      CntOSD++;
#endif

      /* Set the cycle Time to 120ms / 125ms */
      if (OldTime != 0)
      {
        while (((Count8Khz - OldTime) *10) / 8 < 120);
        DebugOut.Analog[14] = ((Count8Khz - OldTime) *10) / 8;
      }
      OldTime = Count8Khz;
     
      /* GetMeasurements()*/
      GetMeasurements();

      /* EstimateFlightAttitude */
      FlightAttitudeEstimation();

      /* Set Nominal Value */
      RemoteControl();  

      /* PD Control */
      PD_Regler();
     
      /* Send Motor Data */
      SendMotorData();
     
      /* TestRemote */
      TestRemote();
     
      /* Test IC2- / RC-Link */
      TestIC2Link();
    }
    /* Send Debug Data over RS232 */
    SendDebugData();
    /* Check the Batery for Undervoltage */
    TestBattery();
    /* DeployRescue */
    DeployRescue();
  }
}

/* ****************************************************************************
Functionname:     DeployRescue                      */
/*!
Description:       Deploy a rescue parachute using a servo

  @return           void
  @pre              -
  @post             -
  @author           Michael Walter
**************************************************************************** */

void DeployRescue()
{
  static int InvalidAttitude = 0;
  /* Yaw or pitch are greater than 90 Deg abs */
  if (((abs(status.iTheta10) > 900) || (abs(status.iPhi10) > 900)) &&
     ((abs(AverageRoll) > 400) ||
      (abs(AverageNick) > 400) ||
      (abs(AverageGier) > 400) ))
  {
    //MotorenEin = 0;
    Delay_ms(500);
    InvalidAttitude = 1;
  }
 
  if (InvalidAttitude)
  {
    ServoValue = 150;
  }
  else
  {
    ServoValue = 0;
  }
}

/* ****************************************************************************
Functionname:     ReadParameterSet                      */
/*!
Description:      -- Parametersatz aus EEPROM lesen ---
                  number [0..5]

  @return           void
  @pre              -
  @post             -
  @author           H. Buss / I. Busker
**************************************************************************** */

void ReadParameterSet(unsigned char number, unsigned char *buffer, unsigned char length)
{
  if (number > 5)
  {
    number = 5;
  }
  eeprom_read_block(buffer, &EEPromArray[EEPROM_ADR_PARAM_BEGIN + length * number], length);
}

/* ****************************************************************************
Functionname:     WriteParameterSet                      */
/*!
Description:      -- Parametersatz ins EEPROM schreiben ---
                  number [0..5]

  @return           void
  @pre              -
  @post             -
  @author           H. Buss / I. Busker
**************************************************************************** */

void WriteParameterSet(unsigned char number, unsigned char *buffer, unsigned char length)
{
  if(number > 5)
  {
    number = 5;
  }
  eeprom_write_block(buffer, &EEPromArray[EEPROM_ADR_PARAM_BEGIN + length * number], length);
  eeprom_write_byte(&EEPromArray[EEPROM_ADR_ACTIVE_SET], number);      // diesen Parametersatz als aktuell merken
}

/* ****************************************************************************
Functionname:     GetActiveParamSetNumber                      */
/*!
Description:      

  @return           void
  @pre              -
  @post             -
  @author           H. Buss / I. Busker
**************************************************************************** */

unsigned char GetActiveParamSetNumber(void)
{
  unsigned char set;
  set = eeprom_read_byte(&EEPromArray[EEPROM_ADR_ACTIVE_SET]);
  if(set > 5)
  {
    set = 2;  
    eeprom_write_byte(&EEPromArray[EEPROM_ADR_ACTIVE_SET], set);      // diesen Parametersatz als aktuell merken
  }
  return(set);
}

/* ****************************************************************************
Functionname:     GetAirPressureOffset                      */
/*!
Description:      

  @return           void
  @pre              -
  @post             -
  @author           H. Buss / I. Busker
**************************************************************************** */

void GetAirPressureOffset(void)
{
 unsigned int timer;
 ReadParameterSet(GetActiveParamSetNumber(), (unsigned char *) &EE_Parameter.Kanalbelegung[0], STRUCT_PARAM_LAENGE);
  printf("\n\rBenutze Parametersatz %d", GetActiveParamSetNumber());
  if(EE_Parameter.GlobalConfig & CFG_HOEHENREGELUNG)
  {
    printf("\n\rAbgleich Luftdrucksensor..");
    timer = SetDelay(1000);  
    SucheLuftruckOffset();
    while (!CheckDelay(timer));
    printf("OK\n\r");
  }
}

/* ****************************************************************************
Functionname:     GenerateDefaults                      */
/*!
Description:      Generate the Default Paramter

  @return           void
  @pre              -
  @post             -
  @author           H. Buss / I. Busker
**************************************************************************** */

void  GenerateDefaults()
{
  VersionInfo.Hauptversion = VERSION_HAUPTVERSION;
  VersionInfo.Nebenversion = VERSION_NEBENVERSION;
  VersionInfo.PCKompatibel = VERSION_KOMPATIBEL;
 
#define EE_DATENREVISION 66 // wird angepasst, wenn sich die EEPROM-Daten geändert haben
  if(eeprom_read_byte(&EEPromArray[EEPROM_ADR_VALID]) != EE_DATENREVISION)
  {
    printf("\n\rInit. EEPROM: Generiere Default-Parameter...");
    DefaultKonstanten1();
    for (unsigned char i=0;i<6;i++)  
    {
      if(i==2) DefaultKonstanten2(); // Kamera
      if(i==3) DefaultKonstanten3(); // Beginner
      if(i>3)  DefaultKonstanten2(); // Kamera
      WriteParameterSet(i, (unsigned char *) &EE_Parameter.Kanalbelegung[0], STRUCT_PARAM_LAENGE);
    }
    eeprom_write_byte(&EEPromArray[EEPROM_ADR_ACTIVE_SET], 3); // default-Setting
    eeprom_write_byte(&EEPromArray[EEPROM_ADR_VALID], EE_DATENREVISION);
  }
}


/* ****************************************************************************
Functionname:     InitPorts                      */
/*!
Description:      Init the IO Ports

  @return           void
  @pre              -
  @post             -
  @author           H. Buss / I. Busker
**************************************************************************** */

void  InitPorts()
{
  unsigned int timer = 0;
  DDRB  = 0x00;
  PORTB = 0x00;
  for(timer = 0; timer < 1000; timer++); // verzögern
  DDRC  = 0x81; // SCL
  PORTC = 0xff; // Pullup SDA
  DDRB  = 0x1B; // LEDs und Druckoffset
  PORTB = 0x01; // LED_Rot
  DDRD  = 0x3E; // Speaker & TXD & J3 J4 J5
  DDRD  |=0x80; // J7
  PORTD = 0xF7; // LED
 
  MCUSR &=~(1<<WDRF);
  WDTCSR |= (1<<WDCE)|(1<<WDE);
  WDTCSR = 0;
}

/* ****************************************************************************
Functionname:     TestIC2Link                      */
/*!
Description:      Test IC2- / RC-Link

  @return           void
  @pre              -
  @post             -
  @author           H. Buss / I. Busker
**************************************************************************** */

void TestIC2Link()
{
  if(PcZugriff)
  {
    PcZugriff--;
  }
 
  if(SenderOkay)  
  {
    SenderOkay--;
  }
 
  if(!I2CTimeout)
  {
    I2CTimeout = 5;
    i2c_reset();
    if((BeepMuster == 0xffff) && MotorenEin)
    {
      beeptime = 10000;
      BeepMuster = 0x0080;
    }
  }
  else
  {
    I2CTimeout--;
  }
}


/* ****************************************************************************
Functionname:     SendDebugData                      */
/*!
Description:      Send Debug Data over RS232

  @return           void
  @pre              -
  @post             -
  @author           H. Buss / I. Busker
**************************************************************************** */

void SendDebugData()
{
  if(SIO_DEBUG)
  {
    DatenUebertragung();
    BearbeiteRxDaten();
  }
  else
  {
    BearbeiteRxDaten();
  }
}


/* ****************************************************************************
Functionname:     TestBattery                      */
/*!
Description:      Check the Battery Voltage

  @return           void
  @pre              -
  @post             -
  @author           H. Buss / I. Busker
**************************************************************************** */

void  TestBattery()
{
  unsigned int timer = 0;
  if(CheckDelay(timer))
  {  /* Voltage is Below Threshhod ? */
    if(UBat < EE_Parameter.UnterspannungsWarnung)
    {    
      if(BeepMuster == 0xffff)
      {
        beeptime = 6000;
        BeepMuster = 0x0300;
      }
    }
    timer = SetDelay(100);  
  }
  DebugOut.Analog[15] =  UBat;
}

/* ****************************************************************************
  Functionname:     TestRemote                      */
/*!
  Description:      

  @param[in]        

  @return           void
  @pre              -
  @post             -
  @author         Michael Walter  
**************************************************************************** */

void TestRemote()
{
  /*--- (SYMBOLIC) CONSTANTS ---*/
 
  /*--- VARIABLES ---*/
  static unsigned int TimeSinceRC_BelowThreshhold = 0;
  static unsigned int TimeSinceRC_AboveThreshhold = 0;
 
  if (MotorenEin == 1)
  {
    if (RemoteLinkLost == 0)
    {
      if (RCQuality < 60)
      {
        if (TimeSinceRC_BelowThreshhold < 10000)
        {
          TimeSinceRC_BelowThreshhold++;
        }
      }
      else
      {
        TimeSinceRC_BelowThreshhold = 0;
      }
      if ((TimeSinceRC_BelowThreshhold > 500) || /* aprox. 5 seconds */
        (SenderOkay < 100))
      {
        RemoteLinkLost = 1;
        TimeSinceRC_AboveThreshhold = 0;
      }
    }
    else
    {
      if (RCQuality > 80)
      {
        if (TimeSinceRC_AboveThreshhold < 10000)
        {
          TimeSinceRC_AboveThreshhold++;
        }
      }
      else
      {
        TimeSinceRC_AboveThreshhold = 0;
      }
      if (TimeSinceRC_AboveThreshhold > 100) /* aprox. 1 seconds */
      {
        RemoteLinkLost = 0;
        TimeSinceRC_BelowThreshhold = 0;    
      }
    }
  }
  else
  {
    RemoteLinkLost = 0;
    TimeSinceRC_BelowThreshhold = 0;
    TimeSinceRC_AboveThreshhold = 0;
  }
  /*DebugOut.Analog[14] = TimeSinceRC_BelowThreshhold;*/
  /*DebugOut.Analog[15] = TimeSinceRC_AboveThreshhold;*/
}