確認用

Dependencies:   HCSR04_2 MPU6050_2 mbed SDFileSystem3

Fork of Autoflight2018_29 by 航空研究会

main.cpp

Committer:
taknokolat
Date:
2018-09-07
Revision:
1:f383708a5a52
Parent:
0:17f575135219
Child:
2:23daa5fa28b4

File content as of revision 1:f383708a5a52:

//mbed
#include "mbed.h"
#include "FATFileSystem.h"
#include "SDFileSystem.h"
//C
#include "math.h"
//sensor
#include "MPU6050_DMP6.h"
//#include "MPU9250.h"
//#include "BMP280.h"
#include "hcsr04.h"
//device
#include "sbus.h"
//config
#include "SkipperSv2.h"
#include "falfalla.h"
//other
#include "pid.h"

#define DEBUG_SEMIAUTO 0
#define DEBUG_PRINT_INLOOP 1

#define KP_ELE 2.0
#define KI_ELE 0.0
#define KD_ELE 0.0
#define KP_RUD 3.0
#define KI_RUD 0.0
#define KD_RUD 0.0
#define KP_AIL 3.0
#define KI_AIL 0.0
#define KD_AIL 0.0




#define GAIN_CONTROLVALUE_TO_PWM 3.0

#define RIGHT_ROLL -12.0
#define RIGHT_PITCH -5.0
#define LEFT_ROLL 12.0
#define LEFT_PITCH -5.0
#define STRAIGHT_ROLL 4.0
#define STRAIGHT_PITCH 3.0
#define TAKEOFF_THR 0.8
#define LOOP_THR 0.6

#define RIGHT_ROLL_SHORT -12.0
#define RIGHT_PITCH_SHORT -5.0
#define LEFT_ROLL_SHORT 12.0
#define LEFT_PITCH_SHORT -5.0

#define GLIDE_ROLL -12.0
#define GLIDE_PITCH -3.0

//コンパスキャリブレーション
//SkipperS2基板
/*
#define MAGBIAS_X -35.0
#define MAGBIAS_Y 535.0
#define MAGBIAS_Z -50.0
*/
//S2v2 1番基板
#define MAGBIAS_X 395.0
#define MAGBIAS_Y 505.0
#define MAGBIAS_Z -725.0
//S2v2 2番基板
/*
#define MAGBIAS_X 185.0
#define MAGBIAS_Y 220.0
#define MAGBIAS_Z -350.0
*/

#define ELEMENT 1
#define LIMIT_STRAIGHT_YAW 5.0 
#define THRESHOLD_TURNINGRADIUS_YAW 60.0 
#define ALLOWHEIGHT 15

#ifndef PI
#define PI 3.14159265358979
#endif

const int16_t lengthdivpwm = 320; 
const int16_t changeModeCount = 6;

const float trim[4] = {Trim_Falfalla[0],Trim_Falfalla[1],Trim_Falfalla[2],Trim_Falfalla[3]};
const float expMax[4] = {ExpMax_Falfalla[0],ExpMax_Falfalla[1],ExpMax_Falfalla[2],ExpMax_Falfalla[3]};
const float expMin[4] = {ExpMin_Falfalla[0],ExpMin_Falfalla[1],ExpMin_Falfalla[2],ExpMin_Falfalla[3]};
const int16_t reverce[4] = {ExpMin_Falfalla[0],Reverce_falfalla[1],Reverce_falfalla[2],Reverce_falfalla[3]};

SBUS sbus(PA_9, PA_10); //SBUS

PwmOut servo1(PC_6); // TIM3_CH1  //old echo
PwmOut servo2(PC_7); // TIM3_CH2    //PC_7
PwmOut servo3(PB_0); // TIM3_CH3
PwmOut servo4(PB_1); // TIM3_CH4
PwmOut servo5(PB_6); // TIM4_CH1
PwmOut servo6(PB_7); // TIM4_CH2  //old trigger
//PwmOut servo7(PB_8); // TIM4_CH3    //PB_8 new echo
//PwmOut servo8(PB_9); // TIM4_CH4   //new trigger

RawSerial pc(PA_2,PA_3, 115200);    //tx,rx.baudrate pin;PA_2=UART2_TX, PA_3=UART2_RX
//RawSerial pc2(PB_6,PB_7, 115200);   //sbus確認用
SDFileSystem sd(PB_15, PB_14, PB_13, PB_12, "sd");

DigitalOut led1(PA_0);  //黄色のコネクタ
DigitalOut led2(PA_1);
DigitalOut led3(PB_4); 
DigitalOut led4(PB_5);

//InterruptIn switch2(PC_14);
MPU6050DMP6 mpu6050(PC_0,&pc); //割り込みピン,シリアルポインタ i2cのピン指定は MPU6050>>I2Cdev.h 内のdefine
HCSR04 usensor(PB_9,PB_8); //trig,echo  9,8 

PID pid_AIL(g_kpAIL,g_kiAIL,g_kdAIL);
PID pid_ELE(g_kpELE,g_kiELE,g_kdELE);
PID pid_RUD(g_kpRUD,g_kiRUD,g_kdRUD);

enum Channel{AIL_R, ELE, THR, RUD, DROP, AIL_L, Ch7, Ch8};
enum Angle{ROLL, PITCH, YAW};   //yaw:北を0とした絶対角度
enum OperationMode{StartUp, SemiAuto, RightLoop, LeftLoop, GoStraight, BombwithPC, ZERO, Moebius, Glide};
enum BombingMode{Takeoff, Chicken, Transition, Approach};
enum OutputStatus{Manual, Auto};

static OutputStatus output_status = Manual;
OperationMode operation_mode = StartUp;
BombingMode bombing_mode = Takeoff;
static int16_t autopwm[8] = {1500,1500,1180,1500,1392,1500};
static int16_t trimpwm[6] = {1500,1500,1180,1500,1392,1500};
int16_t maxpwm[6] = {1820,1820,1820,1820,1820,1820};
int16_t minpwm[6] = {1180,1180,1180,1180,1180,1180};
int16_t oldTHR = 1000;

static float nowAngle[3] = {0,0,0};
const float trimAngle[3] = {0.0, 0.0, 0.0};
const float maxAngle[2] = {90, 90};
const float minAngle[2] = {-90, -90};

float FirstROLL = 0.0, FirstPITCH = 0.0 ,FirstYAW = 0.0;

unsigned int g_distance;
Ticker USsensor;
static char g_buf[16];
char g_landingcommand;
float g_SerialTargetYAW;

Timer t;
Timeout RerurnChickenServo1;
Timeout RerurnChickenServo2;

/*-----関数のプロトタイプ宣言-----*/
void setup();
void loop();

void Init_PWM();
void Init_servo();              //サーボ初期化
void Init_sbus();               //SBUS初期化
void Init_sensors();
void DisplayClock();            //クロック状態確認

//センサの値取得
void SensingMPU();
void UpdateDist();

//void offsetRollPitch(float FirstROLL, float FirstPITCH);
//void TransYaw(float FirstYAW);
float TranslateNewYaw(float beforeYaw,  float newzeroYaw);
void UpdateTargetAngle(float targetAngle[3]);
void CalculateControlValue(float targetAngle[3], float controlValue[3]);
void UpdateAutoPWM(float controlValue[3]);
void ConvertPWMintoRAD(float targetAngle[3]);
inline float CalcRatio(float value, float trim, float limit);
bool CheckSW_Up(Channel ch);
int16_t ThresholdMaxMin(int16_t value, int16_t max, int16_t min);
inline int16_t SetTHRinRatio(float ratio);

//sbus割り込み
void Update_PWM();              //マニュアル・自動モードのpwmデータを整形しpwm変数に入力
void Output_PWM(int16_t pwm[6]);    //pwmをサーボへ出力

//シリアル割り込み
void SendSerial();   //1文字きたら送り返す
void SendArray();
void getSF_Serial();
float ConvertByteintoFloat(char high, char low);
void ISR_Serial_Rx();

//SD設定
int GetParameter(FILE *fp, const char *paramName,char parameter[]);
int SetOptions(float *g_kpELE, float *g_kiELE, float *g_kdELE,
               float *g_kpRUD, float *g_kiRUD, float *g_kdRUD,
               float *g_rightloopROLL, float *g_rightloopPITCH,
               float *g_leftloopROLL, float *g_leftloopPITCH,
               float *g_gostraightROLL, float *g_gostraightPITCH,
               float *g_takeoffTHR, float *g_loopTHR,
               float *g_rightloopROLLshort, float *g_rightloopPITCHshort,
               float *g_leftloopROLLshort, float *g_leftloopPITCHshort,
               float *g_glideloopROLL, float *g_glideloopPITCH);
//switch2割り込み
void ResetTrim();

//自動操縦
void UpdateTargetAngle_GoStraight(float targetAngle[3]);
void UpdateTargetAngle_Rightloop(float targetAngle[3]);
void UpdateTargetAngle_Rightloop_short(float targetAngle[3]);
void UpdateTargetAngle_Leftloop(float targetAngle[3]);
void UpdateTargetAngle_Leftloop_short(float targetAngle[3]);
void UpdateTargetAngle_Moebius(float targetAngle[3]);
void UpdateTargetAngle_Glide(float targetAngle[3]);
void UpdateTargetAngle_Takeoff(float targetAngle[3]);
void UpdateTargetAngle_Approach(float targetAngle[3]);
void Take_off_and_landing(float targetAngle[3]);

int Rotate(float targetAngle[3], float TargetYAW);

//投下
void Chicken_Drop();
void ReturnChickenServo1();
void ReturnChickenServo2();

//超音波による高度補正
void checkHeight(float targetAngle[3]);
void UpdateTargetAngle_NoseUP(float targetAngle[3]);
void UpdateTargetAngle_NoseDOWN(float targetAngle[3]);

//デバッグ用
void DebugPrint();

/*---関数のプロトタイプ宣言終わり---*/

int main()
{   
    setup();
    
    
    while(1){
        
        loop();
        
        if(!CheckSW_Up(Ch7)){
            led3=0;
        }else{
            led3=1;
        }
    }
    
}

void setup(){
    //buzzer = 0;
    led1 = 1;
    led2 = 1;
    led3 = 1;
    led4 = 1;
    
    SetOptions(&g_kpELE, &g_kiELE, &g_kdELE,
               &g_kpRUD, &g_kiRUD, &g_kdRUD,
               &g_rightloopROLL, &g_rightloopPITCH,
               &g_leftloopROLL, &g_leftloopPITCH,
               &g_gostraightROLL, &g_gostraightPITCH,
               &g_takeoffTHR, &g_loopTHR,
               &g_rightloopROLLshort, &g_rightloopPITCHshort,
               &g_leftloopROLLshort, &g_leftloopPITCHshort,
               &g_glideloopROLL, &g_glideloopPITCH);    
    
        
    Init_PWM();
    Init_servo();
    Init_sbus();    
    Init_sensors();
    //switch2.rise(ResetTrim);
    pc.attach(getSF_Serial, Serial::RxIrq);
    USsensor.attach(&UpdateDist, 0.05);
    
    NVIC_SetPriority(USART1_IRQn,0);
    NVIC_SetPriority(EXTI0_IRQn,1);
    NVIC_SetPriority(TIM5_IRQn,2);
    NVIC_SetPriority(EXTI9_5_IRQn,3);
    NVIC_SetPriority(USART2_IRQn,4);
    DisplayClock();
    t.start();
    
    
    pc.printf("MPU calibration start\r\n");
    
    float offsetstart = t.read();
    while(t.read() - offsetstart < 26){
        SensingMPU();
        for(uint8_t i=0; i<3; i++) pc.printf("%3.2f\t",nowAngle[i]);
        pc.printf("\r\n");
        led1 = !led1;
        led2 = !led2;
        led3 = !led3;
        led4 = !led4;
    }
    
    FirstROLL = nowAngle[ROLL];
    FirstPITCH = nowAngle[PITCH];
    nowAngle[ROLL] -=FirstROLL;
    nowAngle[PITCH] -=FirstPITCH;
    
    led1 = 0;
    led2 = 0;
    led3 = 0;
    led4 = 0;
    wait(0.2);
    
    
    pc.printf("All initialized\r\n");
}

void loop(){
    static float targetAngle[3] = {0.0, 0.0, 0.0}, controlValue[2] = {0.0, 0.0};

    SensingMPU();
    UpdateTargetAngle(targetAngle);
    //Rotate(targetAngle, 30.0);
    CalculateControlValue(targetAngle, controlValue);
    UpdateAutoPWM(controlValue);
    wait_ms(23);
#if DEBUG_PRINT_INLOOP
    DebugPrint();
#endif
}

//サーボ初期化関数
void Init_servo(){
    
    servo1.period_ms(14);
    servo1.pulsewidth_us(trimpwm[AIL_R]);
    
    servo2.period_ms(14);
    servo2.pulsewidth_us(trimpwm[ELE]);
    
    servo3.period_ms(14);
    servo3.pulsewidth_us(trimpwm[THR]);
    
    servo4.period_ms(14);
    servo4.pulsewidth_us(trimpwm[RUD]);
    
    servo5.period_ms(14);
    servo5.pulsewidth_us(1392);

    servo6.period_ms(14);
    servo6.pulsewidth_us(trimpwm[AIL_L]);

    pc.printf("servo initialized\r\n");
}

//Sbus初期化
void Init_sbus(){
    sbus.initialize();
    sbus.setLastfuncPoint(Update_PWM);
    sbus.startInterrupt();
}

void Init_sensors(){
    if(mpu6050.setup() == -1){
        pc.printf("failed initialize\r\n");
        while(1){
            led1 = 1; led2 = 0; led3 = 1; led4 = 0;
            wait(1);
            led1 = 0; led2 = 1; led3 = 0; led4 = 1;
            wait(1);
        }
    }
}

void Init_PWM(){
    for (uint8_t i = 0; i < 4; ++i){
        trimpwm[i] = 1500 + (int16_t)(lengthdivpwm * (trim[i]/100));
        maxpwm[i] = 1500 + (int16_t)(lengthdivpwm * (expMax[i]/100));
        minpwm[i] = 1500 - (int16_t)(lengthdivpwm * (expMin[i]/100));
    }
    pc.printf("PWM initialized\r\n");
}

void DisplayClock(){
    pc.printf("System Clock = %d[MHz]\r\n", HAL_RCC_GetSysClockFreq()/1000000);
    pc.printf("HCLK Clock   = %d[MHz]\r\n", HAL_RCC_GetHCLKFreq()/1000000);
    pc.printf("PCLK1 Clock  = %d[MHz]\r\n", HAL_RCC_GetPCLK1Freq()/1000000);
    pc.printf("PCLK2 Clock  = %d[MHz]\r\n", HAL_RCC_GetPCLK2Freq()/1000000);
    pc.printf("\r\n");
}

void UpdateTargetAngle(float targetAngle[3]){
    static int16_t count_op = 0;
#if DEBUG_SEMIAUTO    
    switch(operation_mode){
        case StartUp:
            if(!CheckSW_Up(Ch7) && CheckSW_Up(Ch8)){
                count_op++;
                if(count_op > changeModeCount){
                    operation_mode = SemiAuto;
                    pc.printf("Goto SemiAuto mode\r\n");
                    count_op = 0;
                }
            }else count_op = 0;
            break;

        case SemiAuto:
        /*  大会用では以下のif文を入れてoperation_modeを変える
            if(CheckSW_Up(Ch6)){
                count_op++;
                if(count_op>changeModeCount){
                    output_status = XXX;
                    led2 = 0;
                    pc.printf("Goto XXX mode\r\n");
                    count_op = 0;
                }else count_op = 0;
                ConvertPWMintoRAD(targetAngle);
            }
        */
            ConvertPWMintoRAD(targetAngle);
            break;

        default:
            operation_mode = SemiAuto;
            break;
    }

#else

    switch(operation_mode){
        case StartUp:
            if(!CheckSW_Up(Ch7) && !CheckSW_Up(Ch8)){        //ch7;自動・手動切り替え ch8;自動操縦モード切替
                count_op++;
                if(count_op > changeModeCount){
                    operation_mode = RightLoop;
                    pc.printf("Goto RightLoop mode\r\n");
                    count_op = 0;
                }
            }else count_op = 0;
            break;

        case RightLoop:
            if(!CheckSW_Up(Ch7) && CheckSW_Up(Ch8)){
                count_op++;
                if(count_op > changeModeCount){
                    operation_mode = LeftLoop;
                    pc.printf("Goto LeftLoop mode\r\n");
                    count_op = 0;
                }
            }else count_op = 0;
            UpdateTargetAngle_Rightloop(targetAngle);
            
            break;

        case LeftLoop:
            if(!CheckSW_Up(Ch7) && !CheckSW_Up(Ch8)){
                count_op++;
                if(count_op > changeModeCount){
                    operation_mode = GoStraight;
                    pc.printf("Goto GoStraight mode\r\n");
                    count_op = 0;
                }
            }else count_op = 0;
            UpdateTargetAngle_Leftloop(targetAngle);
            break;
        
        case GoStraight:
            if(!CheckSW_Up(Ch7) && CheckSW_Up(Ch8)){
                count_op++;
                if(count_op > changeModeCount){
                    operation_mode = Moebius;
                    pc.printf("Goto Moebius mode\r\n");
                    count_op = 0;
                }
            }else count_op = 0;
            UpdateTargetAngle_GoStraight(targetAngle);
            break;

        case Moebius:
            if(!CheckSW_Up(Ch7) && !CheckSW_Up(Ch8)){
                count_op++;
                if(count_op > changeModeCount){
                    operation_mode = Glide;
                    pc.printf("Goto Glide mode\r\n");
                    count_op = 0;
                }
            }else count_op = 0;
            UpdateTargetAngle_Moebius(targetAngle);
            break;

        case Glide:
            if(!CheckSW_Up(Ch7) && CheckSW_Up(Ch8)){
                count_op++;
                if(count_op > changeModeCount){
                    operation_mode = BombwithPC;
                    pc.printf("Goto Bombing mode\r\n");
                    count_op = 0;
                }
            }else count_op = 0;
            UpdateTargetAngle_Glide(targetAngle);
            break;

        case BombwithPC:
            if(!CheckSW_Up(Ch7) && !CheckSW_Up(Ch8)){
                count_op++;
                if(count_op > changeModeCount){
                    operation_mode = RightLoop;
                    pc.printf("Goto RightLoop mode\r\n");
                    count_op = 0;
                }
            }else count_op = 0;
            Take_off_and_landing(targetAngle);
            break;

        default:
            operation_mode = StartUp;
            break;
    }
#endif

    if(CheckSW_Up(Ch7)){
        output_status = Auto;
        led1 = 1;
    }else{
        output_status = Manual;
        led1 = 0;
    }
}

int GetParameter(FILE *fp, const char *paramName,char parameter[]){
    int i=0, j=0;
    int strmax = 200;
    char str[strmax];

    rewind(fp); //ファイル位置を先頭に
    while(1){
        if (fgets(str, strmax, fp) == NULL) {
            return 0;
        }
        if (!strncmp(str, paramName, strlen(paramName))) {
            while (str[i++] != '=') {}
            while (str[i] != '\n') {
                    parameter[j++] = str[i++];
            }
            parameter[j] = '\0';
            return 1;
        }
    }
    return 0;
}


//sdによる設定
int SetOptions(float *g_kpELE, float *g_kiELE, float *g_kdELE,
               float *g_kpRUD, float *g_kiRUD, float *g_kdRUD,
               float *g_rightloopROLL, float *g_rightloopPITCH,
               float *g_leftloopROLL, float *g_leftloopPITCH,
               float *g_gostraightROLL, float *g_gostraightPITCH,
               float *g_takeoffTHR, float *g_loopTHR,
               float *g_rightloopROLLshort, float *g_rightloopPITCHshort,
               float *g_leftloopROLLshort, float *g_leftloopPITCHshort,
               float *g_glideloopROLL, float *g_glideloopPITCH
               ){

    pc.printf("SDsetup start.\r\n");    
    
    FILE *fp;
    char parameter[30]; //文字列渡す用の配列
    int SDerrorcount = 0;  //取得できなかった数を返す
    const char *paramNames[] = { 
        "KP_ELEVATOR",
        "KI_ELEVATOR",
        "KD_ELEVATOR",
        "KP_RUDDER",
        "KI_RUDDER",
        "KD_RUDDER",
        "RIGHTLOOP_ROLL",
        "RIGHTLOOP_PITCH",
        "LEFTLOOP_ROLL",
        "LEFTLOOP_PITCH",
        "GOSTRAIGHT_ROLL",
        "GOSTRAIGHT_PITCH",
        "TAKEOFF_THR_RATE",
        "LOOP_THR_RATE",
        "RIGHTLOOP_ROLL_SHORT",
        "RIGHTLOOP_PITCH_SHORT",
        "LEFTLOOP_ROLL_SHORT",
        "LEFTLOOP_PITCH_SHORT",
        "AUTOGLIDE_ROLL",
        "AUTOGLIDE PITCH"        
    };

    fp = fopen("/sd/option.txt","r");
    
    if(fp != NULL){ //開けたら
        pc.printf("File was openned.\r\n");
        if(GetParameter(fp,paramNames[0],parameter)) *g_kpELE = atof(parameter);
        else{                                        *g_kpELE = KP_ELE;
                                                     SDerrorcount++;
        }
        if(GetParameter(fp,paramNames[1],parameter)) *g_kiELE = atof(parameter);
        else{                                        *g_kiELE = KI_ELE;
                                                      SDerrorcount++;
        }
        if(GetParameter(fp,paramNames[2],parameter)) *g_kdELE = atof(parameter);
        else{                                        *g_kdELE = KD_ELE;
                                                     SDerrorcount++;
        }
        if(GetParameter(fp,paramNames[3],parameter)) *g_kpRUD = atof(parameter);
        else{                                        *g_kpRUD = KP_RUD;
                                                      SDerrorcount++;
        }
        if(GetParameter(fp,paramNames[4],parameter)) *g_kiRUD = atof(parameter);
        else{                                        *g_kiRUD = KI_RUD;
                                                      SDerrorcount++;
        }
        if(GetParameter(fp,paramNames[5],parameter)) *g_kdRUD = atof(parameter);
        else{                                        *g_kdRUD = KD_RUD;
                                                      SDerrorcount++;
        }
        if(GetParameter(fp,paramNames[6],parameter)) *g_rightloopROLL = atof(parameter);
        else{                                        *g_rightloopROLL = RIGHT_ROLL;
                                                      SDerrorcount++;
        }
        if(GetParameter(fp,paramNames[7],parameter)) *g_rightloopPITCH = atof(parameter);
        else{                                        *g_rightloopPITCH = RIGHT_PITCH;
                                                      SDerrorcount++;
        }
        if(GetParameter(fp,paramNames[8],parameter)) *g_leftloopROLL = atof(parameter);
        else{                                        *g_leftloopROLL = LEFT_ROLL;
                                                      SDerrorcount++;
        }
        if(GetParameter(fp,paramNames[9],parameter)) *g_leftloopPITCH = atof(parameter);
        else{                                         *g_leftloopPITCH = LEFT_PITCH;
                                                      SDerrorcount++;
        }
        if(GetParameter(fp,paramNames[10],parameter)) *g_gostraightROLL = atof(parameter);
        else{                                         *g_gostraightROLL = STRAIGHT_ROLL;
                                                      SDerrorcount++;
        }
        if(GetParameter(fp,paramNames[11],parameter)) *g_gostraightPITCH = atof(parameter);
        else{                                         *g_gostraightPITCH = STRAIGHT_PITCH;
                                                      SDerrorcount++;
        }
        if(GetParameter(fp,paramNames[12],parameter)) *g_takeoffTHR = atof(parameter);
        else{                                         *g_takeoffTHR = TAKEOFF_THR;
                                                      SDerrorcount++;
        }
        if(GetParameter(fp,paramNames[13],parameter)) *g_loopTHR = atof(parameter);
        else{                                         *g_loopTHR = LOOP_THR;
                                                      SDerrorcount++;
        }
        if(GetParameter(fp,paramNames[14],parameter)) *g_rightloopROLLshort = atof(parameter);
        else{                                         *g_rightloopROLLshort = RIGHT_ROLL_SHORT;
                                                      SDerrorcount++;
        }
        if(GetParameter(fp,paramNames[15],parameter)) *g_rightloopPITCHshort = atof(parameter);
        else{                                         *g_rightloopPITCHshort = RIGHT_PITCH_SHORT;
                                                      SDerrorcount++;
        }
        if(GetParameter(fp,paramNames[16],parameter)) *g_leftloopROLLshort = atof(parameter);
        else{                                         *g_leftloopROLLshort = LEFT_ROLL_SHORT;
                                                      SDerrorcount++;
        }
        if(GetParameter(fp,paramNames[17],parameter)) *g_leftloopPITCHshort = atof(parameter);
        else{                                         *g_leftloopPITCHshort = LEFT_PITCH_SHORT;
                                                      SDerrorcount++;
        }
        if(GetParameter(fp,paramNames[18],parameter)) *g_glideloopROLL = atof(parameter);
        else{                                         *g_glideloopROLL = GLIDE_ROLL;
                                                      SDerrorcount++;
        }
        if(GetParameter(fp,paramNames[19],parameter)) *g_glideloopPITCH = atof(parameter);
        else{                                         *g_glideloopPITCH = GLIDE_PITCH;
                                                      SDerrorcount++;
        }
        fclose(fp);

    }else{  //ファイルがなかったら
        pc.printf("fp was null.\r\n");
        *g_kpELE = KP_ELE;
        *g_kiELE = KI_ELE;
        *g_kdELE = KD_ELE;
        *g_kpRUD = KP_RUD;
        *g_kiRUD = KI_RUD;
        *g_kdRUD = KD_RUD;
        *g_rightloopROLL = RIGHT_ROLL;
        *g_rightloopPITCH = RIGHT_PITCH;
        *g_leftloopROLL = LEFT_ROLL;
        *g_leftloopPITCH = LEFT_PITCH;
        *g_gostraightROLL = STRAIGHT_ROLL;
        *g_gostraightPITCH = STRAIGHT_PITCH;
        *g_takeoffTHR = TAKEOFF_THR;
        *g_loopTHR = LOOP_THR;
        SDerrorcount = -1;
    }
    pc.printf("SDsetup finished.\r\n");
    if(SDerrorcount == 0)  pc.printf("setting option is success\r\n");
    else if(SDerrorcount == -1) pc.printf("ERROR 1. cannot open option\r\n");
    else if(SDerrorcount > 0)  pc.printf("ERROR 2. reading parameter is failed[%d]\r\n",SDerrorcount); 
    
    pc.printf("kpELE = %f, kiELE = %f, kdELE = %f\r\n", *g_kpRUD, *g_kiRUD, *g_kdRUD);
    pc.printf("kpRUD = %f, kiRUD = %f, kdRUD = %f\r\n", *g_kpELE, *g_kiELE, *g_kdELE);
    pc.printf("rightloopROLL = %f, rightloopPITCH = %f\r\n", *g_rightloopROLL, *g_rightloopPITCH);
    pc.printf("leftloopROLL = %f, g_leftloopPITCH =  %f\r\n", *g_leftloopROLL, *g_leftloopPITCH);
    pc.printf("gostraightROLL = %f, g_gostraightPITCH = %f\r\n", *g_gostraightROLL, *g_gostraightPITCH);
    pc.printf("g_takeoffTHR = %f, g_loopTHR = %f\r\n", *g_takeoffTHR, *g_loopTHR);
    pc.printf("rightloopROLLshort = %f, rightloopPITCHshort = %f\r\n", *g_rightloopROLLshort, *g_rightloopPITCHshort);
    pc.printf("leftloopROLLshort = %f, g_leftloopPITCHshort =  %f\r\n", *g_leftloopROLLshort, *g_leftloopPITCHshort);
    pc.printf("glideROLL = %f, glidePITCH = %f\r\n", *g_glideloopROLL, *g_glideloopPITCH);
    
    return SDerrorcount;
}                  

void CalculateControlValue(float targetAngle[3], float controlValue[3]){
    static int t_last;
    int t_now;
    float dt;

    t_now = t.read_us();
    dt = (float)((t_now - t_last)/1000000.0f) ;
    t_last = t_now;


    //controlValue[ROLL] = pid_RUD.calcPID(nowAngle[ROLL], targetAngle[ROLL], dt);
    controlValue[ROLL] = pid_AIL.calcPID(nowAngle[ROLL], targetAngle[ROLL], dt);       //エルロンでロール制御   
    controlValue[PITCH] = pid_ELE.calcPID(nowAngle[PITCH], targetAngle[PITCH], dt);
}

void UpdateAutoPWM(float controlValue[3]){    
    int16_t addpwm[2]; //-500~500
    addpwm[PITCH] = (float)GAIN_CONTROLVALUE_TO_PWM * controlValue[PITCH];    //センサ:機首下げ正    レバー:機首上げ正
    addpwm[ROLL] = (float)GAIN_CONTROLVALUE_TO_PWM * controlValue[ROLL];           //センサ:右回転正(8月13日時点;左回転が正!)     レバー:右回転正
    
    //autopwm[ELE] = trimpwm[ELE] + reverce[ELE] * addpwm[PITCH];
    autopwm[AIL_R] = trimpwm[AIL_R] + reverce[AIL_R] * addpwm[AIL_R];
    //autopwm[THR] = oldTHR;

    autopwm[ELE] = ThresholdMaxMin(autopwm[ELE], maxpwm[ELE], minpwm[ELE]);
    autopwm[AIL_R] = ThresholdMaxMin(autopwm[AIL_R], maxpwm[AIL_R], minpwm[AIL_R]);
}

inline float CalcRatio(float value, float trim, float limit){
    return  (value - trim) / (limit - trim);
}

bool CheckSW_Up(Channel ch){
    if(SWITCH_CHECK < sbus.manualpwm[ch]){
        return true;
    }else{
        return false;
    }
}

int16_t ThresholdMaxMin(int16_t value, int16_t max, int16_t min){
    if(value > max) return max;
    if(value < min) return min;
    return value;
}

inline int16_t SetTHRinRatio(float ratio){
    return minpwm[THR] + (int16_t)(2 * lengthdivpwm * ratio);
}

/*---SBUS割り込み処理---*/

//udate_Inputで抽出したpwmデータを整形して各変数に代入する。(マニュアルモード)
//各stabiGylo関数で算出したpwmを各変数に代入する(自動モード)
void Update_PWM()
{    
    static int16_t pwm[6];
    static int16_t temppwm[6]={trimpwm[0],trimpwm[1],trimpwm[2],trimpwm[3],trimpwm[4],trimpwm[5]};
    if(sbus.flg_ch_update == true){
        switch(output_status){    //マニュアルモード,自動モード,自動着陸もモードを切替
            case Manual: 
                for(uint8_t i=0;i<6;i++){
                    pwm[i] = sbus.manualpwm[i];  
                }
                pc.printf("%d ,",pwm[0]);//R
                pc.printf("%d ,\r\n",pwm[5]);//L
                oldTHR = sbus.manualpwm[THR];
                //pc.printf("update_manual\r\n");
                break;
        
            case Auto:
                pwm[AIL_R] = autopwm[AIL_R];               //sbus.manualpwm[AIL];
                pwm[ELE] = autopwm[ELE];
                pwm[THR] = autopwm[THR];
                pwm[RUD] = autopwm[RUD];
                pwm[DROP] = autopwm[DROP];
                pwm[AIL_L] = autopwm[AIL_L];
                //pc.printf("update_auto\r\n");
                break;
                
            default:
                for(uint8_t i=0;i<6;i++){
                    pwm[i] = sbus.manualpwm[i];
                } //pc.printf("update_manual\r\n");
                break;
        }
        for(uint8_t i=0;i<6;i++){
        if(pwm[i]<1000 || pwm[i]>2000) pwm[i]=temppwm[i];
        temppwm[i]=pwm[i];
        }
    }else{
        pc.printf("0\r\n");
    }
    sbus.flg_ch_update = false;   
    Output_PWM(pwm);  
}


//pwmをサーボに出力。
void Output_PWM(int16_t pwm[5])
{
    servo1.pulsewidth_us(pwm[0]);
    servo2.pulsewidth_us(pwm[1]);
    servo3.pulsewidth_us(pwm[2]);
    servo4.pulsewidth_us(pwm[3]);
    servo5.pulsewidth_us(pwm[4]);
    servo6.pulsewidth_us(pwm[5]);

}

void ResetTrim(){
    for(uint8_t i=0; i<6; i++){            //i=4から書き換え_投下サーボは入ってない模様
        trimpwm[i] = sbus.manualpwm[i];
    }
    pc.printf("reset PWM trim\r\n");
}


void SensingMPU(){
    //static int16_t deltaT = 0, t_start = 0;
    //t_start = t.read_us();
    
    float rpy[3] = {0}, oldrpy[3] = {0};
    static uint16_t count_changeRPY = 0;
    static bool flg_checkoutlier = false;
    NVIC_DisableIRQ(USART1_IRQn);
    NVIC_DisableIRQ(USART2_IRQn);
    NVIC_DisableIRQ(TIM5_IRQn);
    NVIC_DisableIRQ(EXTI0_IRQn);
    NVIC_DisableIRQ(EXTI9_5_IRQn);

    mpu6050.getRollPitchYaw_Skipper(rpy);
 
    NVIC_EnableIRQ(USART1_IRQn);
    NVIC_EnableIRQ(USART2_IRQn);
    NVIC_EnableIRQ(TIM5_IRQn);
    NVIC_EnableIRQ(EXTI0_IRQn);
    NVIC_EnableIRQ(EXTI9_5_IRQn);
    
    
    //外れ値対策
    for(uint8_t i=0; i<3; i++) rpy[i] *= 180.0f/PI;
    rpy[ROLL] -= FirstROLL;
    rpy[PITCH] -= FirstPITCH;
    rpy[YAW] -= FirstYAW;
    
    for(uint8_t i=0; i<3; i++) {if(rpy[i] < nowAngle[i]-10 || rpy[i] > nowAngle[i]+10) {flg_checkoutlier = true;}}
    if(!flg_checkoutlier || count_changeRPY >= 2){
        for(uint8_t i=0; i<3; i++){
            nowAngle[i] = (rpy[i] + nowAngle[i])/2.0f;  //2つの移動平均
        }
        count_changeRPY = 0;
    }else   count_changeRPY++;
    flg_checkoutlier = false;
    
}

float TranslateNewYaw(float beforeYaw,  float newzeroYaw){
    float newYaw = beforeYaw - newzeroYaw;
    
    if(newYaw<-180.0f) newYaw += 360.0f;
    else if(newYaw>180.0f) newYaw -= 360.0f;
    return newYaw;
}


void getSF_Serial(){
    
        static char SFbuf[16];
        static int bufcounter=0;
        
        SFbuf[bufcounter]=pc.getc();
        if(SFbuf[0]=='S'&&bufcounter<5) bufcounter++;
            
        if(bufcounter==5 && SFbuf[4]=='F'){
            g_landingcommand = SFbuf[1];
            if(g_landingcommand=='Y')g_SerialTargetYAW = ConvertByteintoFloat(SFbuf[2], SFbuf[3]);
            bufcounter = 0;
            memset(SFbuf, 0, strlen(SFbuf));
            pc.printf("command = %c, commandYAW = %f\r\n", g_landingcommand, g_SerialTargetYAW); 
        }
            else if(bufcounter>=5 && g_buf[4]!='F'){
                pc.printf("Communication Falsed.\r\n");
                bufcounter = 0;
            }
    }
    
float ConvertByteintoFloat(char high, char low){

        //int16_t intvalue = (int16_t)high*256 + (int16_t)low;
        int16_t intvalue = (int16_t)(((int16_t)high << 8) | low);  // Turn the MSB and LSB into a signed 16-bit value
        float floatvalue = (float)intvalue;
        return floatvalue;
}


//超音波割り込み
void UpdateDist(){
    g_distance = usensor.get_dist_cm();
    usensor.start();
}

//8の字旋回
void UpdateTargetAngle_Moebius(float targetAngle[3]){
    static uint8_t RotateCounter=0;
    static bool flg_setInStartAuto = false;
    static float FirstYAW_Moebius = 0.0;
    float newYaw_Moebius;

    if(!flg_setInStartAuto && CheckSW_Up(Ch7)){
        FirstYAW_Moebius = nowAngle[YAW];
        RotateCounter = 0;
        flg_setInStartAuto = true;
    }else if(!CheckSW_Up(Ch7)){
        flg_setInStartAuto = false;
        led2 = 0;
    }
    
    newYaw_Moebius = TranslateNewYaw(nowAngle[YAW], FirstYAW_Moebius);

    if(RotateCounter == 0 && newYaw_Moebius >90.0 && newYaw_Moebius < 180.0)    {RotateCounter++; led2 = 1; pc.printf("Rotate 90\r\n");}
    if(RotateCounter == 1 && newYaw_Moebius >-180.0 && newYaw_Moebius < -90.0)  {RotateCounter++; led2 = 0; pc.printf("Rotate 180\r\n");}
    if(RotateCounter == 2 && newYaw_Moebius >-90.0 && newYaw_Moebius < 10.0f)   {RotateCounter++; led2 = 1; pc.printf("Rotate 270\r\n");}
    if(RotateCounter == 3 && newYaw_Moebius >20.0 && newYaw_Moebius < 180.0f)     {RotateCounter++; led2 = 0; pc.printf("Change Rotate direction\r\n");}


    if(RotateCounter <= 3) UpdateTargetAngle_Rightloop_short(targetAngle);    
    else UpdateTargetAngle_Leftloop_short(targetAngle);   //左旋回

}

//自動滑空
void UpdateTargetAngle_Glide(float targetAngle[3]){
    static int THRcount = 0;
    static int t_start = 0;
    static bool flg_tstart = false;
    int t_diff = 0;
    static int groundcount = 0;
    
    targetAngle[ROLL] = g_glideloopROLL;
    targetAngle[PITCH] = g_glideloopPITCH;
    
    autopwm[THR]=oldTHR;
    //シリアル通信受信の割り込みイベント登録
    pc.attach(ISR_Serial_Rx, Serial::RxIrq);
    
/*    
    //時間計測開始設定
    if(!flg_tstart && CheckSW_Up(Ch7)){
        t_start = t.read();
        flg_tstart = true;
        pc.printf("timer start\r\n");
    }else if(!CheckSW_Up(Ch7)){
        t_start = 0;
        flg_tstart = false;
    }


    //フラグが偽であれば計測は行わない    
    if(flg_tstart){
        t_diff = t.read() - t_start;
        //一定高度or15秒でled点灯
        if((groundcount>5 && g_distance>0) || t_diff > 15){
            led2 = 1;
            //pc.printf("Call [Stop!] calling!\r\n");
        }
        if(g_distance<180 && g_distance > 0) groundcount++;
    }else{
        t_diff = 0;
        groundcount = 0;
        led2 = 0;
    }
    
    if(t_diff > 17){
        autopwm[THR] = SetTHRinRatio(0.5);
    }else{
        if(g_distance<150 && g_distance>0 ){
            THRcount++;
            if(THRcount>5){
                autopwm[THR] = SetTHRinRatio(0.6);
                //pc.printf("throttle ON\r\n");
            }
        }else{
            autopwm[THR] = 1180;
            THRcount = 0;
        }
    }*/
}
//離陸-投下-着陸一連
void Take_off_and_landing(float targetAngle[3]){
    if(!CheckSW_Up(Ch7)) bombing_mode = Takeoff;
    
    switch(bombing_mode){
        case Takeoff:
            static bool flg_setFirstYaw = false;
            static int TakeoffCount = 0;

            if(!flg_setFirstYaw && CheckSW_Up(Ch7)){
                FirstYAW = nowAngle[YAW];
                flg_setFirstYaw = true;
            }else if(flg_setFirstYaw && !CheckSW_Up(Ch7)){
                flg_setFirstYaw = false;
            }
            
            UpdateTargetAngle_Takeoff(targetAngle);
            
            if(g_distance>150) TakeoffCount++;
            else TakeoffCount = 0;
            if(TakeoffCount>5){
                autopwm[THR] = 1180+320*2*0.5;
                pc.printf("Now go to Approach mode!!");
                bombing_mode = Approach;
            }
            break;
        /*    
        case Chicken:    
            break;
        */    
        case Transition:
            static int ApproachCount = 0;
            targetAngle[YAW]=180.0;
            int Judge = Rotate(targetAngle, g_SerialTargetYAW);
            
            if(Judge==0) ApproachCount++;
            if(ApproachCount>5) bombing_mode = Approach;
            break;
            
        case Approach:
            UpdateTargetAngle_Approach(targetAngle);
            break;
            
        default:
            bombing_mode = Takeoff;
            break;    
    }
}

//離陸モード
void UpdateTargetAngle_Takeoff(float targetAngle[3]){
    //pc.printf("%d \r\n",g_distance);
    targetAngle[ROLL] = g_gostraightROLL;
    targetAngle[PITCH] = g_loopTHR;
    autopwm[THR] = SetTHRinRatio(g_takeoffTHR); //0.7;スロットルの割合
}

//ヨーを目標値にして許容角度になるまで水平旋回
int Rotate(float targetAngle[3], float TargetYAW){
    float diffYaw = TranslateNewYaw(TargetYAW, nowAngle[YAW]);

    if(diffYaw > LIMIT_STRAIGHT_YAW){
        /*
        if(diffYaw > THRESHOLD_TURNINGRADIUS_YAW) UpdateTargetAngle_Rightloop_short(targetAngle);
        else UpdateTargetAngle_Rightloop(targetAngle);
        */
        UpdateTargetAngle_Rightloop_short(targetAngle);
        return 1;
    }else if(diffYaw < -LIMIT_STRAIGHT_YAW){
        UpdateTargetAngle_Leftloop_short(targetAngle);
        /*
        if(diffYaw < -THRESHOLD_TURNINGRADIUS_YAW) UpdateTargetAngle_Leftloop_short(targetAngle);
        else UpdateTargetAngle_Leftloop(targetAngle);
        */
        return 1;
    }else{
        UpdateTargetAngle_GoStraight(targetAngle);
        return 0;
    }
}

//チキラー投下
void Chicken_Drop(){
    if(CheckSW_Up(Ch7)){
        autopwm[DROP] = 1512;
        pc.printf("Bombed!\r\n");
        RerurnChickenServo1.attach(&ReturnChickenServo1, 3);
        //operation_mode = Approach;
        //buzzer = 0;
        pc.printf("Goto LeftLoop mode\r\n");
    }
}

void ReturnChickenServo1(){
    autopwm[DROP] = 1344;
    pc.printf("first reverse\r\n");
    RerurnChickenServo2.attach(&ReturnChickenServo2, 1);
}

void ReturnChickenServo2(){
    autopwm[DROP] = 1392;
    pc.printf("second reverse\r\n");
}

//着陸モード(PCからの指令に従う)
void UpdateTargetAngle_Approach(float targetAngle[3]){
    pc.putc(g_buf[0]);
    switch(g_buf[0]){
        case 'R':   //右旋回セヨ
            UpdateTargetAngle_Rightloop(targetAngle);
            break;
            
        case 'L':   //左旋回セヨ
            UpdateTargetAngle_Leftloop(targetAngle);
            break;
            
        case 'G':   //直進セヨ
            UpdateTargetAngle_GoStraight(targetAngle);
            break;
        
        case 'Y':   //指定ノヨー方向ニ移動セヨ
            Rotate(targetAngle, g_SerialTargetYAW);
            break;
        
        case 'B':   //ブザーヲ鳴ラセ
            //buzzer = 1;
            break;
            
        case 'D':   //物資ヲ落トセ
            Chicken_Drop();
            break;
                    
        case 'C':   //停止セヨ
            targetAngle[ROLL] = 0.0;
            targetAngle[PITCH] = -3.0;
            autopwm[THR] = minpwm[THR];
            break;
    }
}

void checkHeight(float targetAngle[3]){
    
    static int targetHeight = 200; 
    
    if(g_distance < targetHeight + ALLOWHEIGHT){
        UpdateTargetAngle_NoseUP(targetAngle);
        if(CheckSW_Up(Ch7)) led2 = 1;
    }
    else if(g_distance > targetHeight - ALLOWHEIGHT){
        UpdateTargetAngle_NoseDOWN(targetAngle);
        if(CheckSW_Up(Ch7)) led2 = 1;
    }
    else led2=0;
}

void UpdateTargetAngle_NoseUP(float targetAngle[3]){
    
    //targetAngle[PITCH] += 2.0f;
    //if(nowAngle[PITCH]<targetAngle[PITCH]) autopwm[THR] = SetTHRinRatio(0.6);
    autopwm[THR] = SetTHRinRatio(g_loopTHR+0.05);
    //pc.printf("nose UP");
}

void UpdateTargetAngle_NoseDOWN(float targetAngle[3]){
    
    //targetAngle[PITCH] -= 2.0f;
    autopwm[THR] = SetTHRinRatio(g_loopTHR-0.05);
    //pc.printf("nose DOWN");
}

//直進
void UpdateTargetAngle_GoStraight(float targetAngle[3]){

    targetAngle[ROLL] = g_gostraightROLL;
    targetAngle[PITCH] = g_gostraightPITCH;
    autopwm[THR] = SetTHRinRatio(g_loopTHR);
    
    //pc.printf("Roll = %f, PITCH = %f, THR = %d \r\n", targetAngle[ROLL], targetAngle[PITCH], autopwm[THR]);
}

//右旋回
void UpdateTargetAngle_Rightloop(float targetAngle[3]){ //右旋回

    targetAngle[ROLL] = g_rightloopROLL;
    targetAngle[PITCH] = g_rightloopPITCH ;
    autopwm[THR] = SetTHRinRatio(g_loopTHR);
    //checkHeight(targetAngle);
    //pc.printf("Roll = %f, PITCH = %f, THR = %d \r\n", targetAngle[ROLL], targetAngle[PITCH], autopwm[THR]);
}

void UpdateTargetAngle_Rightloop_short(float targetAngle[3]){ //右旋回

    targetAngle[ROLL] = g_rightloopROLLshort;
    targetAngle[PITCH] = g_rightloopPITCHshort;
    autopwm[THR] = SetTHRinRatio(g_loopTHR);
    
    
    //pc.printf("Roll = %f, PITCH = %f, THR = %d \r\n", targetAngle[ROLL], targetAngle[PITCH], autopwm[THR]);
}

//左旋回
void UpdateTargetAngle_Leftloop(float targetAngle[3]){
    
    targetAngle[ROLL] = g_leftloopROLL;
    targetAngle[PITCH] = g_leftloopPITCH;
    autopwm[THR] = SetTHRinRatio(g_loopTHR);
    //checkHeight(targetAngle);

    //printf("Roll = %f, PITCH = %f, THR = %d \r\n", targetAngle[ROLL], targetAngle[PITCH], autopwm[THR]);
}

void UpdateTargetAngle_Leftloop_short(float targetAngle[3]){
    
    targetAngle[ROLL] = g_leftloopROLLshort;
    targetAngle[PITCH] = g_leftloopPITCHshort;
    autopwm[THR] = SetTHRinRatio(g_loopTHR);
    
    //pc.printf("Roll = %f, PITCH = %f, THR = %d \r\n", targetAngle[ROLL], targetAngle[PITCH], autopwm[THR]);
}
void ISR_Serial_Rx()
{
    // シリアルの受信処理
    char data = pc.getc();
    
    if(data=='C'){
    autopwm[THR]=minpwm[2];
    wait(60.0);
    }
    
}

//デバッグ用
void DebugPrint(){    
    /*
    static int16_t deltaT = 0, t_start = 0;
    deltaT = t.read_u2s() - t_start;
    pc.printf("t:%d us, ",deltaT);
    pc.printf("\r\n");
    t_start = t.read_us();
    */
    //for(uint8_t i=0; i<8; i++) pc.printf("%d ",sbus.manualpwm[i]);
    //for(uint8_t i=1; i<4; i++) pc.printf("%d ",sbus.manualpwm[i]);
    //pc.printf("\r\n");
    for(uint8_t i=0; i<3; i++) pc.printf("%3.2f\t",nowAngle[i]);
    //for(uint8_t i=0; i<2; i++) pc.printf("%3.2f\t",nowAngle[i]); //ロール、ピッチのみ 小数点以下2ケタ
    //pc.printf("%d\t",autopwm[ELE]);  pc.printf("%d\t",autopwm[RUD]);
    //pc.printf("%d",g_distance);

    //pc.printf("Mode: %c: ",g_buf[0]);
    //if(g_buf[0] == 'Y') pc.printf(" %3.1f",g_SerialTargetYAW);
    pc.printf("\r\n");
}