-> Free Drone Company.
Section 4: Flight-Control-Functions.

............ Flight Control Source Code ...............

== File-Name: 1_Wing-Drone-flight-control-mag3110-V10-9-22.ino ==


//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//++++++++++++++ Begin Flight Control Function ++++++++++++++++
//++ General Comments, Libraries, Constants and Global Vars  ++
//                Last Update: 15-10-2022  
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

// Note: decimal is a POINT and not a KOMMA. < is < operator.
// Flight-Control based on sketch of a Tilt Compensated Compass with GPS and air-pressure sensor
// DUE-Teensy-DUE-Teensy-DUE-Teensy-DUE-Teensy-DUE-Teensy-DUE-Teensy-
// with Calibrated MPU6050 (accel & gyro) and Magnetometer MAG3110.
// Results displayed on monitor only.
// This code will control 4 Servo's with servo-library. 
// The Pitch, Roll, Yaw is controlled bij accel., gyro, and magnetometer sensors.
// The formula's for yawdot, pitchdot and rolldot as function of gyro data are included
// All used for input to the PID-Controller.
// Homing-in is applied.
// "Pelles-ST-Rotated-Ellipsoid-Fitting-for-Sensor-Calibration" is applied for Magnetometer calibration.

// - PCA9685 will be used for control LED's.
// - PCA9685 GRD to Arduino Ground.
// - PCA9685 VCC to 3.3V of Arduino.
// - PCA9685 PWM output 0,1,2 etc. to be used for System Control-Leds
// - PCA9685 GRD output (black) pins to be connected to the LEDs-LEDS

// -GPS-GPS-GPS-GPS-GPS-GPS-GPS-GPS-GPS-GPS-GPS-GPS-GPS-GPS-GPS
// Serial1 (pin 18 en 19) is being used to read GPS 
// Connect VCC of GPS board to 3.3V of Due
// Connect Ground of GPS board to Ground of Due
// Connect RX of GPS board to Serial1 TX1 (18) of Due
// Connect TX of GPS board to Serial1 RX1 (19) of Due 
// GPS sketch represents the coordinates as floats

#include 
#include 
//#include 
#include 

#include     // with DUE all Wire has to be replaced by Wire1 
#define I2C Wire     //Teensy

#include 

// Call Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
// I2C address PCA9685 is: 0x40
 Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40);

 #define MPU_addr    (0x68)  // I2C Device address as specified in data sheet
 #define KOMPASS     (0x0E)  // I2C address of MAG3110.
 #define BMP280_Addr (0x76)  // BMP-280 I2C address is 0x76

//...................................................................
// Begin Coordinate-Axis Offset address def.MAG3110 sensor
 #define OFF_X_MSB 0x09 
 #define OFF_X_LSB 0x0A 
 #define OFF_Y_MSB 0x0B
 #define OFF_Y_LSB 0x0C
 #define OFF_Z_MSB 0x0D
 #define OFF_Z_LSB 0x0E

 #define SPKR 9 // 9 is the digital pin to plug the speaker "red" wire in

 unsigned long  time1;    //millis() returns an unsigned long, type int
 int Loop_T_millis;       //Loop-time in millis
 float Loop_T_secs;
 int Job_T_millis = 0;
 float Loop_Control_T_Secs;
 float Job_T_secs   = 0.0;        //sec

 int GPS_Read_Freq = 19;
 
 int   nDevices = 1;        //This value should be >=4 when the correct number of I2C sensors are found. 
 int   Flag;               
 int   Gyro_Init_setting = 1;

// mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
// Select the processor number that will be used
// mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
// Processor= 1: Switch for Test Bench Teensy and Calibration Data of Test-Bench Sensors.
// Processor= 2: Switch for Drone Teensy and Calibration Data of Drone Sensors.

   int Processor = 1;     //Select Test-Bench Teensy
//  int Processor = 2;    //Select Drone Teensy

// mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
// mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
 
 int Calib_Serie;
 float Gvalue;         //G-value is set in Calibration Matrices Function
 
 // PCA9685 output pins for 16 control LED's
 uint8_t PCApin[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};   
 float GyroX_Drift = 0;
 float GyroY_Drift = 0;
 float GyroZ_Drift = 0;

 float AccSensitivity;       // Accel-Sensitivity LSB/g
 float DigitPerdps;          // gyro-Sensitivity  Digits per deg.per.second
 
 float  CaliMatrix[3][3];        // Accelerator Calibratie Matrix
 float  CaliVec[3];              // Accelerator Calibratie shift vector

 short  Mag_VSx, Mag_VSy, Mag_VSz; // Magnetometer Calibratie Shift vector
 float  Wmin1[3][3];               //Magnetometer calibration matrix.

 int n, m;
 int i = 0, j = 0;
 int start=0;

//======================================================
//======================================================
//--- Ultrasone and Barometric Altitude Sensors Vars ---

 int AltitudeFlag=0;
 float drone_altitude;
 float homing_in_altitude;
 int hswitch = 0;

// ................................................................................................
// Temp. Calibration data from barometric BMP280 EEProm
 uint16_t dig_T1;
 int16_t  dig_T2, dig_T3;
// Press. Calibration data from barometric BMP280 EEProm
 uint16_t dig_P1;
 int16_t  dig_P2,dig_P3,dig_P4,dig_P5,dig_P6,dig_P7,dig_P8,dig_P9;

// Barometric Altitude Sensor Variables
  int count;
  uint16_t  Coff[12];
  byte data[6];
  int32_t t_fine; 
  float temperature;
  float start_baropressure;       //millibar
  float actual_baropressure;      //millibar
  float baro_height;          //[cm]  max.value=2.147.483.647cm

// ======================================================
// ======================================================

  float Loc1_Lon, Loc1_Lat, Loc2_Lon, Loc2_Lat;
 
// ++++++++++++++++++ GPS global data declaration ++++++++++++++++++ 
// ++++++++++++++++++ GPS global data declaration ++++++++++++++++++ 

  const int MaxChars = 128;   //128 or 256 characters is sufficient for a hit
  char GPSstrBuffer[MaxChars]= {'\0'};
  size_t nCount;
  int GPS_Flag =0;
// As initial Actual GPS position a Position in Pacific Ocean is selected        
  float GPS_val_Lon = 155.14; // GPS reading in degrees Long
  float GPS_val_Lat =  44.71; // GPS reading in degrees Lat
  
// ++++++++ Heading global data declaration ++++ Heading global data declaration ++++++
  float Lon_angle_Home; // User defined in degrees Long
  float Lat_angle_Home; // User defined in degrees Lat
  //char _HomeName[15];
  String HomeName;
  
  float Lon_angle_Target = 0.00; // User defined in degrees Long
  float Lat_angle_Target = 0.00; // User defined in degrees Lat
  //char _TargetName[15];
  String TargetName;
      
//  float Flight_Distance;
  int Fake_Flight_Distance = 1500;  //m use for testing only
  int Max_Flight_Distance = 10000;     //[m]
// Set as initial value for Flight_Distance=2*Max_Flight_Distance
  float Flight_Distance;     // =2*Max_Flight_Distance;
  float Alpha;      // Angle between North and Target 
  float DeltaYaw;   // Drone Rotation Angle to align Drone-Nose to Target 
  char Rotation[5]; // Rotation direction CW or CWW to align Drone-Nose to Target 
  int Rotation_Sign;
 
  int Old_Distance;
  float Old_Alpha;     // Angle between North and Target 
  float Old_DeltaYaw;  // Drone Rotation Angle to align Drone-Nose to Target 
  int Old_Rotation_Sign;

// ======= PID Control Variables, GAIN and LIMIT SETTINGS =======
// .........................................................
// PID-ROLL ----- PID-ROLL ----- PID-ROLL ----- PID-ROLL ---   
   float pid_roll_output;
   
// .............................................................
// PID-PITCH ----- PID-PITCH ----- PID-PITCH ----- PID-PITCH ---   
   float pitch_setpoint;
   float pid_pitch_output;

//.........................................................
// PID-YAW ----- PID-YAW ----- PID-YAW ----- PID-YAW -----   
  float Bank_angle =0.0;
  float pid_yaw_output;

// ============= Begin global variables to Calc_Pitch_Roll_Yaw =========
float AccPitch, AccRoll;
float GyroPitch, GyroRoll;  
float MagYaw, GeoMagYaw, GyroYaw;
float G_Value;

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
float Calib_Acc_x, Calib_Acc_y, Calib_Acc_z;
float Mag_Bfx, Mag_Bfy, Mag_Bfy1, Mag_Bfy2;
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ============= End global variables to Calc_Pitch_Roll_Yaw  =========

float Pitch_Correction;
float Roll_Correction;
float Yaw_Correction;
float Mag_Declination; 

//...................................................................................
//Moving-average calculation
 int const len = 10;           //number of elements used for averaging
 float arrNumbers[len] = {0};  //declaration Array with len elementa.
 float CumulVals = 0;
 float MoveAver = 0;  

//.......................................................................
//Rotating-average calculation
  int const Max_RotateIndex = 10; 
  float RotateArray[Max_RotateIndex] = {0};  //declaration Array with Rotate_MaxIndex elementa.
  int Rotate_Index = 0; 
  float Cum_Value = 0;
  float RotateAvg = 0; 
 
//...................................................................................
//Gyro Calibration
  float Gyroraw[3];
  float GyroCalib[3];
  float GyroVs[3];               //Gyro Calibration shift Vector
  float GyroCaliMx[3][3];        //Gyro Calibration Matrix

// ........Servo-Control Variables ........Serv-Control Variables .........Motor-Control Variables.....
// create the servo's as "servo"Objekts for control.
   Servo Servo_0, Servo_1, Servo_2, Servo_3;
// Servo_0 => Ailerons
// Servo_1 => Hoogte roer
// Servo_2 => Rudder
// Servo_3 => free

   int PWMpin_4_Servo_0 = 2; // Teensy PWM pin2 4=for Roll Ailerons Servo
   int PWMpin_4_Servo_1 = 3; // Teensy PWM pin3 4=for Pitch Elevator Servo 
   int PWMpin_4_Servo_2 = 4; // Teensy PWM pin4 4=for Yaw Rudder Servo
   int PWMpin_4_Servo_3 = 5; // Teensy PWM pin5 4=for Motor Servo
   
  int EmVPin14 = 14;      // Teensy Pin 14 for Analog Input to read Emergency PWM-to-Voltage values
  int EmVreadValue;
  int EmCorrection;   
  int Emrev_up_Motor = 0; //Emrev is Emergency-rev-up Motor @ Frame-Pos0123

//1600 all servo's in mid-position
  int Servo_0_In = 1600; // PWM Value Passed to Servo_0 via Teensy-Pin 2          
  int Servo_1_In = 1600; // PWM Value Passed to Servo_1 via Teensy-Pin 3          
  int Servo_2_In = 1600; // PWM Value Passed to Servo_2 via Teensy-Pin 4          
  int Servo_3_In = 1600; // PWM Value Passed to Servo_3 via Teensy-Pin 5          

//----------- Serial_Print Variables List ------------------
   int   printfreq = 0;
//-------- End of Serial_Print Variables List --------------

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++ End Flight Control Function +++++++++++++++++
//++ General Comments, Libraries, Constants and Global Vars  ++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Free-Drones Company 2022