能代宇宙イベント2020,ロケット用プログラム Nucleo-F303K8 ,MPU9250,BME280

Dependencies:   mbed SDFileSystem BME280 MPU9250

main.cpp

Committer:
Zero0000
Date:
2020-10-29
Revision:
0:aa715ea672cb

File content as of revision 0:aa715ea672cb:

#include "mbed.h"
#include "math.h"
#include "MPU9250.h"
#include "BME280.h"
#include "SDFileSystem.h"
#define NUM_CNT_MEDIAN      10  //中央値をとる個数
#define CNT_LAUNCH_TIMES 5//発射判定に必要な連続数
#define TIME_SEND           1.0 //無線送信する間隔
#define CNT_LAUNCH          5  //発射判定するときのしきい値(TBD)
#define ACC_JUDGE_LAUNCH    3.0 //発射判定の合成加速度のしきい値
#define TIME_BURNING        6   //燃焼時間(TBD)
#define ALT_JUDGE_OPEN      5   //落下判定のカウントを1増やす高度差
#define CNT_JUDGE           10  //頂点判定する時に落下のカウント数
#define p0 1013.25f //海面気圧
#define N 5
#define sampleFreq 100.0f
#define beta 0.33f // gain(大きいと加速度による補正が早い)
#define PI 3.14159265358979323846f

MPU9250 mpu = MPU9250(PB_7,PB_6);// pin30,29 SDA,SCL
Serial gps(PB_4,PB_3, 9600);//pin19,20 tx,rx
DigitalOut key(PA_8);//pin22
Serial pc(PA_10,PA_9, 115200);//pin8,9 TX,RX
BME280 bme = BME280(PB_7, PB_6);//pin30,29 SDA,SCL
SDFileSystem sd(PA_7, PA_6, PA_5, PA_4, "sd");
Timer timer_standby;
Timer timer_flight;
Timer timer_burning;
FILE *fp;
FILE *al;
FILE *ac;
//関数
float _getAlt();
float _median(float data[],int num);
void  _SendGPS();
float _DMS2DEG(float raw_data);
void _calcurateAcc();


void mpu_init(){
    uint8_t whoami_MPU9250, whoami_AK8963;
    float mag_init[3];
    
    whoami_MPU9250 = mpu.readByte(MPU9250_ADDRESS, WHO_AM_I_MPU9250);
    whoami_AK8963 = mpu.readByte(AK8963_ADDRESS, WHO_AM_I_AK8963);
    pc.printf("MPU9250 IS 0x%x\n\r", whoami_MPU9250); // 0x71で正常
    pc.printf("AK8963 IS 0x%x\n\r", whoami_AK8963); // 0x48で正常
    
    if (whoami_MPU9250 == 0x71 || whoami_AK8963 == 0x48){  
        pc.printf("MPU9250 is detected.\n\r");
        wait(0.1);
        mpu.resetMPU9250();
        mpu.initMPU9250();
        wait(0.1);
        mpu.initAK8963(mag_init);
        mpu.getGres();
        mpu.getAres();
        mpu.getMres();
        wait(0.1);
    }
   else{
        pc.printf("Could not detect MPU9250.\n\r");
        pc.printf("whoami_MPU9250 = 0x%x\n\rwhoami_AK8963 = 0x%x\r\n",
                  whoami_MPU9250, whoami_AK8963);
        while(1);
    }
}

enum PHASE{Standby=0,Flight=1,Burning=3,Parachute=7} Phase;
float alt_gnd;
float alt_max;
char c[516];
int i = 0;
int cnt_gps=0;
int timeout;
int cnt_data;
int cnt_judge=0;
int16_t acc[3];
    
float buff_ax[N], buff_ay[N], buff_az[N];
float sum_ax = 0.0f, sum_ay = 0.0f, sum_az = 0.0f;
float ax_new = 0.0f, ay_new = 0.0f, az_new = 0.0f;
float ax = 0.0f, ay = 0.0f, az = 0.0f;
int cnt = 0;
float acc_abs;
float alt_buff[10],alt_md;

int main(){
    
    wait(0.1);
    mpu_init();
    bme.initialize();//BME初期化
    mkdir("/sd/mydir",0777);//SDファイル作成
    fp = fopen("/sd/mydir/gps.txt", "a");//最初のSDopen時間かかるのでwhile外デ
    al = fopen("/sd/mydir/altitude.txt", "a");
    ac = fopen("/sd/mydir/acc.txt", "a");
    if(fp == NULL) {
       error("Could not open file for write\n");
       }

    wait(0.1);

    
    switch(Phase){
             case Standby: //待機モード
                pc.printf("Standby\n\r");
                key = 0;
                if(pc.readable()){
                    c[0]=pc.getc();
                }

                if(c[0] == 'f'){
                pc.printf("Flight\r\n");
                Phase = Flight;
                timer_standby.stop();
                timer_flight.start();
                }
                
                break;
                
            case Flight:
                     key = 0;
                while(1){
                     mpu.readAccelData(acc);
                     _calcurateAcc();
                     acc_abs = sqrt(pow(ax/9.81f,2)+pow(ay/9.81f,2)+pow(az/9.81f,2));//合成加速度
                     fp = fopen("/sd/mydir/gps.txt", "a");
                     _SendGPS();
                     fclose(fp);
                     timeout = timer_flight.read();
                     ac = fopen("/sd/mydir/acc.txt","a");
                     fprintf(ac,"%f\t%f\t%f\t%f\t%f\r\n",timeout,ax,ay,az,acc_abs);
                     fclose(ac);
                     pc.printf("%f\t%f\t%f\t%f\t%f\r\n",timeout,ax,ay,az,acc_abs);
                    /*加速度判定*/
                    if(acc_abs>ACC_JUDGE_LAUNCH){
                        cnt_judge++;
                     }
                    if(cnt_judge==CNT_LAUNCH){
                        cnt_judge=0;
                        timer_burning.start();
                        Phase = Burning;
                        timer_flight.stop();
                    }
                  }
                  break;
            case Burning:
                key = 0;
                while(timer_flight.read() < TIME_BURNING){
                    mpu.readAccelData(acc);
                     _calcurateAcc();
                    pc.printf("Burning\n\r");
                    fp = fopen("/sd/mydir/gps.txt", "a");
                    _SendGPS();
                     fclose(fp);
                     timeout = timer_flight.read();
                     ac = fopen("/sd/mydir/acc.txt","a");
                     fprintf(ac,"%f\t%f\t%f\t%f\t%f\r\n",timeout,ax,ay,az,acc_abs);
                     fclose(ac);
                     pc.printf("%f\t%f\t%f\t%f\t%f\r\n",timeout,ax,ay,az,acc_abs);
                    
                }
                Phase = Parachute;
                pc.printf("Parachute\n\r");
                break;
           
               
            case Parachute:
                while(1){
                    mpu.readAccelData(acc);
                     _calcurateAcc();
                    fp = fopen("/sd/mydir/gps.txt", "a");
                    _SendGPS();
                     fclose(fp);
                     timeout = timer_flight.read();
                     ac = fopen("/sd/mydir/acc.txt","a");
                     fprintf(ac,"%f\t%f\t%f\t%f\t%f\r\n",timeout,ax,ay,az,acc_abs);
                     fclose(ac);
                     pc.printf("%f\t%f\t%f\t%f\t%f\r\n",timeout,ax,ay,az,acc_abs);
                    
                    for(cnt_data=0;cnt_data<NUM_CNT_MEDIAN;cnt_data++){
                        alt_buff[cnt_data] = _getAlt();
                    }
                    alt_md = _median(alt_buff,NUM_CNT_MEDIAN);
                    alt_md = alt_md - alt_gnd;
                
                    if(alt_md > alt_max){
                    alt_max = alt_md;
                    cnt_judge = 0;
                }
                else if((alt_max-alt_md) > ALT_JUDGE_OPEN){
                    cnt_judge++;
                }
                //if((timer_open.read()-time_judge) - TIME_JUDGE_CNT > 0) cnt_judge=0;
                 if(cnt_judge == CNT_JUDGE){
                    key = 1;
                    pc.printf("Open\n\r");
                }
                break;
                
             }
           }    
    }
         
    



float _getAlt(){
    float altitude,pressure,temperature;
    temperature = bme.getTemperature();
    pressure =  bme.getPressure();
    altitude = (pow((p0/pressure), (1.0f/5.257f))-1.0f)*(temperature+273.15f)/0.0065f;
    return altitude;
}

float _DMS2DEG(float raw_data){
    int d=(int)(raw_data/100);
    float m=(raw_data-(float)d*100);
    return (float)d+m/60;
}
float _median(float data[], int num){
    float *data_cpy, ans;
    data_cpy = new float[num];
    memcpy(data_cpy,data,sizeof(float)*num);
    for(i=0; i<num; i++){
        for(int j=0; j<num-i-1; j++){
            if(data_cpy[j]>data_cpy[j+1]){
                float buff = data_cpy[j+1];
                data_cpy[j+1] = data_cpy[j];
                data_cpy[j] = buff;
            }
        }
    }
    
    if(num%2!=0) ans = data_cpy[num/2];
    else         ans = (data_cpy[num/2-1]+data_cpy[num/2])/2.0;
    delete[] data_cpy;
    return ans;
}


void _SendGPS(){
    char gps_data[256];
    while(1){
        if(gps.readable()){
            gps_data[cnt_gps] = gps.getc();
            if(gps_data[cnt_gps] == '$' || cnt_gps ==256){
                cnt_gps = 0;
                memset(gps_data,'\0',256);
            }else if(gps_data[cnt_gps] == '\r'){
                float world_time, lon_east, lat_north;
                int rlock, sat_num;
                char lat,lon;
                if(sscanf(gps_data,"GPGGA,%f,%f,%c,%f,%c,%d,%d",&world_time,&lat_north,&lat,&lon_east,&lon,&rlock,&sat_num)>=1){
                    if(rlock==1){
                        lat_north = _DMS2DEG(lat_north);
                        lon_east = _DMS2DEG(lon_east);
                        pc.printf("%s\r\n",gps_data);
                        pc.printf("Lat:%f,Lon:%f\r\ntime:%f,sat_num:%d\r\n",lat_north,lon_east,world_time,sat_num);
                        pc.printf("Lat:%f,Lon:%f,MAX_ALT:%f\r\n",lat_north,lon_east,alt_max);
                        for(i=0;i<2;i++){
                            c[i]=pc.getc();
                        }
                        break;
                    }else{
                        //pc.printf("%s\r\n",gps_data);
                        pc.printf("NoGPSSignal\r\n");
                        break;
                    }
                }else{
                    //pc.printf("No_Satellite_signal\r\n");
                }
            }else{
                cnt_gps++;
            }
        }
    }
}

void _calcurateAcc(){
    /* 5回移動平均 */
        sum_ax = sum_ax - buff_ax[cnt];
        sum_ay = sum_ay - buff_ay[cnt];
        sum_az = sum_az - buff_az[cnt];

        ax_new = acc[0] / 2049.81;
        ay_new = acc[1] / 2049.81;
        az_new = acc[2] / 2049.81;

        buff_ax[cnt] = ax_new;
        buff_ay[cnt] = ay_new;
        buff_az[cnt] = az_new;

        sum_ax = sum_ax + buff_ax[cnt];
        sum_ay = sum_ay + buff_ay[cnt];
        sum_az = sum_az + buff_az[cnt];

        cnt++;
        if(cnt == N) cnt = 0;
        
        ax = sum_ax / N;
        ay = sum_ay / N;
        az = sum_az / N;
    }