336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.
졸업작품 의뢰는 instructables.tistory.com/64 로...
드론 하드웨어 관련 스팩은 https://instructables.tistory.com/662 로 넘어오시면 됩니다.

드론제작 의뢰하는 분이 없어서 아직 만들어놓은 영상이 없네요
(홈플러스에서 파는 드론가격을 제시하곤해서 그냥 웃음만 나옵니다 ^^)

키트 문의 주셔도 됩니다. (250 드론 키트도 갖고있습니다.)

드론전용 충전기 구매도 가능하니 문의주세요

드론은 Body크기와 Motor의 스팩이 중요합니다.


편하게 댓글이나 ▲위 페이지로 넘어오셔서 메세지 주세요.

아래 코드는 다두이노 제품의 참고코드입니다. (의뢰받고 따로 제작합니다.)




Favicon of m.search.naver.com [아두이노 드론키트]

Favicon of search.daum.net [아두이노 키트]

Favicon of search.naver.com [아두이노 드론 코드]

Favicon of search.naver.com [아두이노 드론 소스코드]

Favicon of search.naver.com [아두이노 드론소스]

Favicon of search.naver.com [드론코드]

Favicon of search.naver.com [아두이노 드론]

Favicon of m.search.naver.com [드론키트]

Favicon of m.search.naver.com [아두이노드론]

Favicon of m.search.daum.net [아두이노 드론]

Favicon of search.naver.com [드론 이륙소스]

Favicon of m.search.naver.com [드론 코드]

Favicon of m.search.naver.com [드론 아두이노]

Favicon of m.search.naver.com [드론50000]

Favicon of m.search.naver.com [드론 킷트]

[hmc1 드론]

[아두이노 i2c gps]

[eeprom layout]

[코드이노키트] :: ▶LINK  개별문의 댓글 남겨주세요

[아두이노 드론 키트]

[아두이노 PID 코드]

[아두이노 키트 홈플러스] ::  아래 링크를 통해서 구매해주세요~


bing[드론 아두이노 코드]





▼여기 통해서 바로 구매해주세요~





11111

11111






▼ Code File Link

http://instructables.tistory.com/723













/*

MultiWiiCopter by Alexandre Dubus

www.multiwii.com

March  2013     V2.2

 This program is free software: you can redi stribute it and/or modify

 it under the terms of the GNU General Public License as published by

 the Free Software Foundation, either version 3 of the License, or

 any later version. see <http://www.gnu.org/licenses/>

*/


#include <avr/io.h>

#include <Wire.h>


#include "config.h"        //추가할것

#include "def.h"


#include <avr/pgmspace.h>

#define  VERSION  220


#if defined(AIR)

volatile uint16_t serialRcValue[RC_CHANS] 

= {1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502}; 

uint8_t flightState = 0;

#endif


/*********** RC alias *****************/

enum rc 

{

  ROLL,                    //Y축 회전

  PITCH,                   //X축 회전

  YAW,                    //Z축 회전

  THROTTLE,            //이륙,착륙 담당

  AUX1,

  AUX2,

  AUX3,

  AUX4

};


enum pid 

{

  PIDROLL,

  PIDPITCH,

  PIDYAW,

  PIDALT,

  PIDPOS,

  PIDPOSR,

  PIDNAVR,

  PIDLEVEL,

  PIDMAG,

  PIDVEL,     // not used currently

  PIDITEMS

};


const char pidnames[] PROGMEM =

  "ROLL;"

  "PITCH;"

  "YAW;"

  "ALT;"

  "Pos;"

  "PosR;"

  "NavR;"

  "LEVEL;"

  "MAG;"

  "VEL;"

;


enum box 

{

  BOXARM,

  #if ACC

    BOXANGLE,

    BOXHORIZON,

  #endif


  #if BARO && (!defined(SUPPRESS_BARO_ALTHOLD))

    BOXBARO,

  #endif


  #ifdef VARIOMETER

    BOXVARIO,

  #endif


  #if MAG

    BOXMAG,

    BOXHEADFREE,

    BOXHEADADJ, // acquire heading for HEADFREE mode

  #endif


  #if defined(SERVO_TILT) || defined(GIMBAL)  || defined(SERVO_MIX_TILT)

    BOXCAMSTAB,

  #endif


  #if defined(CAMTRIG)

    BOXCAMTRIG,

  #endif


  #if GPS

    BOXGPSHOME,

    BOXGPSHOLD,

  #endif


  #if defined(FIXEDWING) || defined(HELICOPTER)

    BOXPASSTHRU,

  #endif


  #if defined(BUZZER)

    BOXBEEPERON,

  #endif


  #if defined(LED_FLASHER)

    BOXLEDMAX, // we want maximum illumination

    BOXLEDLOW, // low/no lights

  #endif


  #if defined(LANDING_LIGHTS_DDR)

    BOXLLIGHTS, // enable landing lights at any altitude

  #endif


  #ifdef INFLIGHT_ACC_CALIBRATION

    BOXCALIB,

  #endif


  #ifdef GOVERNOR_P

    BOXGOV,

  #endif


  #ifdef OSD_SWITCH

    BOXOSD,

  #endif


  CHECKBOXITEMS

};




const char boxnames[] PROGMEM = // names for dynamic generation of config GUI

  "ARM;"

  #if ACC

    "ANGLE;"

    "HORIZON;"

  #endif


  #if BARO && (!defined(SUPPRESS_BARO_ALTHOLD))

    "BARO;"

  #endif


  #ifdef VARIOMETER

    "VARIO;"

  #endif


  #if MAG                //Sensors.ino 안에 MAG

    "MAG;"

    "HEADFREE;"

    "HEADADJ;"  

  #endif


  #if defined(SERVO_TILT) || defined(GIMBAL)|| defined(SERVO_MIX_TILT)

    "CAMSTAB;"

  #endif



  #if defined(CAMTRIG)        //CAM Trig 정의

    "CAMTRIG;"

  #endif


  #if GPS

    "GPS HOME;"                //GPS.ino 안에서 GPS_HOME_MODE 로 쓰인다.

    "GPS HOLD;"

  #endif


  #if defined(FIXEDWING) || defined(HELICOPTER)

    "PASSTHRU;"

  #endif


  #if defined(BUZZER)        //Alarms.ino 안에서 Buzzer로 쓰인다.

    "BEEPER;"

  #endif


  #if defined(LED_FLASHER)

    "LEDMAX;"

    "LEDLOW;"

  #endif


  #if defined(LANDING_LIGHTS_DDR)

    "LLIGHTS;"

  #endif


  #ifdef INFLIGHT_ACC_CALIBRATION

    "CALIB;"

  #endif


  #ifdef GOVERNOR_P

    "GOVERNOR;"

  #endif


  #ifdef OSD_SWITCH

    "OSD SW;"

  #endif

;




const uint8_t boxids[] PROGMEM = {// permanent IDs associated to boxes. This way, you can rely on an ID number to identify a BOX function.

  0, //"ARM;"

  #if ACC

    1, //"ANGLE;"

    2, //"HORIZON;"

  #endif


  #if BARO && (!defined(SUPPRESS_BARO_ALTHOLD))

    3, //"BARO;"

  #endif


  #ifdef VARIOMETER

    4, //"VARIO;"

  #endif


  #if MAG

    5, //"MAG;"

    6, //"HEADFREE;"

    7, //"HEADADJ;"  

  #endif


  #if defined(SERVO_TILT) || defined(GIMBAL)|| defined(SERVO_MIX_TILT)

    8, //"CAMSTAB;"

  #endif


  #if defined(CAMTRIG)

    9, //"CAMTRIG;"

  #endif


  #if GPS

    10, //"GPS HOME;"

    11, //"GPS HOLD;"

  #endif


  #if defined(FIXEDWING) || defined(HELICOPTER)

    12, //"PASSTHRU;"

  #endif


  #if defined(BUZZER)

    13, //"BEEPER;"

  #endif


  #if defined(LED_FLASHER)

    14, //"LEDMAX;"

    15, //"LEDLOW;"

  #endif


  #if defined(LANDING_LIGHTS_DDR)

    16, //"LLIGHTS;"

  #endif


  #ifdef INFLIGHT_ACC_CALIBRATION

    17, //"CALIB;"

  #endif


  #ifdef GOVERNOR_P

    18, //"GOVERNOR;"

  #endif


  #ifdef OSD_SWITCH

    19, //"OSD_SWITCH;"

  #endif

};



static uint32_t currentTime = 0;

static uint16_t previousTime = 0;

static uint16_t cycleTime = 0;     // this is the number in micro second to achieve a full loop, it can differ a little and is taken into account in the PID loop

static uint16_t calibratingA = 0;  // the calibration is done in the main loop. Calibrating decreases at each cycle down to 0, then we enter in a normal mode.

static uint16_t calibratingB = 0;  // baro calibration = get new ground pressure value

static uint16_t calibratingG;

static uint16_t acc_1G;            // this is the 1G measured acceleration

static uint16_t acc_25deg;

static int16_t  gyroADC[3],accADC[3],accSmooth[3],magADC[3];

static int16_t  heading,magHold,headFreeModeHold; // [-180;+180]

static uint8_t  vbat;                   // battery voltage in 0.1V steps

static uint8_t  vbatMin = VBATNOMINAL;  // lowest battery voltage in 0.1V steps

static uint8_t  rcOptions[CHECKBOXITEMS];

static int32_t  BaroAlt,EstAlt,AltHold; // in cm

static int16_t  BaroPID = 0;

static int16_t  errorAltitudeI = 0;

static int16_t  vario = 0;              // variometer in cm/s


#if defined(ARMEDTIMEWARNING)

  static uint32_t  ArmedTimeWarningMicroSeconds = 0;

#endif


static int16_t  debug[4];

static int16_t  sonarAlt; //to think about the unit


//-------------------------------------------------------------------------

// Calibration flag value

uint8_t calibration_flag;

//-------------------------------------------------------------------------


struct flags_struct {

  uint8_t OK_TO_ARM :1 ;

  uint8_t ARMED :1 ;

  uint8_t I2C_INIT_DONE :1 ; // For i2c gps we have to now when i2c init is done, so we can update parameters to the i2cgps from eeprom (at startup it is done in setup())

  uint8_t ACC_CALIBRATED :1 ;

  uint8_t NUNCHUKDATA :1 ;

  uint8_t ANGLE_MODE :1 ;

  uint8_t HORIZON_MODE :1 ;

  uint8_t MAG_MODE :1 ;

  uint8_t BARO_MODE :1 ;

  uint8_t GPS_HOME_MODE :1 ;

  uint8_t GPS_HOLD_MODE :1 ;

  uint8_t HEADFREE_MODE :1 ;

  uint8_t PASSTHRU_MODE :1 ;

  uint8_t GPS_FIX :1 ;

  uint8_t GPS_FIX_HOME :1 ;

  uint8_t SMALL_ANGLES_25 :1 ;

  uint8_t CALIBRATE_MAG :1 ;

  uint8_t VARIO_MODE :1;

} f;


//for log

#if defined(LOG_VALUES) || defined(LCD_TELEMETRY)

  static uint16_t cycleTimeMax = 0;       // highest ever cycle timen

  static uint16_t cycleTimeMin = 65535;   // lowest ever cycle timen

  static uint16_t powerMax = 0;           // highest ever current;

  static int32_t  BAROaltMax;         // maximum value

#endif

#if defined(LOG_VALUES) || defined(LCD_TELEMETRY) || defined(ARMEDTIMEWARNING)  || defined(LOG_PERMANENT)

  static uint32_t armedTime = 0;

#endif


static int16_t  i2c_errors_count = 0;

static int16_t  annex650_overrun_count = 0;


// **********************

//Automatic ACC Offset Calibration

// **********************

#if defined(INFLIGHT_ACC_CALIBRATION)

  static uint16_t InflightcalibratingA = 0;

  static int16_t AccInflightCalibrationArmed;

  static uint16_t AccInflightCalibrationMeasurementDone = 0;

  static uint16_t AccInflightCalibrationSavetoEEProm = 0;

  static uint16_t AccInflightCalibrationActive = 0;

#endif


// **********************

// power meter

// **********************

#if defined(POWERMETER)

#define PMOTOR_SUM 8                     // index into pMeter[] for sum

  static uint32_t pMeter[PMOTOR_SUM + 1];  // we use [0:7] for eight motors,one extra for sum

  static uint8_t pMeterV;                  // dummy to satisfy the paramStruct logic in ConfigurationLoop()

  static uint32_t pAlarm;                  // we scale the eeprom value from [0:255] to this value we can directly compare to the sum in pMeter[6]

  static uint16_t powerValue = 0;          // last known current

#endif

static uint16_t intPowerMeterSum, intPowerTrigger1;


// **********************

// telemetry

// **********************

#if defined(LCD_TELEMETRY)

  static uint8_t telemetry = 0;

  static uint8_t telemetry_auto = 0;

#endif

#ifdef LCD_TELEMETRY_STEP

  static char telemetryStepSequence []  = LCD_TELEMETRY_STEP;

  static uint8_t telemetryStepIndex = 0;

#endif


// ******************

// rc functions

// ******************

#define MINCHECK 1100

#define MAXCHECK 1900


#define ROL_LO  (1<<(2*ROLL))

#define ROL_CE  (3<<(2*ROLL))

#define ROL_HI  (2<<(2*ROLL))

#define PIT_LO  (1<<(2*PITCH))

#define PIT_CE  (3<<(2*PITCH))

#define PIT_HI  (2<<(2*PITCH))

#define YAW_LO  (1<<(2*YAW))

#define YAW_CE  (3<<(2*YAW))

#define YAW_HI  (2<<(2*YAW))

#define THR_LO  (1<<(2*THROTTLE))

#define THR_CE  (3<<(2*THROTTLE))

#define THR_HI  (2<<(2*THROTTLE))


static int16_t failsafeEvents = 0;

volatile int16_t failsafeCnt = 0;


static int16_t rcData[RC_CHANS];    // interval [1000;2000]

static int16_t rcCommand[4];        // interval [1000;2000] for THROTTLE and [-500;+500] for ROLL/PITCH/YAW 

static int16_t lookupPitchRollRC[6];// lookup table for expo & RC rate PITCH+ROLL

static int16_t lookupThrottleRC[11];// lookup table for expo & mid THROTTLE

static uint16_t rssi;               // range: [0;1023]


#if defined(SPEKTRUM)

  volatile uint8_t  spekFrameFlags;

  volatile uint32_t spekTimeLast;

#endif


#if defined(OPENLRSv2MULTI)

  static uint8_t pot_P,pot_I; // OpenLRS onboard potentiometers for P and I trim or other usages

#endif


// **************

// gyro+acc IMU

// **************

static int16_t gyroData[3] = {0,0,0};

static int16_t gyroZero[3] = {0,0,0};

static int16_t angle[2]    = {0,0};  // absolute angle inclination in multiple of 0.1 degree    180 deg = 1800


// *************************

// motor and servo functions

// *************************

static int16_t axisPID[3];

static int16_t motor[NUMBER_MOTOR];

#if defined(SERVO)

  static int16_t servo[8] = {1500,1500,1500,1500,1500,1500,1500,1500};

#endif


// ************************

// EEPROM Layout definition

// ************************

static uint8_t dynP8[3], dynD8[3];


static struct {

  uint8_t currentSet;

  int16_t accZero[3];

  int16_t magZero[3];

  uint8_t checksum;      // MUST BE ON LAST POSITION OF STRUCTURE ! 

} global_conf;



static struct {

  uint8_t checkNewConf;

  uint8_t P8[PIDITEMS], I8[PIDITEMS], D8[PIDITEMS];

  uint8_t rcRate8;

  uint8_t rcExpo8;

  uint8_t rollPitchRate;

  uint8_t yawRate;

  uint8_t dynThrPID;

  uint8_t thrMid8;

  uint8_t thrExpo8;

  int16_t angleTrim[2];

  uint16_t activate[CHECKBOXITEMS];

  uint8_t powerTrigger1;

  #ifdef FLYING_WING

    uint16_t wing_left_mid;

    uint16_t wing_right_mid;

  #endif

  #ifdef TRI

    uint16_t tri_yaw_middle;

  #endif

  #if defined HELICOPTER || defined(AIRPLANE)|| defined(SINGLECOPTER)|| defined(DUALCOPTER)

    int16_t servoTrim[8];

  #endif

  #if defined(GYRO_SMOOTHING)

    uint8_t Smoothing[3];

  #endif

  #if defined (FAILSAFE)

    int16_t failsafe_throttle;

  #endif

  #ifdef VBAT

    uint8_t vbatscale;

    uint8_t vbatlevel_warn1;

    uint8_t vbatlevel_warn2;

    uint8_t vbatlevel_crit;

    uint8_t no_vbat;

  #endif

  #ifdef POWERMETER

    uint16_t psensornull;

    uint16_t pleveldivsoft;

    uint16_t pleveldiv;

    uint8_t pint2ma;

  #endif

  #ifdef CYCLETIME_FIXATED

    uint16_t cycletime_fixated;

  #endif

  #ifdef MMGYRO

    uint8_t mmgyro;

  #endif

  #ifdef ARMEDTIMEWARNING

    uint16_t armedtimewarning;

  #endif

  int16_t minthrottle;

  #ifdef GOVERNOR_P

   int16_t governorP;

   int16_t governorD;

   int8_t  governorR;

  #endif

  uint8_t  checksum;      // MUST BE ON LAST POSITION OF CONF STRUCTURE ! 

} conf;


#ifdef LOG_PERMANENT

static struct 

{

  uint16_t arm;           // #arm events

  uint16_t disarm;        // #disarm events

  uint16_t start;         // #powercycle/reset/initialize events

  uint32_t armed_time ;   // copy of armedTime @ disarm

  uint32_t lifetime;      // sum (armed) lifetime in seconds

  uint16_t failsafe;      // #failsafe state @ disarm

  uint16_t i2c;           // #i2c errs state @ disarm

  uint8_t  running;       // toggle on arm & disarm to monitor for clean shutdown vs. powercut

  uint8_t  checksum;      // MUST BE ON LAST POSITION OF CONF STRUCTURE !

} plog;

#endif


// **********************

// GPS common variables

// **********************

  static int32_t  GPS_coord[2];

  static int32_t  GPS_home[2];

  static int32_t  GPS_hold[2];

  static uint8_t  GPS_numSat;

  static uint16_t GPS_distanceToHome;                          // distance to home  - unit: meter

  static int16_t  GPS_directionToHome;                         // direction to home - unit: degree

  static uint16_t GPS_altitude;                                // GPS altitude      - unit: meter

  static uint16_t GPS_speed;                                   // GPS speed         - unit: cm/s

  static uint8_t  GPS_update = 0;                              // a binary toogle to distinct a GPS position update

  static int16_t  GPS_angle[2] = { 0, 0};                      // the angles that must be applied for GPS correction

  static uint16_t GPS_ground_course = 0;                       //                   - unit: degree*10

  static uint8_t  GPS_Present = 0;                             // Checksum from Gps serial

  static uint8_t  GPS_Enable  = 0;


  #define LAT  0

  #define LON  1

  // The desired bank towards North (Positive) or South (Negative) : latitude

  // The desired bank towards East (Positive) or West (Negative)   : longitude

  static int16_t  nav[2];

  static int16_t  nav_rated[2];    //Adding a rate controller to the navigation to make it smoother


  // default POSHOLD control gains

  #define POSHOLD_P              .11

  #define POSHOLD_I              0.0

  #define POSHOLD_IMAX           20        // degrees


  #define POSHOLD_RATE_P         2.0

  #define POSHOLD_RATE_I         0.08      // Wind control

  #define POSHOLD_RATE_D         0.045     // try 2 or 3 for POSHOLD_RATE 1

  #define POSHOLD_RATE_IMAX      20        // degrees


  // default Navigation PID gains

  #define NAV_P                  1.4

  #define NAV_I                  0.20      // Wind control

  #define NAV_D                  0.08      //

  #define NAV_IMAX               20        // degrees


  /////////////////////////////////////////////////////////////////////////////////////////////////////////////

  // Serial GPS only variables

  //navigation mode

  #define NAV_MODE_NONE          0

  #define NAV_MODE_POSHOLD       1

  #define NAV_MODE_WP            2

  static uint8_t nav_mode = NAV_MODE_NONE; // Navigation mode

 

  static uint8_t alarmArray[16];           // array

 

#if BARO

  static int32_t baroPressure;

  static int32_t baroTemperature;

  static int32_t baroPressureSum;

#endif



void annexCode() { // this code is excetuted at each loop and won't interfere with control loop if it lasts less than 650 microseconds

  static uint32_t calibratedAccTime;

  uint16_t tmp,tmp2;

  uint8_t axis,prop1,prop2;


  #define BREAKPOINT 1500

  // PITCH & ROLL only dynamic PID adjustemnt,  depending on throttle value

  if (rcData[THROTTLE]<BREAKPOINT) {

    prop2 = 100;

  } else {

    if (rcData[THROTTLE]<2000) {

      prop2 = 100 - (uint16_t)conf.dynThrPID*(rcData[THROTTLE]-BREAKPOINT)/(2000-BREAKPOINT);

    } else {

      prop2 = 100 - conf.dynThrPID;

    }

  }


  for(axis=0;axis<3;axis++) {

    tmp = min(abs(rcData[axis]-MIDRC),500);

    #if defined(DEADBAND)

      if (tmp>DEADBAND) { tmp -= DEADBAND; }

      else { tmp=0; }

    #endif

    if(axis!=2) { //ROLL & PITCH

      tmp2 = tmp/100;

      rcCommand[axis] = lookupPitchRollRC[tmp2] + (tmp-tmp2*100) * (lookupPitchRollRC[tmp2+1]-lookupPitchRollRC[tmp2]) / 100;

      prop1 = 100-(uint16_t)conf.rollPitchRate*tmp/500;

      prop1 = (uint16_t)prop1*prop2/100;

    } else {      // YAW

      rcCommand[axis] = tmp;

      prop1 = 100-(uint16_t)conf.yawRate*tmp/500;

    }

    dynP8[axis] = (uint16_t)conf.P8[axis]*prop1/100;

    dynD8[axis] = (uint16_t)conf.D8[axis]*prop1/100;

    if (rcData[axis]<MIDRC) rcCommand[axis] = -rcCommand[axis];

  }

  tmp = constrain(rcData[THROTTLE],MINCHECK,2000);

  tmp = (uint32_t)(tmp-MINCHECK)*1000/(2000-MINCHECK); // [MINCHECK;2000] -> [0;1000]

  tmp2 = tmp/100;

  rcCommand[THROTTLE] = lookupThrottleRC[tmp2] + (tmp-tmp2*100) * (lookupThrottleRC[tmp2+1]-lookupThrottleRC[tmp2]) / 100; // [0;1000] -> expo -> [conf.minthrottle;MAXTHROTTLE]


  if(f.HEADFREE_MODE) { //to optimize

    float radDiff = (heading - headFreeModeHold) * 0.0174533f; // where PI/180 ~= 0.0174533

    float cosDiff = cos(radDiff);

    float sinDiff = sin(radDiff);

    int16_t rcCommand_PITCH = rcCommand[PITCH]*cosDiff + rcCommand[ROLL]*sinDiff;

    rcCommand[ROLL] =  rcCommand[ROLL]*cosDiff - rcCommand[PITCH]*sinDiff; 

    rcCommand[PITCH] = rcCommand_PITCH;

  }


  #if defined(POWERMETER_HARD)

    uint16_t pMeterRaw;               // used for current reading

    static uint16_t psensorTimer = 0;

    if (! (++psensorTimer % PSENSORFREQ)) {

      pMeterRaw =  analogRead(PSENSORPIN);

      //lcdprint_int16(pMeterRaw); LCDcrlf();

      powerValue = ( conf.psensornull > pMeterRaw ? conf.psensornull - pMeterRaw : pMeterRaw - conf.psensornull); // do not use abs(), it would induce implicit cast to uint and overrun

      if ( powerValue < 333) {  // only accept reasonable values. 333 is empirical

      #ifdef LCD_TELEMETRY

        if (powerValue > powerMax) powerMax = powerValue;

      #endif

      } else {

        powerValue = 333;

      }        

      pMeter[PMOTOR_SUM] += (uint32_t) powerValue;

    }

  #endif

  #if defined(BUZZER)

    #if defined(VBAT)

      static uint8_t vbatTimer = 0;

      static uint8_t ind = 0;

      uint16_t vbatRaw = 0;

      static uint16_t vbatRawArray[8];

      if (! (++vbatTimer % VBATFREQ)) {

        vbatRawArray[(ind++)%8] = analogRead(V_BATPIN);

        for (uint8_t i=0;i<8;i++) vbatRaw += vbatRawArray[i];

        vbat = (vbatRaw*2) / conf.vbatscale; // result is Vbatt in 0.1V steps

      }

    #endif

    alarmHandler(); // external buzzer routine that handles buzzer events globally now

  #endif  


  #if defined(RX_RSSI)

    static uint8_t sig = 0;

    uint16_t rssiRaw = 0;

    static uint16_t rssiRawArray[8];

    rssiRawArray[(sig++)%8] = analogRead(RX_RSSI_PIN);

    for (uint8_t i=0;i<8;i++) rssiRaw += rssiRawArray[i];

    rssi = rssiRaw / 8;       

  #endif


  if ( (calibratingA>0 && ACC ) || (calibratingG>0) ) { // Calibration phasis

    LEDPIN_TOGGLE;

  } else {

    if (f.ACC_CALIBRATED) {LEDPIN_OFF;}

    if (f.ARMED) {LEDPIN_ON;}

  }


  #if defined(LED_RING)

    static uint32_t LEDTime;

    if ( currentTime > LEDTime ) {

      LEDTime = currentTime + 50000;

      i2CLedRingState();

    }

  #endif


  #if defined(LED_FLASHER)

    auto_switch_led_flasher();

  #endif


  if ( currentTime > calibratedAccTime ) {

    if (! f.SMALL_ANGLES_25) {

      // the multi uses ACC and is not calibrated or is too much inclinated

      f.ACC_CALIBRATED = 0;

      LEDPIN_TOGGLE;

      calibratedAccTime = currentTime + 100000;

    } else {

      f.ACC_CALIBRATED = 1;

    }

  }


  #if !(defined(SPEKTRUM) && defined(PROMINI))  //Only one serial port on ProMini.  Skip serial com if Spektrum Sat in use. Note: Spek code will auto-call serialCom if GUI data detected on serial0.

    #if defined(GPS_PROMINI)

      if(GPS_Enable == 0) {serialCom();}

    #else

      serialCom();

    #endif

  #endif


  #if defined(POWERMETER)

    intPowerMeterSum = (pMeter[PMOTOR_SUM]/conf.pleveldiv);

    intPowerTrigger1 = conf.powerTrigger1 * PLEVELSCALE; 

  #endif


  #ifdef LCD_TELEMETRY_AUTO

    static char telemetryAutoSequence []  = LCD_TELEMETRY_AUTO;

    static uint8_t telemetryAutoIndex = 0;

    static uint16_t telemetryAutoTimer = 0;

    if ( (telemetry_auto) && (! (++telemetryAutoTimer % LCD_TELEMETRY_AUTO_FREQ) )  ){

      telemetry = telemetryAutoSequence[++telemetryAutoIndex % strlen(telemetryAutoSequence)];

      LCDclear(); // make sure to clear away remnants

    }

  #endif  

  #ifdef LCD_TELEMETRY

    static uint16_t telemetryTimer = 0;

    if (! (++telemetryTimer % LCD_TELEMETRY_FREQ)) {

      #if (LCD_TELEMETRY_DEBUG+0 > 0)

        telemetry = LCD_TELEMETRY_DEBUG;

      #endif

      if (telemetry) lcd_telemetry();

    }

  #endif


  #if GPS & defined(GPS_LED_INDICATOR)       // modified by MIS to use STABLEPIN LED for number of sattelites indication

    static uint32_t GPSLEDTime;              // - No GPS FIX -> LED blink at speed of incoming GPS frames

    static uint8_t blcnt;                    // - Fix and sat no. bellow 5 -> LED off

    if(currentTime > GPSLEDTime) {           // - Fix and sat no. >= 5 -> LED blinks, one blink for 5 sat, two blinks for 6 sat, three for 7 ...

      if(f.GPS_FIX && GPS_numSat >= 5) {

        if(++blcnt > 2*GPS_numSat) blcnt = 0;

        GPSLEDTime = currentTime + 150000;

        if(blcnt >= 10 && ((blcnt%2) == 0)) {STABLEPIN_ON;} else {STABLEPIN_OFF;}

      }else{

        if((GPS_update == 1) && !f.GPS_FIX) {STABLEPIN_ON;} else {STABLEPIN_OFF;}

        blcnt = 0;

      }

    }

  #endif


  #if defined(LOG_VALUES) && (LOG_VALUES >= 2)

    if (cycleTime > cycleTimeMax) cycleTimeMax = cycleTime; // remember highscore

    if (cycleTime < cycleTimeMin) cycleTimeMin = cycleTime; // remember lowscore

  #endif

  if (f.ARMED)  {

    #if defined(LCD_TELEMETRY) || defined(ARMEDTIMEWARNING) || defined(LOG_PERMANENT)

      armedTime += (uint32_t)cycleTime;

    #endif

    #if defined(VBAT)

      if ( (vbat > conf.no_vbat) && (vbat < vbatMin) ) vbatMin = vbat;

    #endif

    #ifdef LCD_TELEMETRY

      #if BARO

        if ( (BaroAlt > BAROaltMax) ) BAROaltMax = BaroAlt;

      #endif

    #endif

  }

}



void setup()

{

 #if !defined(GPS_PROMINI)

SerialOpen(0,SERIAL0_COM_SPEED);

    #if defined(PROMICRO)

SerialOpen(1,SERIAL1_COM_SPEED);

    #endif

    #if defined(MEGA)

SerialOpen(1,SERIAL1_COM_SPEED);

SerialOpen(2,SERIAL2_COM_SPEED);

SerialOpen(3,SERIAL3_COM_SPEED);

    #endif

  #endif

LEDPIN_PINMODE;

POWERPIN_PINMODE;

BUZZERPIN_PINMODE;

STABLEPIN_PINMODE;

POWERPIN_OFF;

initOutput();

  #ifdef MULTIPLE_CONFIGURATION_PROFILES

for(global_conf.currentSet=0; global_conf.currentSet<3; global_conf.currentSet++) {  // check all settings integrity

readEEPROM();

}

  #else

global_conf.currentSet=0;

readEEPROM();

  #endif

readGlobalSet();

readEEPROM();   // load current setting data

blinkLED(2,40,global_conf.currentSet+1);

configureReceiver();

  #if defined (PILOTLAMP) 

PL_INIT;

  #endif

  #if defined(OPENLRSv2MULTI)

initOpenLRS();

  #endif

initSensors();

  #if defined(I2C_GPS) || defined(GPS_SERIAL) || defined(GPS_FROM_OSD)

GPS_set_pids();

  #endif

previousTime = micros();

  #if defined(GIMBAL)

calibratingA = 512;

  #endif

calibratingG = 512;

calibratingB = 200;  // 10 seconds init_delay + 200 * 25 ms = 15 seconds before ground pressure settles

  #if defined(POWERMETER)

for(uint8_t i=0;i<=PMOTOR_SUM;i++)

pMeter[i]=0;

  #endif

/************************************/

  #if defined(GPS_SERIAL)

GPS_SerialInit();

for(uint8_t i=0;i<=5;i++){

GPS_NewData(); 

LEDPIN_ON

delay(20);

LEDPIN_OFF

delay(80);

}

if(!GPS_Present){

SerialEnd(GPS_SERIAL);

SerialOpen(0,SERIAL0_COM_SPEED);

}

    #if !defined(GPS_PROMINI)

GPS_Present = 1;

    #endif

GPS_Enable = GPS_Present;  

  #endif

/************************************/

 

  #if defined(I2C_GPS) || defined(TINY_GPS) || defined(GPS_FROM_OSD)

GPS_Enable = 1;

  #endif

 

  #if defined(LCD_ETPP) || defined(LCD_LCD03) || defined(OLED_I2C_128x64) || defined(LCD_TELEMETRY_STEP)

initLCD();

  #endif

  #ifdef LCD_TELEMETRY_DEBUG

telemetry_auto = 1;

  #endif

  #ifdef LCD_CONF_DEBUG

configurationLoop();

  #endif

  #ifdef LANDING_LIGHTS_DDR

init_landing_lights();

  #endif

ADCSRA |= _BV(ADPS2) ; ADCSRA &= ~_BV(ADPS1); ADCSRA &= ~_BV(ADPS0); // this speeds up analogRead without loosing too much resolution: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1208715493/11

  #if defined(LED_FLASHER)

init_led_flasher();

led_flasher_set_sequence(LED_FLASHER_SEQUENCE);

  #endif

f.SMALL_ANGLES_25=1; // important for gyro only conf

  #ifdef LOG_PERMANENT

// read last stored set

readPLog();

plog.lifetime += plog.armed_time / 1000000;

plog.start++;  // #powercycle/reset/initialize events

// dump plog data to terminal

    #ifdef LOG_PERMANENT_SHOW_AT_STARTUP

dumpPLog(0);

    #endif

plog.armed_time = 0;   // lifetime in seconds

//plog.running = 0;  // toggle on arm & disarm to monitor for clean shutdown vs. powercut

  #endif


    pinMode(7,OUTPUT);

    digitalWrite(7,LOW);

  

debugmsg_append_str("initialization completed\n");

}


//------------------------------------------------------------------

void calibration_fun(void)

{

calibratingG = 512;

  #if GPS 

GPS_reset_home_position();

  #endif

  #if BARO

calibratingB = 10;  // calibrate baro to new ground level (10 * 25 ms = ~250 ms non blocking)

  #endif

}

//------------------------------------------------------------------


// Unlock function

void go_arm() {

  

  if(calibratingG == 0 && f.ACC_CALIBRATED 

  #if defined(FAILSAFE)

   // && failsafeCnt < 2

  #endif

    ) {

    if(!f.ARMED) { // arm now!

      digitalWrite(7,HIGH);

      delay(200);

      digitalWrite(7,LOW);

      f.ARMED = 1;

      

      flightState = flightState | 0x80;

      

      headFreeModeHold = heading;

      #if defined(VBAT)

        if (vbat > conf.no_vbat) vbatMin = vbat;

      #endif

      #ifdef LCD_TELEMETRY // reset some values when arming

        #if BARO

           BAROaltMax = BaroAlt;

        #endif

      #endif

      #ifdef LOG_PERMANENT

        plog.arm++;           // #arm events

        plog.running = 1;       // toggle on arm & disarm to monitor for clean shutdown vs. powercut

        // write now.

        writePLog();

      #endif

    }

  } else if(!f.ARMED) { 

    blinkLED(2,255,1);

    alarmArray[8] = 1;

  }

  

  if (calibration_flag == 0) {

    calibration_flag = 1;

    calibration_fun();

  }

}


// Unlock function

void go_disarm() {

  

  if (f.ARMED) {

    digitalWrite(7,HIGH);

    delay(200);

    digitalWrite(7,LOW);

    f.ARMED = 0;

    

    flightState = flightState & 0x7f;

    

    #ifdef LOG_PERMANENT

      plog.disarm++;        // #disarm events

      plog.armed_time = armedTime ;   // lifetime in seconds

      if (failsafeEvents) plog.failsafe++;      // #acitve failsafe @ disarm

      if (i2c_errors_count > 10) plog.i2c++;           // #i2c errs @ disarm

      plog.running = 0;       // toggle @ arm & disarm to monitor for clean shutdown vs. powercut

      // write now.

      writePLog();

    #endif

  }

}

void servos2Neutral() {

  #ifdef TRI

    servo[5] = 1500; // we center the yaw servo in conf mode

    writeServos();

  #endif

  #ifdef FLYING_WING

    servo[0]  = conf.wing_left_mid;

    servo[1]  = conf.wing_right_mid;

    writeServos();

  #endif

  #ifdef AIRPLANE

    for(uint8_t i = 4; i<7 ;i++) servo[i] = 1500;

    writeServos();

  #endif

  #ifdef HELICOPTER

    servo[5] = YAW_CENTER;

    servo[3] = servo[4] = servo[6] = 1500;

    writeServos();

  #endif

}


// ******** Main Loop *********

void loop () {

  static uint8_t rcDelayCommand; // this indicates the number of time (multiple of RC measurement at 50Hz) the sticks must be maintained to run or switch off motors

  static uint8_t rcSticks;       // this hold sticks position for command combos

  uint8_t axis,i;

  int16_t error,errorAngle;

  int16_t delta,deltaSum;

  int16_t PTerm,ITerm,DTerm;

  int16_t PTermACC = 0 , ITermACC = 0 , PTermGYRO = 0 , ITermGYRO = 0;

  static int16_t lastGyro[3] = {0,0,0};

  static int16_t delta1[3],delta2[3];

  static int16_t errorGyroI[3] = {0,0,0};

  static int16_t errorAngleI[2] = {0,0};

  static uint32_t rcTime  = 0;

  static int16_t initialThrottleHold;

  static uint32_t timestamp_fixated = 0;


  #if defined(SPEKTRUM)

    if (spekFrameFlags == 0x01) readSpektrum();

  #endif

  #if defined(OPENLRSv2MULTI) 

    Read_OpenLRS_RC();

  #endif 


#if defined(AIR)

  serialCom();

#endif


  if (currentTime > rcTime ) { // 50Hz

    rcTime = currentTime + 20000;

    computeRC();

    // Failsafe routine - added by MIS

#if defined(AIR)

     rcData[0] = serialRcValue[0];

     rcData[1] = serialRcValue[1];

     rcData[2] = serialRcValue[2];

     rcData[3] = serialRcValue[3];

     rcData[4] = serialRcValue[4];

     rcData[5] = serialRcValue[5];

     rcData[6] = serialRcValue[6];

     rcData[7] = serialRcValue[7];

#endif

    

    #if defined(FAILSAFE)

      if ( failsafeCnt > (5*FAILSAFE_DELAY) && f.ARMED) {                  // Stabilize, and set Throttle to specified level

        for(i=0; i<3; i++) rcData[i] = MIDRC;                               // after specified guard time after RC signal is lost (in 0.1sec)

        

        if(rcData[THROTTLE] < conf.failsafe_throttle){

          rcData[THROTTLE] = MINTHROTTLE;

        }

        else{

          rcData[THROTTLE] = conf.failsafe_throttle;

        }

        

        if (failsafeCnt > 5*(FAILSAFE_DELAY+FAILSAFE_OFF_DELAY)) {          // Turn OFF motors after specified Time (in 0.1sec)

          go_disarm();     // This will prevent the copter to automatically rearm if failsafe shuts it down and prevents

          f.OK_TO_ARM = 0; // to restart accidentely by just reconnect to the tx - you will have to switch off first to rearm

        }

        failsafeEvents++;

      }

      if ( failsafeCnt > (5*FAILSAFE_DELAY) && !f.ARMED) {  //Turn of "Ok To arm to prevent the motors from spinning after repowering the RX with low throttle and aux to arm

          go_disarm();     // This will prevent the copter to automatically rearm if failsafe shuts it down and prevents

          f.OK_TO_ARM = 0; // to restart accidentely by just reconnect to the tx - you will have to switch off first to rearm

      }

      failsafeCnt++;

    #endif

    // end of failsafe routine - next change is made with RcOptions setting


    // ------------------ STICKS COMMAND HANDLER --------------------

    // checking sticks positions

    uint8_t stTmp = 0;

    for(i=0;i<4;i++) {

      stTmp >>= 2;

      if(rcData[i] > MINCHECK) stTmp |= 0x80;      // check for MIN

      if(rcData[i] < MAXCHECK) stTmp |= 0x40;      // check for MAX

    }

    if(stTmp == rcSticks) {

      if(rcDelayCommand<250) rcDelayCommand++;

    } else rcDelayCommand = 0;

    rcSticks = stTmp;

    

    // perform actions    

    if (rcData[THROTTLE] <= MINCHECK) {            // THROTTLE at minimum

      errorGyroI[ROLL] = 0; errorGyroI[PITCH] = 0; errorGyroI[YAW] = 0;

      errorAngleI[ROLL] = 0; errorAngleI[PITCH] = 0;

      if (conf.activate[BOXARM] > 0) {             // Arming/Disarming via ARM BOX

        if ( rcOptions[BOXARM] && f.OK_TO_ARM ) 

go_arm();

        else if (f.ARMED) 

go_disarm();

      }

    }

    if(rcDelayCommand == 20) {

      if(f.ARMED) {                   // actions during armed

        #ifdef ALLOW_ARM_DISARM_VIA_TX_YAW

          if (conf.activate[BOXARM] == 0 && rcSticks == THR_LO + YAW_LO + PIT_CE + ROL_CE) go_disarm();    // Disarm via YAW

        #endif

        #ifdef ALLOW_ARM_DISARM_VIA_TX_ROLL

          if (conf.activate[BOXARM] == 0 && rcSticks == THR_LO + YAW_CE + PIT_CE + ROL_LO) go_disarm();    // Disarm via ROLL

        #endif

      } else {                        // actions during not armed

        i=0;

        if (rcSticks == THR_LO + YAW_LO + PIT_LO + ROL_CE) {    // GYRO calibration

//------------------------------------------------------------

calibration_fun();

//------------------------------------------------------------

        }

        #if defined(INFLIGHT_ACC_CALIBRATION)  

         else if (rcSticks == THR_LO + YAW_LO + PIT_HI + ROL_HI) {    // Inflight ACC calibration START/STOP

            if (AccInflightCalibrationMeasurementDone){                // trigger saving into eeprom after landing

              AccInflightCalibrationMeasurementDone = 0;

              AccInflightCalibrationSavetoEEProm = 1;

            }else{ 

              AccInflightCalibrationArmed = !AccInflightCalibrationArmed; 

              #if defined(BUZZER)

               if (AccInflightCalibrationArmed) alarmArray[0]=2; else   alarmArray[0]=3;

              #endif

            }

         } 

        #endif

        #ifdef MULTIPLE_CONFIGURATION_PROFILES

          if      (rcSticks == THR_LO + YAW_LO + PIT_CE + ROL_LO) i=1;    // ROLL left  -> Profile 1

          else if (rcSticks == THR_LO + YAW_LO + PIT_HI + ROL_CE) i=2;    // PITCH up   -> Profile 2

          else if (rcSticks == THR_LO + YAW_LO + PIT_CE + ROL_HI) i=3;    // ROLL right -> Profile 3

          if(i) {

            global_conf.currentSet = i-1;

            writeGlobalSet(0);

            readEEPROM();

            blinkLED(2,40,i);

            alarmArray[0] = i;

          }

        #endif

        if (rcSticks == THR_LO + YAW_HI + PIT_HI + ROL_CE) {            // Enter LCD config

          #if defined(LCD_CONF)

            configurationLoop(); // beginning LCD configuration

          #endif

          previousTime = micros();

        }

        #ifdef ALLOW_ARM_DISARM_VIA_TX_YAW

          else if (conf.activate[BOXARM] == 0 && rcSticks == THR_LO + YAW_HI + PIT_CE + ROL_CE) go_arm();      // Arm via YAW

        #endif

        #ifdef ALLOW_ARM_DISARM_VIA_TX_ROLL

          else if (conf.activate[BOXARM] == 0 && rcSticks == THR_LO + YAW_CE + PIT_CE + ROL_HI) go_arm();      // Arm via ROLL

        #endif

        #ifdef LCD_TELEMETRY_AUTO

          else if (rcSticks == THR_LO + YAW_CE + PIT_HI + ROL_LO) {              // Auto telemetry ON/OFF

            if (telemetry_auto) {

              telemetry_auto = 0;

              telemetry = 0;

            } else

              telemetry_auto = 1;

          }

        #endif

        #ifdef LCD_TELEMETRY_STEP

          else if (rcSticks == THR_LO + YAW_CE + PIT_HI + ROL_HI) {              // Telemetry next step

            telemetry = telemetryStepSequence[++telemetryStepIndex % strlen(telemetryStepSequence)];

            #ifdef OLED_I2C_128x64

              if (telemetry != 0) i2c_OLED_init();

            #endif

            LCDclear();

          }

        #endif

        else if (rcSticks == THR_HI + YAW_LO + PIT_LO + ROL_CE) calibratingA=512;     // throttle=max, yaw=left, pitch=min

        else if (rcSticks == THR_HI + YAW_HI + PIT_LO + ROL_CE) f.CALIBRATE_MAG = 1;  // throttle=max, yaw=right, pitch=min  

        i=0;

        if      (rcSticks == THR_HI + YAW_CE + PIT_HI + ROL_CE) {conf.angleTrim[PITCH]+=2; i=1;}

        else if (rcSticks == THR_HI + YAW_CE + PIT_LO + ROL_CE) {conf.angleTrim[PITCH]-=2; i=1;}

        else if (rcSticks == THR_HI + YAW_CE + PIT_CE + ROL_HI) {conf.angleTrim[ROLL] +=2; i=1;}

        else if (rcSticks == THR_HI + YAW_CE + PIT_CE + ROL_LO) {conf.angleTrim[ROLL] -=2; i=1;}

        if (i) {

          writeParams(1);

          rcDelayCommand = 0;    // allow autorepetition

          #if defined(LED_RING)

            blinkLedRing();

          #endif

        }

      }

    }

    #if defined(LED_FLASHER)

      led_flasher_autoselect_sequence();

    #endif

    

    #if defined(INFLIGHT_ACC_CALIBRATION)

      if (AccInflightCalibrationArmed && f.ARMED && rcData[THROTTLE] > MINCHECK && !rcOptions[BOXARM] ){ // Copter is airborne and you are turning it off via boxarm : start measurement

        InflightcalibratingA = 50;

        AccInflightCalibrationArmed = 0;

      }  

      if (rcOptions[BOXCALIB]) {      // Use the Calib Option to activate : Calib = TRUE Meausrement started, Land and Calib = 0 measurement stored

        if (!AccInflightCalibrationActive && !AccInflightCalibrationMeasurementDone){

          InflightcalibratingA = 50;

        }

      }else if(AccInflightCalibrationMeasurementDone && !f.ARMED){

        AccInflightCalibrationMeasurementDone = 0;

        AccInflightCalibrationSavetoEEProm = 1;

      }

    #endif


    uint16_t auxState = 0;

    for(i=0;i<4;i++)

      auxState |= (rcData[AUX1+i]<1300)<<(3*i) | (1300<rcData[AUX1+i] && rcData[AUX1+i]<1700)<<(3*i+1) | (rcData[AUX1+i]>1700)<<(3*i+2);

    for(i=0;i<CHECKBOXITEMS;i++)

      rcOptions[i] = (auxState & conf.activate[i])>0;


    // note: if FAILSAFE is disable, failsafeCnt > 5*FAILSAFE_DELAY is always false

    #if ACC

      if ( rcOptions[BOXANGLE] || (failsafeCnt > 5*FAILSAFE_DELAY) ) { 

        // bumpless transfer to Level mode

        if (!f.ANGLE_MODE) {

          errorAngleI[ROLL] = 0; errorAngleI[PITCH] = 0;

          f.ANGLE_MODE = 1;

        }  

      } else {

        // failsafe support

        f.ANGLE_MODE = 0;

      }

      if ( rcOptions[BOXHORIZON] ) {

        f.ANGLE_MODE = 0;

        if (!f.HORIZON_MODE) {

          errorAngleI[ROLL] = 0; errorAngleI[PITCH] = 0;

          f.HORIZON_MODE = 1;

        }

      } else {

        f.HORIZON_MODE = 0;

      }

    #endif


    if (rcOptions[BOXARM] == 0) f.OK_TO_ARM = 1;

    #if !defined(GPS_LED_INDICATOR)

      if (f.ANGLE_MODE || f.HORIZON_MODE) {STABLEPIN_ON;} else {STABLEPIN_OFF;}

    #endif


    #if BARO

      #if (!defined(SUPPRESS_BARO_ALTHOLD))

        if (rcOptions[BOXBARO]) {

            if (!f.BARO_MODE) {

              f.BARO_MODE = 1;

              AltHold = EstAlt;

              initialThrottleHold = rcCommand[THROTTLE];

              errorAltitudeI = 0;

              BaroPID=0;

            }

        } else {

            f.BARO_MODE = 0;

        }

      #endif

      #ifdef VARIOMETER

        if (rcOptions[BOXVARIO]) {

          if (!f.VARIO_MODE) {

            f.VARIO_MODE = 1;

          }

        } else {

          f.VARIO_MODE = 0;

        }

      #endif

    #endif

    #if MAG

      if (rcOptions[BOXMAG]) {

        if (!f.MAG_MODE) {

          f.MAG_MODE = 1;

          magHold = heading;

        }

      } else {

        f.MAG_MODE = 0;

      }

      if (rcOptions[BOXHEADFREE]) {

        if (!f.HEADFREE_MODE) {

          f.HEADFREE_MODE = 1;

        }

      } else {

        f.HEADFREE_MODE = 0;

      }

      if (rcOptions[BOXHEADADJ]) {

        headFreeModeHold = heading; // acquire new heading

      }

    #endif

    

    #if GPS

      static uint8_t GPSNavReset = 1;

      if (f.GPS_FIX && GPS_numSat >= 5 ) {

        if (rcOptions[BOXGPSHOME]) {  // if both GPS_HOME & GPS_HOLD are checked => GPS_HOME is the priority

          if (!f.GPS_HOME_MODE)  {

            f.GPS_HOME_MODE = 1;

            f.GPS_HOLD_MODE = 0;

            GPSNavReset = 0;

            #if defined(I2C_GPS)

              GPS_I2C_command(I2C_GPS_COMMAND_START_NAV,0);        //waypoint zero

            #else // SERIAL

              GPS_set_next_wp(&GPS_home[LAT],&GPS_home[LON]);

              nav_mode    = NAV_MODE_WP;

            #endif

          }

        } else {

          f.GPS_HOME_MODE = 0;

          if (rcOptions[BOXGPSHOLD] && abs(rcCommand[ROLL])< AP_MODE && abs(rcCommand[PITCH]) < AP_MODE) {

            if (!f.GPS_HOLD_MODE) {

              f.GPS_HOLD_MODE = 1;

              GPSNavReset = 0;

              #if defined(I2C_GPS)

                GPS_I2C_command(I2C_GPS_COMMAND_POSHOLD,0);

              #else

                GPS_hold[LAT] = GPS_coord[LAT];

                GPS_hold[LON] = GPS_coord[LON];

                GPS_set_next_wp(&GPS_hold[LAT],&GPS_hold[LON]);

                nav_mode = NAV_MODE_POSHOLD;

              #endif

            }

          } else {

            f.GPS_HOLD_MODE = 0;

            // both boxes are unselected here, nav is reset if not already done

            if (GPSNavReset == 0 ) {

              GPSNavReset = 1;

              GPS_reset_nav();

            }

          }

        }

      } else {

        f.GPS_HOME_MODE = 0;

        f.GPS_HOLD_MODE = 0;

        #if !defined(I2C_GPS)

          nav_mode = NAV_MODE_NONE;

        #endif

      }

    #endif

    

    #if defined(FIXEDWING) || defined(HELICOPTER)

      if (rcOptions[BOXPASSTHRU]) {f.PASSTHRU_MODE = 1;}

      else {f.PASSTHRU_MODE = 0;}

    #endif

 

  } else { // not in rc loop

    static uint8_t taskOrder=0; // never call all functions in the same loop, to avoid high delay spikes

    if(taskOrder>4) taskOrder-=5;

    switch (taskOrder) {

      case 0:

        taskOrder++;

        #if MAG

          if (Mag_getADC()) break; // max 350 µs (HMC5883) // only break when we actually did something

        #endif

      case 1:

        taskOrder++;

        #if BARO

          if (Baro_update() != 0 ) break;

        #endif

      case 2:

        taskOrder++;

        break;

        

        #if BARO

          if (getEstimatedAltitude() !=0) break;

        #endif 

       

      case 3:

        taskOrder++;

        #if GPS

          if(GPS_Enable) GPS_NewData();

          break;

        #endif

      case 4:

        taskOrder++;

        #if SONAR

          Sonar_update();

        #endif

        #ifdef LANDING_LIGHTS_DDR

          auto_switch_landing_lights();

        #endif

        #ifdef VARIOMETER

          if (f.VARIO_MODE) vario_signaling();

        #endif

        

        break;

    }

  }

 

  computeIMU();

  // Measure loop rate just afer reading the sensors

  currentTime = micros();

  cycleTime = currentTime - previousTime;

  previousTime = currentTime;


  #ifdef CYCLETIME_FIXATED

    if (conf.cycletime_fixated) {

      if ((micros()-timestamp_fixated)>conf.cycletime_fixated) {

      } else {

         while((micros()-timestamp_fixated)<conf.cycletime_fixated) ; // waste away

      }

      timestamp_fixated=micros();

    }

  #endif

  //***********************************

  //**** Experimental FlightModes *****

  //***********************************

  #if defined(ACROTRAINER_MODE)

    if(f.ANGLE_MODE){

      if (abs(rcCommand[ROLL]) + abs(rcCommand[PITCH]) >= ACROTRAINER_MODE ) {

        f.ANGLE_MODE=0;

        f.HORIZON_MODE=0;

        f.MAG_MODE=0;

        f.BARO_MODE=0;

        f.GPS_HOME_MODE=0;

        f.GPS_HOLD_MODE=0;

      }

    }

  #endif


 //*********************************** 

 

  #if MAG

    if (abs(rcCommand[YAW]) <70 && f.MAG_MODE) {

      int16_t dif = heading - magHold;

      if (dif <= - 180) dif += 360;

      if (dif >= + 180) dif -= 360;

      if ( f.SMALL_ANGLES_25 ) rcCommand[YAW] -= dif*conf.P8[PIDMAG]>>5;

    } else magHold = heading;

  #endif


  #if BARO && (!defined(SUPPRESS_BARO_ALTHOLD))

    if (f.BARO_MODE) {

      static uint8_t isAltHoldChanged = 0;

      #if defined(ALTHOLD_FAST_THROTTLE_CHANGE)

        if (abs(rcCommand[THROTTLE]-initialThrottleHold) > ALT_HOLD_THROTTLE_NEUTRAL_ZONE) {

         //errorAltitudeI = 0;

          isAltHoldChanged = 1;

          rcCommand[THROTTLE] += (rcCommand[THROTTLE] > initialThrottleHold) ? -ALT_HOLD_THROTTLE_NEUTRAL_ZONE : ALT_HOLD_THROTTLE_NEUTRAL_ZONE;          

         // initialThrottleHold += (rcCommand[THROTTLE] > initialThrottleHold) ? -ALT_HOLD_THROTTLE_NEUTRAL_ZONE : ALT_HOLD_THROTTLE_NEUTRAL_ZONE;; //++hex nano

        } else {

          if (isAltHoldChanged) {

            AltHold = EstAlt;

            isAltHoldChanged = 0;

          }

          rcCommand[THROTTLE] = initialThrottleHold + BaroPID;

        }

      #else

        static int16_t AltHoldCorr = 0;

        if (abs(rcCommand[THROTTLE]-initialThrottleHold)>ALT_HOLD_THROTTLE_NEUTRAL_ZONE) {

          // Slowly increase/decrease AltHold proportional to stick movement ( +100 throttle gives ~ +50 cm in 1 second with cycle time about 3-4ms)

          AltHoldCorr+= rcCommand[THROTTLE] - initialThrottleHold;

          if(abs(AltHoldCorr) > 500) {

            AltHold += AltHoldCorr/500;

            AltHoldCorr %= 500;

          }

          //errorAltitudeI = 0;

          isAltHoldChanged = 1;

        } else if (isAltHoldChanged) {

          AltHold = EstAlt;

          isAltHoldChanged = 0;

        }

        rcCommand[THROTTLE] = initialThrottleHold + BaroPID;

      #endif

    }

  #endif

  #if GPS

    if ( (f.GPS_HOME_MODE || f.GPS_HOLD_MODE) && f.GPS_FIX_HOME ) {

      float sin_yaw_y = sin(heading*0.0174532925f);

      float cos_yaw_x = cos(heading*0.0174532925f);

      #if defined(NAV_SLEW_RATE)     

        nav_rated[LON]   += constrain(wrap_18000(nav[LON]-nav_rated[LON]),-NAV_SLEW_RATE,NAV_SLEW_RATE);

        nav_rated[LAT]   += constrain(wrap_18000(nav[LAT]-nav_rated[LAT]),-NAV_SLEW_RATE,NAV_SLEW_RATE);

        GPS_angle[ROLL]   = (nav_rated[LON]*cos_yaw_x - nav_rated[LAT]*sin_yaw_y) /10;

        GPS_angle[PITCH]  = (nav_rated[LON]*sin_yaw_y + nav_rated[LAT]*cos_yaw_x) /10;

      #else 

        GPS_angle[ROLL]   = (nav[LON]*cos_yaw_x - nav[LAT]*sin_yaw_y) /10;

        GPS_angle[PITCH]  = (nav[LON]*sin_yaw_y + nav[LAT]*cos_yaw_x) /10;

      #endif

    } else {

      GPS_angle[ROLL]  = 0;

      GPS_angle[PITCH] = 0;

    }

  #endif


  //**** PITCH & ROLL & YAW PID ****

  int16_t prop;

  prop = min(max(abs(rcCommand[PITCH]),abs(rcCommand[ROLL])),500); // range [0;500]


  for(axis=0;axis<3;axis++) {

    if ((f.ANGLE_MODE || f.HORIZON_MODE) && axis<2 ) { // MODE relying on ACC

      // 50 degrees max inclination

      errorAngle = constrain((rcCommand[axis]<<1) + GPS_angle[axis],-500,+500) - angle[axis] + conf.angleTrim[axis]; //16 bits is ok here

      PTermACC = ((int32_t)errorAngle*conf.P8[PIDLEVEL])>>7;                          // 32 bits is needed for calculation: errorAngle*P8[PIDLEVEL] could exceed 32768   16 bits is ok for result

      PTermACC = constrain(PTermACC,-conf.D8[PIDLEVEL]*5,+conf.D8[PIDLEVEL]*5);


      errorAngleI[axis]     = constrain(errorAngleI[axis]+errorAngle,-10000,+10000);    // WindUp     //16 bits is ok here

      ITermACC              = ((int32_t)errorAngleI[axis]*conf.I8[PIDLEVEL])>>12;            // 32 bits is needed for calculation:10000*I8 could exceed 32768   16 bits is ok for result

    }

    if ( !f.ANGLE_MODE || f.HORIZON_MODE || axis == 2 ) { // MODE relying on GYRO or YAW axis

      if (abs(rcCommand[axis])<500) error =          (rcCommand[axis]<<6)/conf.P8[axis] ; // 16 bits is needed for calculation: 500*64 = 32000      16 bits is ok for result if P8>5 (P>0.5)

                               else error = ((int32_t)rcCommand[axis]<<6)/conf.P8[axis] ; // 32 bits is needed for calculation


      error -= gyroData[axis];


      PTermGYRO = rcCommand[axis];

      

      errorGyroI[axis]  = constrain(errorGyroI[axis]+error,-16000,+16000);         // WindUp   16 bits is ok here

      if (abs(gyroData[axis])>640) errorGyroI[axis] = 0;

      ITermGYRO = ((errorGyroI[axis]>>7)*conf.I8[axis])>>6;                        // 16 bits is ok here 16000/125 = 128 ; 128*250 = 32000

    }

    if ( f.HORIZON_MODE && axis<2) {

      PTerm = ((int32_t)PTermACC*(512-prop) + (int32_t)PTermGYRO*prop)>>9;         // the real factor should be 500, but 512 is ok

      ITerm = ((int32_t)ITermACC*(512-prop) + (int32_t)ITermGYRO*prop)>>9;

    } else {

      if ( f.ANGLE_MODE && axis<2) {

        PTerm = PTermACC;

        ITerm = ITermACC;

      } else {

        PTerm = PTermGYRO;

        ITerm = ITermGYRO;

      }

    }


    PTerm -= ((int32_t)gyroData[axis]*dynP8[axis])>>6; // 32 bits is needed for calculation   


    delta          = gyroData[axis] - lastGyro[axis];  // 16 bits is ok here, the dif between 2 consecutive gyro reads is limited to 800

    lastGyro[axis] = gyroData[axis];

    deltaSum       = delta1[axis]+delta2[axis]+delta;

    delta2[axis]   = delta1[axis];

    delta1[axis]   = delta;

 

    DTerm = ((int32_t)deltaSum*dynD8[axis])>>5;        // 32 bits is needed for calculation

                      

    axisPID[axis] =  PTerm + ITerm - DTerm;

  }


  mixTable();

  writeServos();

  writeMotors();

}

'D > 드론 자료' 카테고리의 다른 글

드론자료(EN) (Drone)  (0) 2017.02.24
Posted by ElectricShock
:
BLOG main image
잡동사니들(지극히 개인취향인...) (다른글에도 댓글 부탁해요♥) You May Leave English Messages on GuestBook. by ElectricShock

공지사항

카테고리

분류 전체보기 (782)
Programming(=프로그래밍) (3)
MiDi (2)
Animation (4)
Blender (3D Graphic Program.. (10)
Blendtuts.com (Series) (1)
Blender 기초 팁들 (2)
Processing (디지털미디어과) (2)
Music (1)
Books in the world (0)
Communication(CAN, UART, et.. (12)
MCU Examples (PIC 기반) (7)
Transistor (1)
Mikro C Pro (11)
Mikro Pascal (1)
Proton IDE (0)
Robot (0)
Swift 3D (1)
Dummies Series (1)
All about Hacking (0)
제2 외국어 (1)
PIC 해외서적들 (3)
AVR (25)
PIC (MikroC) (MPLAB) (4)
Assembly (2)
ARM (3)
Arduino (26)
PSpice (1)
Proteus ISIS (14)
CodeVision (2)
FPGA (15)
MPLAB (24)
PCB (the Procedure) (15)
3D Printer (5)
PICKIT3 (6)
Matlab (11)
RaspBerry PI (15)
BeagleBone (1)
Android Studio (17)
졸업작품 (172)
Korea History (0)
Issue(사회) (73)
Multimeter 리뷰 (1)
Oscilloscope (1)
A (34)
B (19)
J (6)
C (32)
P (12)
T (37)
H (12)
I (12)
M (44)
R (5)
E (5)
F (2)
D (9)
O (2)
L (7)
S (9)
W (2)
V (6)
G (14)
Visual C++ or Visual Studio (2)
Android App Development (0)

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백