StoRC
Autonomous Payload Delivery System
storc.pde
Go to the documentation of this file.
00001 /***********************************************************
00002  * StoRC - Search to Rescue Craft
00003  * MEAM Senior Design 2011-2012
00004  * 
00005  * Authors:  Michael Posner (CIS, MEAM '12)
00006  * Timothy Hennelly (ESE '12)
00007  * Jacob Orloff (MEAM '12)
00008  * 
00009  * (some code from ArduPilot Mega project, found here:
00010  * http://code.google.com/p/ardupilot-mega/ )
00011  * 
00012  * Licensing:
00013  * 
00014  * This program is free software: you can redistribute it and/or modify 
00015  * it under the terms of the GNU General Public License as published by 
00016  * the Free Software Foundation, either version 3 of the License, or 
00017  * (at your option) any later version. 
00018  * 
00019  * This program is distributed in the hope that it will be useful, 
00020  * but WITHOUT ANY WARRANTY; without even the implied warranty of 
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
00022  * GNU General Public License for more details. 
00023  * 
00024  * You should have received a copy of the GNU General Public License 
00025  * along with this program. If not, see <http://www.gnu.org/licenses/>.
00026  * 
00027  ***********************************************************/
00028 
00029 /**
00030  *  @file storc.pde
00031  *  @brief Main file, contains Arduino setup() and loop() functions
00032  *  @author Michael Posner (CIS, MEAM '12)
00033  *  @author Timothy Hennelly (ESE '12)
00034  *  @author Jacob Orloff (MEAM '12)
00035  *  
00036  */
00037 
00038 // Libraries  --------------------------------------------------------
00039 // (they have to be included by this main storc.pde file, not storc.h)
00040 
00041 //ArduPilot Mega headers
00042 #include <FastSerial.h>  //ArduPilot Mega library for better serial communication (used by common and GPS library, MUST BE FIRST #include )
00043 #include <AP_Common.h>  //ArduPilot Mega common library
00044 #include <DataFlash.h>  //ArduPilot Mega flash memory library
00045 #include <APM_RC.h>  //ArduPilot Mega library for reading RC inputs and generating PWM pulses on output channels
00046 #include <AP_GPS.h>  //ArduPilot Mega library for reading GPS data from GPS
00047 #include <APM_BMP085.h>  //ArduPilot Mega library for reading the barometer (abs. pressure + temp)
00048 #include <AP_ADC.h>  //ArduPilot Mega library for using ADC
00049 #include <AP_IMU.h>  //ArduPilot Mega general header for including all relevant IMU headers
00050 #include <AP_Compass.h> //ArduPilot Mega magnetometer library
00051 #include <AP_DCM.h>  //ArduPilot Mega dcm library
00052 
00053 //AVR headers
00054 #include <stdio.h>
00055 
00056 //Arduino headers
00057 #include <SPI.h>  // Arduino SPI lib  (for flash memory communication)
00058 #include <Wire.h>  //Arduino I2C library (used by barometer)
00059 
00060 //Project Headers  --------------------------------------------------
00061 #include "storc.h"  //Main storc header file
00062 #include "controls.h"  //Controls header file
00063 
00064 //Functions  --------------------------------------------------------
00065 
00066 /**
00067  * Function that runs every so often, as determined by {@link SLOW_LOOP_CLOCK}
00068  * @see loop
00069  */
00070 void slow_loop(void) {
00071 
00072   //GPS
00073   if(use_gps == true) {
00074 
00075     gps->update();
00076 
00077     //debug_gps();
00078 
00079     if(LOG && (logging_sw > 512)) {
00080       if(gps->new_data) { //If the GPS has new data
00081         //adjust the GPS time:  GPS Millisecond time of week -> HH:MM:SS
00082         long day = floor((gps->time/1000)/SEC_PER_DAY);
00083         long hour = floor(((gps->time/1000) - day*SEC_PER_DAY)/SEC_PER_HOUR);
00084         long minute = floor(((gps->time/1000) - day*SEC_PER_DAY - hour*SEC_PER_HOUR)/SEC_PER_MIN);
00085         long second = floor((gps->time/1000) - day*SEC_PER_DAY - hour*SEC_PER_HOUR - minute*SEC_PER_MIN);
00086 
00087         //convert to EST
00088         hour -= 5;
00089         if(hour < 0) {
00090           hour += 24;
00091         }
00092 
00093         //log gps data in flash memory (these values are sometimes *10^7 or *100, but we fix that in the read function)
00094         Log_Write_GPS(day,hour,minute,second,gps->latitude,gps->longitude,gps->altitude,gps->ground_speed,gps->ground_course);  
00095 
00096         gps->new_data = 0; // We have read the data
00097 
00098         new_ALT = gps->altitude/100.0; // New altitude reading
00099         updated_ALT = 1;               // Updated altitude is true
00100       }
00101     }
00102 
00103 
00104 
00105   }
00106 
00107   //Barometer
00108   if(barometer.Read() == 1) { //if the barometer has new data
00109     //debug_barometer();
00110     if(LOG && (logging_sw > 512)) {
00111       Log_Write_Barometer((float)(barometer.Temp)*0.1 + 273.15, (float)(barometer.Press)/1000.0);  //convert temp to K, press to kPa
00112     }
00113 
00114   }
00115 
00116   //Log state
00117   if(LOG) {
00118     Log_Write_State(drop_state, logging_sw, get_wind_profile, avg_wind_ns, avg_wind_ew, drift_ns, drift_ew);
00119   }
00120 
00121   //Controls ----------------------------------------------------------
00122   if(CONTROLS){
00123 
00124     if (rc_5 > 1500){
00125 
00126       //Navigation update
00127       if(NAVIGATION){
00128 
00129         /*
00130         // Figure out where to go
00131          if(drop_state == false){ // If still have not delivered payload, go to target
00132          LAT_C = target_LAT;
00133          LON_C = target_LON;
00134          }else{ // If already delivered, go to start
00135          LAT_C = gps_start_lat;b
00136          LON_C = gps_start_lon;
00137          }
00138          */
00139          
00140 
00141         // Check if within Tolerance Radius Squared of the drop site
00142         //dist2drop = (del_LAT*del_LAT)+(del_LON*del_LON);
00143         //if(dist2drop < TRS){
00144         if((abs(del_LAT) < DROP_THRESH) && (abs(del_LON) < DROP_THRESH)) {
00145           drop_payload();
00146           drop_state = true;
00147           LAT_C = gps_start_lat;
00148           LON_C = gps_start_lon;
00149           Serial.println("----IN THE SACK----");
00150         }
00151         else{
00152           reset_drop();
00153           Serial.println("----OUTTA THE SACK----");
00154         }
00155 
00156         //calculate desired heading to align with destination
00157         del_LAT = LAT_C - (gps->latitude);
00158         del_LON = LON_C - (gps->longitude);
00159         psi_c = atan2(del_LAT,del_LON);
00160 
00161         //convert psi_c to same reference frame as GPS Heading is in (atan2 returns in the range [-pi,pi])
00162         if(psi_c < 0) {
00163           psi_c += 2.0*PI;
00164         }
00165 
00166         psi_c = 2.0*PI-(psi_c-PI/2.0);
00167 
00168         psi_c = RAD2DEG(psi_c); //convert to degrees
00169 
00170         //calculate difference in desired from current heading
00171         psi_error = psi_c - gps->ground_course/100.0;
00172 
00173         //wrap if error is over 180 or less than -180
00174         if(psi_error > 180) {
00175           psi_error -= 360;
00176         }
00177         else if (psi_error < -180) {
00178           psi_error += 360;
00179         }      
00180 
00181         //calculate bank command based on difference
00182         if( psi_error < 0 && psi_error > -180 ) { //psi_c is to the left of the plane, turn left
00183 
00184           phi_c = -KP_PSI2PHI*abs(psi_error);
00185         }
00186         else {  //psi_c is to the right of the plane, turn right
00187 
00188           phi_c = KP_PSI2PHI*abs(psi_error);
00189         }
00190 
00191         phi_c = constrain(phi_c,-45,45);
00192 
00193         /*
00194         Serial.print("H: "); 
00195         Serial.print(gps->ground_course/100.0);
00196         Serial.print(", Psi_c: ");  
00197         Serial.print(psi_c);
00198         Serial.print(", Phi_c: "); 
00199         Serial.print(phi_c);
00200         Serial.print(", d: ");
00201         if(drop_state) {
00202           Serial.print("1");
00203         }
00204         else {
00205           Serial.print("0");
00206         }
00207         
00208         Serial.print(", LAT_C: ");
00209         Serial.print(LAT_C);
00210         Serial.print(", LON_C: ");
00211         Serial.print(LON_C);
00212         Serial.print(", real lat: ");
00213         Serial.print(gps->latitude);
00214         Serial.print(", real lon: ");
00215         Serial.print(gps->longitude);
00216         Serial.print(", DROP_THRESH: ");
00217         Serial.print(DROP_THRESH);
00218         Serial.print(", del_LAT: ");
00219         Serial.print(del_LAT);
00220         Serial.print(", del_LON: ");
00221         Serial.println(del_LON);
00222         */
00223 
00224         if(LOG && (logging_sw > 512)) {
00225           Log_Write_Navigation(LAT_C, LON_C, del_LAT, del_LON, psi_c, psi_error, phi_c, DROP_THRESH);
00226         }
00227       }
00228 
00229     }
00230 
00231     if ((rc_4 > 1500) && (updated_ALT)){  // Throttle Control
00232 
00233       // If just switched on 
00234       if(sw1 == 0){
00235         I_THR = 0;                  // Reset integrator to zero 
00236         rc_thr_trim = rc_throttle;  // Remember throttle starting position
00237       }
00238 
00239       sw1 = 1;                                      // Set switch variable to high
00240 
00241       del_THR= 0;                                  // Reset to zero
00242       THR_control(1.0/(float)(SLOW_LOOP_CLOCK));   // Run the throttle controls algorithm. Use slow_loop timer since that's the sampling rate.
00243       updated_ALT = 0;
00244 
00245     }
00246     else{
00247       sw1 = 0;     // Keep switch variable low
00248     }
00249 
00250   }
00251 
00252 }
00253 
00254 /**
00255  * Function that runs every so often, as determined by {@link MED_LOOP_CLOCK}
00256  * @see loop
00257  */
00258 void medium_loop(void) {
00259 
00260   //Read logging switch
00261   logging_sw = analogRead(LOGGING_SWITCH);  //analogRead returns 0-1023
00262 
00263   //test slide switch
00264   //slide_sw = digitalRead(SLIDE_SWITCH);
00265   //Serial.print("slide sw: ");  Serial.println(slide_sw);
00266 
00267   //IMU ---------------------------------------------------------------
00268   imu.update();
00269   accel = imu.get_accel();
00270   gyro = imu.get_gyro();
00271 
00272   //DCM ---------------------------------------------------------------
00273   //debug_dcm();
00274 
00275   //Magnetometer ------------------------------------------------------
00276   compass.read();
00277   compass.calculate(dcm.get_dcm_matrix());  //use the current dcm matrix to adjust calculations
00278   compass.null_offsets(dcm.get_dcm_matrix());  //re-evaluate offsets
00279 
00280   //debug_magnetometer();
00281 
00282   //Airspeed ----------------------------------------------------------
00283   update_airspeed();
00284   //debug_airspeed();
00285 
00286   if(gps->altitude/100.0 > 38+20) {  //if we get high enough, profile over
00287     get_wind_profile = false;
00288   }
00289   
00290   if(get_wind_profile) {
00291     //update average wind stuff while we're ascending
00292     //get current wind speed, split into directions
00293     float curr_wind_ns = (gps->ground_speed/100.0 - airspeed)*sin(DEG2RAD(gps->ground_course/100.0));
00294     float curr_wind_ew = (gps->ground_speed/100.0 - airspeed)*cos(DEG2RAD(gps->ground_course/100.0));
00295   
00296     //add to running sum
00297     sum_wind_ns += curr_wind_ns;
00298     sum_wind_ew += curr_wind_ew;
00299   
00300     //increment total number of samples
00301     total_ns++;
00302     total_ew++;
00303   
00304     //calculate new average
00305     avg_wind_ns = sum_wind_ns/(float)(total_ns);
00306     avg_wind_ew = sum_wind_ew/(float)(total_ew);
00307   }
00308   else {  //do offset calculations
00309     
00310     int s_ns = 1;  //sign of ns wind
00311     int s_ew = -1;  //sign of ew wind
00312     
00313     if(avg_wind_ns < 0) {
00314       s_ns = -1;
00315     }
00316     if(avg_wind_ew < 0) {
00317       s_ew = -1;
00318     }
00319     
00320     drift_ns = K_DRIFT*(gps->altitude/100.0)*avg_wind_ns+(s_ns*OFFSET_DRIFT);  //drift [m] positive means will drift north  
00321     drift_ew = K_DRIFT*(gps->altitude/100.0)*avg_wind_ew+(s_ew*OFFSET_DRIFT);  //drift [m] positive means will drift east
00322     
00323     //drift is in meters, constrain to not be huge
00324     drift_ns = constrain(drift_ns, -500,500);
00325     drift_ew = constrain(drift_ew, -500,500);
00326     
00327     //convert drift to GPS
00328     float drift_ns_gps = DELT_M2GPS_LAT(drift_ns);
00329     float drift_ew_gps = DELT_M2GPS_LON(drift_ew);
00330     
00331     //adjust target
00332     LAT_C = target_LAT - drift_ns_gps*10000000;
00333     LON_C = target_LON - drift_ew_gps*10000000;
00334   
00335   }
00336 
00337   //RC ----------------------------------------------------------------
00338   //debug_rc();
00339 
00340 
00341   //Controls ----------------------------------------------------------
00342   if(CONTROLS){
00343 
00344     /* No Longer Doing Elevator Control
00345      
00346      if (rc_4 > 1500){  // Elevator Control
00347      
00348      // If just switched on 
00349      if(sw1 == 0){
00350      I_ELE = 0;                  // Reset integrator to zero 
00351      rc_ele_trim = rc_elevator;  // Remember servo neutral position
00352      }
00353      
00354      sw1 = 1;                                    // Set switch variable to high
00355      del_ELE = 0;                                // Reset to zero
00356      q_c = (float)(KP_RP*(abs(phi_c)));                   // Commanded pitch rate based on rc input
00357      ELE_control(1.0/(float)(MED_LOOP_CLOCK));   // Run the elevator controls algorithm
00358      
00359      }
00360      else{
00361      sw1 = 0;     // Keep switch variable low
00362      }
00363      */
00364 
00365     if (rc_5 > 1500){  // Rudder Control
00366 
00367       // If just switched on 
00368       if(sw2 == 0){
00369         I_RUD = 0;                // Reset integrator to zero
00370         rc_rud_trim = rc_rudder;  // Remember servo neutral position
00371       }
00372 
00373       sw2 = 1;                                    // Set switch variable to high
00374       del_RUD = 0;                                // Reset to zero
00375       // Get phi_c from navigation (outer loop)
00376       phi_c = (rc_rudder - rc_rud_trim)/10.0f;    // Commanded bank based on rc input (inner loop)
00377       RUD_control(1.0/(float)(MED_LOOP_CLOCK));   // Run the rudder controls algorithm
00378 
00379     }
00380     else{
00381       sw2 = 0;    // Keep switch variable low
00382       phi_c = 0.0;
00383     }
00384 
00385     //debug_controls();
00386 
00387   }
00388   else{  //PAYLOAD DROP ----------------------------------------------------------------
00389 
00390     //re-zero controls variables incase we are switching mid-flight
00391     del_THR = 0;
00392     del_RUD = 0;
00393     del_ELE = 0;
00394 
00395     //alternate conditions for dropping (auto-based on GPS, or manual) based on whether GPS is active
00396     boolean condition = false;
00397     if(use_gps == true) { //if GPS is on
00398       condition = rc_4 > 1500;
00399       //condition = gps->latitude > gps_start_lat + 0.0008*10000000; //farther than about 90 m north of start point  //bug, lose rc control
00400       //condition = gps->latitude < 399518950;
00401     }
00402     else { //else do manual
00403       condition = rc_4 > 1500;
00404     }
00405 
00406     //drop condition
00407     if( condition ) {
00408       drop_payload();
00409       drop_state = true;
00410     }
00411     else {
00412       reset_drop();
00413     }
00414 
00415   }
00416 
00417 }
00418 
00419 /**
00420  * Function that runs every so often, as determined by {@link FAST_LOOP_CLOCK}
00421  * @see loop
00422  */
00423 void fast_loop(void) {
00424 
00425   //update DCM
00426   dcm.update_DCM(GYRO_INT_TIME);
00427 
00428 }
00429 
00430 
00431 //Setup and Loop  ---------------------------------------------------
00432 
00433 /**
00434  * Arduino setup() function.  This gets called first when the board is powered
00435  * on.  It sets up the timers and initializes the serial connection as well as 
00436  * any library initialization.
00437  */
00438 void setup(void){
00439 
00440   //Setup timers for fast, medium, slow loops (Arduino millis() command returns
00441   //  current time in milliseconds in an unsigned long)
00442   fast_timer = millis();
00443   medium_timer = millis();
00444   slow_timer = millis();
00445   telemetry_timer = millis();
00446 
00447   //Initialize LED pins, set for output
00448   pinMode(A_LED,OUTPUT);
00449   pinMode(B_LED,OUTPUT);
00450   pinMode(C_LED,OUTPUT);
00451 
00452   //start LEDs ON, then turn them off as initialization progresses
00453   digitalWrite(A_LED,HIGH);
00454   digitalWrite(B_LED,HIGH);
00455   digitalWrite(C_LED,HIGH);
00456 
00457 
00458   //Initialize Serial ---------------------------------------
00459   Serial.begin(115200);  // Initialize Serial Communication (FTDI on Serial 0)
00460   Serial1.begin(38400, 128, 16);  // standard gps running
00461   Serial3.begin(115200);  // Initialize Serial3 for telemetry communication
00462   Serial.println("---------- StoRC Debug ----------");
00463 
00464   //Initialize Slide switch for input
00465   pinMode(SLIDE_SWITCH,INPUT);
00466   slide_sw = digitalRead(SLIDE_SWITCH);
00467 
00468   //slide switch determines whether to use gps or not
00469   if(slide_sw == 1) {
00470     use_gps = true;
00471   }
00472   else {
00473     use_gps = false;
00474   }
00475 
00476   Serial.print("SLIDE SWITCH: ");
00477   Serial.println(slide_sw);
00478 
00479   //Initialize sensors and libraries ---------------------------------------
00480 
00481   adc.Init(); //initialize adc
00482 
00483   //Only initialize GPS if slide switch has determined we should
00484   if(use_gps == true) {
00485     //Set up GPS
00486     gps = &gps_driver;
00487     gps->init();
00488     gps->update();  //force the driver to detect the GPS before checking its status
00489 
00490     //Wait for full GPS lock before proceeding
00491     Serial.println("GPS Init...");
00492     while(gps->status() < 2) {
00493       gps->update();
00494     }
00495     Serial.println(" GPS Locked, waiting for altitude to settle...");
00496     long count = 0;
00497     while(gps->altitude/100.0 < 20 || gps->altitude/100.0 > 50 ) {
00498       if(count == 100000) { //(int)(gps->altitude) % 10 == 0)
00499         Serial.print("   ");  
00500         Serial.println(gps->altitude/100.0);
00501         count = 0;
00502       }
00503       count++;
00504 
00505       gps->update();
00506     }
00507     Serial.println(" Altitude between 30 and 50 meters.");
00508   }
00509   else {
00510     Serial.println("Screw GPS, man...");
00511   }
00512 
00513   digitalWrite(A_LED,LOW);  //done with GPS intialization
00514 
00515   barometer.Init();  //initialize the barometer
00516 
00517   zero_pitot();  //initialize the airspeed measurement (must come after adc init!)
00518 
00519   imu.init(IMU::COLD_START, delay); //intialize IMU on ground, stationary and level
00520   Serial.println();
00521 
00522   digitalWrite(B_LED,LOW);  //done with IMU initialization
00523 
00524   //Initialize Magnetometer stuff
00525   Wire.begin();  //used to communicate with the magnetometer pins
00526 
00527   boolean result = compass.init();
00528   if(result == true) {
00529     Serial.print("Compass found: ");
00530   }
00531   else {
00532     Serial.println("Compass initialization failed");
00533     while (1) {
00534     };
00535   }
00536 
00537   compass.set_orientation(AP_COMPASS_COMPONENTS_DOWN_PINS_FORWARD);  // set compass's orientation on aircraft.
00538   compass.set_offsets(0,0,0);  // set offsets to account for surrounding interference
00539   compass.set_declination(0.213221057);  // set local difference between magnetic north and true north (Philadelphia: 12 deg, 13 min)
00540 
00541   switch( compass.product_id ) {
00542   case AP_COMPASS_TYPE_HIL:
00543     Serial.println("HIL");
00544     break;
00545   case AP_COMPASS_TYPE_HMC5843:
00546     Serial.println("HMC5843");
00547     break;
00548   case AP_COMPASS_TYPE_HMC5883L:
00549     Serial.println("HMC5883L");
00550     break;
00551   default:
00552     Serial.println("unknown");
00553     break;
00554   }
00555 
00556   //DCM
00557   dcm.set_compass(&compass);
00558   dcm.set_centripetal(1);
00559 
00560   //initialize the flash memory
00561   DataFlash.Init();
00562 
00563   if(LOG) {
00564     start_new_log(get_num_logs());  //start a fresh log if logging is turned on
00565   }
00566 
00567   APM_RC.Init();  // Initialize RC library
00568 
00569   //initialize code parameters -----------------------------------
00570 
00571   //Initialize the drop timer
00572   //drop_timer = -1;  
00573   reset_drop();
00574 
00575 
00576   //Initialize accel and gyro readings
00577   imu.update();
00578   accel = imu.get_accel();
00579   gyro = imu.get_gyro();
00580 
00581   //save starting GPS location
00582   if(use_gps == true) {
00583     gps->update();
00584     gps_start_lat = gps->latitude;
00585     gps_start_lon = gps->longitude;
00586   }
00587 
00588   digitalWrite(C_LED,LOW);  //done with initialization
00589 }
00590 
00591 /**
00592  * Arduino loop() function.  This is called immediately after {@link setup} and
00593  * it loops as long as the board is powered.  This function calls everything else
00594  * that runs.  Using timers and periods set by {@link SLOW_LOOP_CLOCK}, 
00595  * {@link MED_LOOP_CLOCK}, and {@link FAST_LOOP_CLOCK}, it determines when to call
00596  * each subfunction and also calls what needs to run at full speed.
00597  */
00598 void loop(void){
00599 
00600   //Full speed loop (things that are done every iteration of loop() )
00601 
00602   read_RC();  //Get RC commands from controller
00603 
00604   // Slow Loop check
00605   if( millis() - slow_timer >= 1000/SLOW_LOOP_CLOCK ) {
00606     slow_timer = millis();
00607     slow_loop();
00608   }
00609 
00610   // Medium Loop check
00611   if( millis() - medium_timer >= 1000/MED_LOOP_CLOCK ) {
00612     medium_timer = millis();
00613     medium_loop();
00614   }
00615 
00616   // Fast Loop check
00617   if( millis() - fast_timer >= 1000/FAST_LOOP_CLOCK ) {
00618     fast_timer = millis();
00619     fast_loop();
00620   }
00621 
00622   //telemetry
00623   if(TELEMETRY) {
00624     if( millis() - telemetry_timer >= 1000/TELEMETRY_CLOCK ) {
00625       telemetry_timer = millis();
00626       transmit_data();
00627     }
00628   }
00629 
00630   //important, higher-speed logging
00631   if(LOG) {
00632     if( millis() - logging_timer >= 1000/LOGGING_CLOCK ) {
00633       logging_timer = millis();
00634 
00635       if (logging_sw > 512) {        
00636         Log_Write_IMU(gyro.x, gyro.y, gyro.z, accel.x, accel.y, accel.z);
00637         Log_Write_Magnetometer(RAD2DEG(compass.heading), dcm.roll_sensor/100.0, dcm.pitch_sensor/100.0, dcm.yaw_sensor/100.0);
00638         Log_Write_Airspeed(airspeed);
00639         Log_Write_RC(rc_elevator,rc_rudder,rc_throttle, rc_4, rc_5, rc_6, rc_7, rc_8);
00640         Log_Write_Controls_Rudder(KP_RUD, kp_rud_gm, KD_RUD, kd_rud_gm, KI_RUD, ki_rud_gm, I_RUD, del_RUD);
00641         //Log_Write_Controls_Elevator(KP_ELE, kp_ele_gm, KP_RP, KI_ELE, ki_ele_gm, I_ELE, del_ELE);
00642         Log_Write_Controls_Throttle(KP_THR, kp_thr_gm, KI_THR, ki_thr_gm, I_THR, del_ALT, del_THR);
00643       }
00644 
00645     }
00646   }
00647 
00648   //decide whether to add controls
00649   if(CONTROLS){
00650 
00651     if (rc_5 > 1500){  // Rudder Control
00652       rc_rudder = rc_rud_trim + del_RUD;
00653     }
00654     if (rc_4 > 1500) {  // Throttle Control
00655       rc_throttle = rc_thr_trim + del_THR;
00656     }
00657 
00658   }
00659 
00660   //debug_controls();
00661   send_RC();  //Send RC commands to outputs
00662 
00663 }
00664 
00665 
00666 
00667 
00668 
00669 
00670 
00671 
00672 
00673 
00674 
00675 
00676 
00677 
00678 
00679 
00680 
00681 
00682 
00683 
00684 
00685 
00686 
00687 
00688 
00689 
00690 
00691