a

Dependencies:   mbed SDFileSystem BMP180

main.cpp

Committer:
ShioHitomi
Date:
2021-11-19
Revision:
0:0624addc6841

File content as of revision 0:0624addc6841:

#include "mbed.h"
#include "math.h"
#include "BMP180.h"
#include "SDFileSystem.h"

#define  p0  1013.25f                                                           //海面気圧
#define  PI  3.1415
#define  Alt_num 3.0                                                            //高度を何回の平均値にするか
#define  Angle_num 3                                                            //姿勢角を何回の平均値にするか
#define  Angle_cnt 10                                                           //何回姿勢角取得するか
#define  Alt_bou   30                                                           //この高度より低かったらFlight mode入ったとみなす

#define  Z_0    0.962                                                           //KXTC9-2050_rawを使ってキャリブレーションする
#define  Z_90   1.62
#define  Z_180  2.24

enum PHASE{CHECK, STANDBY, FLIGHT, EXPANSION, MISSION, WITHDRAW} Phase;

Serial          pc(USBTX, USBRX, 115200);                                                
Serial          twe(p28, p27, 115200);
DigitalOut      myled_1(LED1);
DigitalOut      myled_2(LED2);
DigitalOut      myled_3(LED3);
DigitalOut      myled_4(LED4);
DigitalIn       Flight_IN(p20);
//SDFileSystem    sd(p5, p6, p7, p8, "sd");
BMP180          bmp(p9, p10);                                                   //(sda, scl)                                       
AnalogIn        z(p19);                                                         //加速度センサ
DigitalOut      load_sck(p13);                                                  //ロードセル 
DigitalIn       load_data(p14); 
DigitalOut      fet(p18);                                                       //ニクロム用MOSFET

PwmOut          servo(p24); 
PwmOut          motor1_1(p25);                                                  //motor1:回転用
PwmOut          motor1_2(p26);
DigitalOut      motor2_1(p22);                                                  //motor2:上昇下降用
DigitalOut      motor2_2(p23);
PwmOut          motor2_pwm(p21);

Timer           time_0;
Timer           time_flight;

int             _getTime();                                                     //time_0取得
float           _getAlt();                                                      //高度取得
float           _getAngle();                                                    //姿勢角取得
int             _averageLoad(uint8_t times);                                    //ロードセルのキャリブレーションする時に使う
int             _getLoad();                                                                 
float           _getGram();                                                     //質量取得
void            _Rand_judge();                                                  //着地判定
//void            _Angle_judge();

int             getTime;
float           getAlt, getAngle, getGram;;
float           Load_offset = 0;

FILE *fp;

int main(){
    
    /*タイマー*/
    time_0.start();
    
    /*SD
    fp = fopen("/sd/test.txt", "a");
    fprintf(fp, "Start.\r\n");
    fclose(fp);
    */
    
    /*BMP180*/
    bmp.Initialize(64,BMP180_OSS_ULTRA_LOW_POWER);
    
    /*ロードセル*/
    load_sck = 1;                                                               
    wait_us(100);
    load_sck = 0;
    Load_offset = _averageLoad(10);
    
    
    /*サーボ*/
    servo.period(0.020);   
    
    Phase = CHECK;
    
    switch(Phase){
        case CHECK: 
        
            pc.printf("Check mode.\r\n");
            twe.printf("Check mode.\r\n");
            twe.printf("Check mode.\r\n");
            
            /*
            fp = fopen("/sd/test.txt", "a");
            fprintf(fp, "Check mode.\r\n");
            fclose(fp);
            */
            
            /*センサ値取得*/
            for(int i=0; i<30; i++){
                        
                getTime = _getTime();
                getAlt = _getAlt();
                getAngle = _getAngle();
                getGram = _getGram();
                
                pc.printf("Time: %d Alt: %f Angle: %f Gram: %f\r\n", getTime, getAlt, getAngle, getGram);
                twe.printf("Time: %d Alt: %f Angle: %f Gram: %f\r\n", getTime, getAlt, getAngle, getGram);
                wait(1.0);
                
            }
            /*
            fp = fopen("/sd/test.txt", "a");
            fprintf(fp, "Time: %d\r\n Alt: %f\r\n Angle: %f\r\n Gram: %f\r\n", getTime, getAlt, getAngle, getGram);
            fclose(fp);
            */
            myled_1 = 1;
            Phase = STANDBY;
            //break;
                    
        case STANDBY:
        
            //pc.printf("Standby mode.\r\n");
            twe.printf("Standby mode.\r\n");
            twe.printf("Standby mode.\r\n");
            /*
            fp = fopen("/sd/test.txt", "a");
            fprintf(fp, "Standby mode.\r\n");
            fclose(fp);
            */
            /*放出判定*/
            int fly_cnt = 0;
            while(1) {
                int FlightPin = Flight_IN;
                getAlt = _getAlt();
                //if((FlightPin == 0) && (getAlt < Alt_bou)){
                if(FlightPin == 0){
                    time_flight.start();
                    break;           
                }else{
                    fly_cnt++;
                    getTime = _getTime();
                    getAlt = _getAlt();
                    getAngle = _getAngle();
                    if(fly_cnt == 100){                                          //100回に1回データ保存
                        fly_cnt = 0;
                        /*
                        fp = fopen("/sd/test.txt", "a");
                        fprintf(fp, "Time: %d Alt: %f Angle: %f\r\n", getTime, getAlt, getAngle);
                        fclose(fp);
                        */
                    }                      
                }    
            }
            
            myled_2 = 1;
            Phase = FLIGHT;
            
        case FLIGHT:
            
            //pc.printf("Flight mode.\r\n");
            twe.printf("Flight mode.\r\n");
            twe.printf("Flight mode.\r\n");
            /*
            fp = fopen("/sd/test.txt", "a");
            fprintf(fp, "Flight mode.\r\n");
            fclose(fp);
            */
            /*着地判定*/
            _Rand_judge();
            
            //pc.printf("Rand judge success!!\r\n");
            twe.printf("Rand judge success!!\r\n");
            twe.printf("Rand judge success!!\r\n");
            
            myled_3 = 1;
            Phase = EXPANSION;
            
        case EXPANSION:
            
            //pc.printf("Expansion mode.\r\n");
            twe.printf("Expansion mode.\r\n");
            twe.printf("Expansion mode.\r\n");
            /*
            fp = fopen("/sd/test.txt", "a");
            fprintf(fp, "Expansion mode.\r\n");
            fclose(fp);
            */
            wait(30);
            
            /*ニクロム線動作*/
            fet = 1;
            wait(0.3);
            fet = 0;
            wait(30.0);
            
            
            for(int i=0; i<30; i++){
                
                getAngle = _getAngle();
                
                //pc.printf("Angle: %f\r\n", getAngle);
                twe.printf("Angle: %f\r\n", getAngle);
                /*
                fp = fopen("/sd/test.txt", "a");                                //毎回角度保存してるけどどうしようかな
                fprintf(fp, "Angle: %f\r\n", getAngle);
                fclose(fp);
                */
                wait(1.0);
                
            }
            
            myled_4 = 1;
            Phase = MISSION;
            
        case MISSION:
            
            //pc.printf("Mission mode.\r\n");
            twe.printf("Mission mode.\r\n");
            twe.printf("Mission mode.\r\n");
            /*
            fp = fopen("/sd/test.txt", "a");
            fprintf(fp, "Mission mode.\r\n");
            fclose(fp);
            */
            
            load_sck = 1;                                                               
            wait_us(100);
            load_sck = 0;
            
            for(int i=0; i<10; i++){
                getGram += _getGram();
                wait(1.0);
            }
            float Gram_0 = 0.0;
            Gram_0 = getGram/10.0;
            
            //pc.printf("Gram_0: %f\r\n", Gram_0);
            twe.printf("Gram_0: %f\r\n", Gram_0);
            /*
            fp = fopen("/sd/test.txt", "a");
            fprintf(fp, "Gram_0: %f\r\n", Gram_0);
            fclose(fp);
            */
            /*ちょっとあげる*/
            motor2_pwm = 1.0; 
            motor2_1 = 1;                                                       
            motor2_2 = 0;
            wait(3.0);
            
            /*サーボ*/
            servo.pulsewidth(0.0015);                                               
            wait(1.0);
            servo.pulsewidth(0.0018);                                               
            wait(1.0);
            servo.pulsewidth(0.0020);                                               
            wait(1.0);
            servo.pulsewidth(0.0022);       
            wait(1.0);
            servo.pulsewidth(0.0023);
            wait(1.0);
            //servo.pulsewidth(0.0026);
            //wait(1.0);
            /*
            servo.pulsewidth(0.0030);
            */
            /*ドリル動作 motor1:回転、motor2:下降上昇*/
            motor2_pwm = 1.0;                                                   
            motor2_1 = 0;                                                       //下降・回転
            motor2_2 = 1;
            motor1_1 = 1.0;
            motor1_2 = 0.0;
            wait(9.0);
            motor2_1 = 0;                                                       //止まる・回転
            motor2_2 = 0;
            motor1_1 = 1.0;
            motor1_2 = 0.0;
            wait(2.0);
            motor1_1 = 0.0;                                                     //止まる・回転停止
            motor1_2 = 0.0;
            wait(3.0);
            motor2_1 = 1;                                                       //上昇・回転停止
            motor2_2 = 0;
            motor1_1 = 0.0;
            motor1_2 = 0.0;
            wait(15.0);
            motor2_1 = 0;                                                       //止まる・回転停止
            motor2_2 = 0;
            motor1_1 = 0.0;
            motor1_2 = 0.0;
            wait(2.0);
            
            /*サーボ動作*/
            servo.pulsewidth(0.0023);                                           
            wait(1.0);
            servo.pulsewidth(0.0022);                                               
            wait(1.0);
            servo.pulsewidth(0.0020);                                               
            wait(1.0);
            servo.pulsewidth(0.0018);                                               
            wait(1.0);
            servo.pulsewidth(0.0014);       
            wait(1.0);
            
            /*サンプルをドリルから取るための回転*/
            motor1_1 = 1.0;
            motor1_2 = 0.0;
            wait(10.0);
            motor1_1 = 0.0;
            motor1_2 = 0.0;
            
            
            /*質量値取得*/
            
            for(int i=0; i<30; i++){
                getGram = _getGram();
                //pc.printf("Gram: %f \r\n", getGram - Gram_0);
                twe.printf("Gram: %f \r\n", getGram - Gram_0);
                /*
                fp = fopen("/sd/test.txt", "a");                                    
                fprintf(fp, "Gram: %f\r\n", getGram - Gram_0);
                fclose(fp);
                */
                wait(1.0);
            }
            
            Phase = WITHDRAW;
        
        case WITHDRAW:
        
            //pc.printf("Withdraw mode.\r\n");
            twe.printf("Withdraw mode.\r\n");
            twe.printf("Withdraw mode.\r\n");
            /*
            fp = fopen("/sd/test.txt", "a");
            fprintf(fp, "Withdraw mode.\r\n");
            fclose(fp);
            */
        
            while(1){
                
                myled_1 = !myled_1;
                myled_2 = !myled_2;
                myled_3 = !myled_3;
                myled_4 = !myled_4;
                
                getTime = _getTime();
                //pc.printf("Time: %d\r\n", getTime);
                twe.printf("Time: %d\r\n", getTime);
                
                wait(1.0);
            
            }
    }
}


int _getTime(){                                                                 //Timer_0取得
    int time;
    time = time_0.read();
    return time;  
}


float _getAlt(){                                                                //高度取得
    float Tem, Pre, Alt, sum = 0;
    
    for(int i=0; i<Alt_num; i++){
        bmp.ReadData(&Tem, &Pre);
        Alt = (pow((p0/Pre), (1.0f/5.257f))-1.0f)*(Tem + 273.15f)/0.0065f;
        sum += Alt;
    }  
    return sum/Alt_num;
}

float _getAngle(){                                                      
    float Z, rad, angle, Angle_sum = 0;
    for(int i=0; i<Angle_num; i++){
        Z = 3.3*z.read();
        if(Z <= Z_0){
            angle = 0;
        }else if(Z > Z_0 && Z < Z_90){
            rad = asin((Z - Z_0)/(Z_90 - Z_0));
            angle = 180*rad/PI;
        }else if(Z >= Z_90 && Z < Z_180){
            rad = asin((Z - Z_90)/(Z_180 - Z_90));
            angle = 90+180*rad/PI;
        }else{
            angle = 180;
        }
        /*
        if(Z <= Z_180){
            angle = 180;
        }else if(Z > Z_180 && Z < Z_90){
            rad = asin((Z - Z_180)/(Z_90 - Z_180));
            angle = 180 - 180*rad/PI;
        }else if(Z >= Z_90 && Z < Z_0){
            rad = asin((Z - Z_90)/(Z_0 - Z_90));
            angle = 90 - 180*rad/PI;                                      
        }else{
            angle = 0;                                                      //全部-180した
        }
        */
        Angle_sum += angle;
    }
    return Angle_sum/Angle_num;
}

void _Rand_judge(){
    float Alt, Alt_old, Alt_new;
    float Alt_sum = 0;
    float Pre, Tem; 
    int rand_cnt = 0; 
    int flight_time;
    
    for(int i=0; i<Alt_num; i++){                                                     
        bmp.ReadData(&Tem, &Pre);
        Alt = (pow((p0/Pre), (1.0f/5.257f))-1.0f)*(Tem + 273.15f)/0.0065f;
        Alt_sum += Alt;
    }
    Alt_old = Alt_sum/Alt_num;                                                      
    Alt_sum = 0;  

    while(1) {
        for(int j=0; j<Alt_num; j++){
            bmp.ReadData(&Tem, &Pre);
            Alt = (pow((p0/Pre), (1.0f/5.257f))-1.0f)*(Tem + 273.15f)/0.0065f;
            Alt_sum += Alt;
        }
        Alt_new = Alt_sum/Alt_num;
        Alt_sum = 0;
        flight_time = time_flight.read();
        /*                                                                      
        fp = fopen("/sd/test.txt", "a");
        fprintf(fp, "flight_time: %d , Alt_new: %f, rand_cnt: %d\r\n", flight_time, Alt_new, rand_cnt);
        fclose(fp);
        */
        if(fabsf(Alt_new-Alt_old)<0.8){                                         //高度差が何m以内の時着地判定クリアとするか  
            rand_cnt++;
            Alt_old = Alt_new;
            wait(0.97);                                                         //1Hzになるように調整
            if(rand_cnt == 3){                                                  //3回連続 または 60秒
                break;
            }         
        }else if(flight_time >= 60){
            break;
            
        }else{
            rand_cnt = 0;
            Alt_old = Alt_new;
            wait(0.97);
        }
        //pc.printf("flightTime:%d s, Alt:%f m, cnt:%d \r\n", flight_time, Alt_old, rand_cnt);
        twe.printf("flightTime:%d s, Alt:%f m, cnt:%d \r\n", flight_time, Alt_old, rand_cnt);
    } 
}

int _averageLoad(uint8_t times){
    int sum = 0;
    for (int i = 0; i < times; i++){
        sum += _getLoad();
    }
    return sum / times;
}

int _getLoad(){
    int buffer; 
    buffer = 0 ;
    
    while (load_data.read()==1);
    
    for (uint8_t i = 24; i--;){
        load_sck=1;
        buffer = buffer << 1 ;
        if (load_data.read()){
            buffer ++;
        }
        load_sck=0;
    }
    
    for (int i = 0; i < 1; i++){
        load_sck=1; 
        load_sck=0;
    }
    
    buffer = buffer ^ 0x800000;
    return buffer;
}

float _getGram(){
    
    long val = (_averageLoad(2) - Load_offset);
    
    if(val < 0) val = 0;
    
    float scale = 0.0003*4.2987*128.0/100.0;                                    //定格出力:0.0006V,  定格容量:100g
    float volt;
    float gram;
    volt = val*(4.2987/16777216.0);
    gram = volt/scale;
    
    return (float) gram;
}