CanSat2018_4にGPSとtweliteをつけ足して関数化したもの
Dependencies: mbed
main.cpp
- Committer:
- ponpoko1939
- Date:
- 2018-08-13
- Revision:
- 2:b257a71f0655
- Parent:
- 1:342818b81499
File content as of revision 2:b257a71f0655:
/*MPU9250_PROGRAM ver2.1 PROGRAMED BY RYOTARO FUNAI 2018/08/10*/ #include <mbed.h> #include <math.h> #define PI 3.14159265359 DigitalOut motor1(p21); DigitalOut motor2(p22); DigitalOut motor3(p23); DigitalOut motor4(p24); I2C i2c(p9, p10); Serial pc(USBTX, USBRX); //TWELITE使う予定なら13,14ピン Serial gps(p28,p27); // tx, rx Serial twelite(p13,p14); //twelite.printfでtwilite経由で通信できる DigitalOut led1(p12); AnalogIn Lx_in(p15); //GPS用変数群 int i,rlock,mode; char gps_data[256]; char ns,ew; float x=135.585800, y=34.648525; //実験用初期位地 float w_time,hokui,tokei; float g_hokui,g_tokei,old_hokui, old_tokei; //oldとg_を比べることで距離と角度を出す float d_hokui,m_hokui,d_tokei,m_tokei; unsigned char c; #define MPU9250_ADDRESS 0x68<<1 //I2CでのMPU9250のスレーブアドレス #define AK8963_ADDRESS 0x0c<<1 //磁気センサのスレーブアドレス #define Whoami 0x75 //who_am_iレジスタのアドレス、0x71が返ってくる #define PWR 0x6b //スリープモードをonにするためのアドレス #define MAG_OPN 0x37 //mpu9250から磁気センサにアクセスできるようにする #define ACC_CONFIG 0x1c //加速度センサ設定用のアドレス #define ACC_2G 0x00 //加速度センサのレンジ(2G) #define ACC_4G 0x08 //加速度センサのレンジ(4G) #define ACC_8G 0x10 //加速度センサのレンジ(8G) #define ACC_16G 0x18 //加速度センサのレンジ(16Gまで計測可能) #define MAG_CONFIG 0x0a //磁気センサ設定用のアドレス #define MAG_8HZ 0x12 //磁気センサの出力周期(8Hz) #define MAG_100HZ 0x16 //磁気センサの出力周期(100Hz) #define accRange 16.0 //加速度センサの測定レンジ #define ST2 0x02 //磁気センサのステータスが入っているアドレス #define Ain 35 #define SDA 21 #define SCL 22 #define led 2 //チェック用のLEDピン //void LCD_Reset(); //m5stackLCDを更新 float Lx_Read(); //cdsセルから値を取得 void Ac_Read(int16_t*, int16_t*, int16_t*); //9軸から加速度の値を取得 void Mag_Read(int16_t*, int16_t*, int16_t*); //addrにスレーブアドレス、regにアクセスするアドレスを入力する void i2cRead(uint8_t addr,uint8_t reg, uint8_t bytes,uint8_t* data); void i2cWrite(uint8_t addr,uint8_t reg, uint8_t data); uint8_t IDcheck(); void Breky(); void Turn(); void Return(); void Right(); void Left(); void release(); void Faling(); void nikurom(); void getGPS(); void distance(); void geoDirection(); void compass(); uint8_t accgyrodata[14]; uint8_t magneticdata[7]; uint8_t ST2_Bit; //磁気センサのステータスを入れておく int main() { gps.baud(9600); twelite.baud(115200); void Release(); //放出判定 gps.attach(getGPS,Serial::RxIrq); //GPS割り込み void Faling();//落下判定 void nikurom(); //ニクロム線を切る void compass();//九軸で進む方向決める } /****************関数群****************/ //cdsセルからアナログ値を持ってくる float Lx_Read(){ float lx; lx = Lx_in.read(); return lx; } //Who_am_Iアドレスで接続確認ができる。0x71もしくは10進数で113が返ってくればok uint8_t IDcheck(){ uint8_t address; i2cRead(MPU9250_ADDRESS, Whoami, 1, &address); return address; } //mpu9250から加速度センサのみ引っ張ってくる void Ac_Read(int16_t* ax, int16_t* ay, int16_t* az){ i2cWrite(MPU9250_ADDRESS, PWR, 0x00); //スリープモードの解除 i2cWrite(MPU9250_ADDRESS, ACC_CONFIG, ACC_16G);//加速度センサの測定レンジの設定 i2cRead(MPU9250_ADDRESS, 0x3b, 14, accgyrodata); *ax = (accgyrodata[0] << 8) | accgyrodata[1];//accGyroTempData[0]を左に8シフトし(<<),accGyroTempData[1]を足し合わせる(|) |は論理和 *ay = (accgyrodata[2] << 8) | accgyrodata[3];//accGyroTempData[2]を左に8シフトし(<<),accGyroTempData[3]を足し合わせる(|) *az = (accgyrodata[4] << 8) | accgyrodata[5];//accGyroTempData[4]を左に8シフトし(<<),accGyroTempData[5]を足し合わせる(|) } //mpu9250から磁気センサのみ引っ張ってくる void Mag_Read(int16_t* mx, int16_t* my, int16_t* mz){ i2cWrite(MPU9250_ADDRESS, PWR, 0x00); //スリープモードの解除 i2cWrite(MPU9250_ADDRESS, MAG_OPN, 0x02); //磁気センサの起動 i2cWrite(AK8963_ADDRESS, MAG_CONFIG, MAG_100HZ);//磁気センサの測定レンジの設定 i2cRead(AK8963_ADDRESS, ST2, 1, &ST2_Bit);//読み出し準備ができたか確認 if(ST2_Bit & 0x01){ //ちゃんと読めたかをST2レジスタの値を読んで確認 i2cRead(AK8963_ADDRESS, 0x03, 7, magneticdata); } else pc.printf("ERROR!!\n"); *mx = (magneticdata[0] << 8) | magneticdata[1]; *my = (magneticdata[2] << 8) | magneticdata[3]; *mz = (magneticdata[4] << 8) | magneticdata[5]; } //mpu9250からデータを取得(bytesに受け取るデータのバイト数、dataに実際のデータを挿入していく) void i2cRead(uint8_t addr,uint8_t reg, uint8_t bytes,uint8_t* data){ char cmd[1]; char written_data[14]; cmd[0] = reg; i2c.write(addr, cmd, 1, 1); i2c.read(addr, written_data, bytes, 0); for(int ii = 0; ii < bytes; ii++) { data[ii] = written_data[ii]; } } //mpu9250にデータを送信(dataに送信するデータを入力する) void i2cWrite(uint8_t addr,uint8_t reg, uint8_t data){ char cmd[2]; cmd[0] = reg; //レジスタ指定 cmd[1] = data; //送信するデータ i2c.write(addr, cmd, 2); //レジスタ指定はどうする? } //各種モータの関数 void Breky(){ motor1 = 0; motor2 = 0; motor3 = 0; motor4 = 0; } void Turn(){ motor1 = 1; motor2 = 0; motor3 = 1; motor4 = 0; } void Return(){ motor1 = 0; motor2 = 1; motor3 = 0; motor4 = 1; } void Left(){ motor1 = 1; motor2 = 0; motor3 = 0; motor4 = 1; } void Right(){ motor1 = 0; motor2 = 1; motor3 = 1; motor4 = 0; } void release(){ while(1){ //cdsセルの値の確認 //暗いときは0.8~1.0程度の値 float blight; blight = Lx_Read(); pc.printf("%4.1f\n\r",blight); if(blight<=0.6) break;// 明るさが0.6以下なら次のフェーズに進む } } void Faling(){ while(1){ int16_t ax, ay, az; float accX, accY, accZ, acc; //加速度の値を取得し、落下判定 Ac_Read(&ax,&ay,&az); accX = ax * accRange / 32768.0;//[G]に変換 accY = ay * accRange / 32768.0;//[G]に変換 accZ = az * accRange / 32768.0;//[G]に変換 acc = sqrt((accX * accX) + (accY * accY) + (accZ * accZ)); // 各軸のGを表示 pc.printf("accX :%f\n\raccY :%f\n\raccZ :%f\n\racc :%f\n\r",accX, accY, accZ, acc); //静止時は1.0程度、落下時はそれを超える為、電源を入れるのは1.1以下にした if(acc <= 1.10){ pc.printf("PWRON!!"); Turn(); break; //led1 = 0; }else{ Breky(); //led1 = 0; } } } void nikurom(){ wait(60); } void getGPS() { c = gps.getc(); if( c=='$' || i == 256){ mode = 0; i = 0; for(int j=0; j<256; j++){ gps_data[j]=NULL; } } if(mode==0){ if((gps_data[i]=c) != '\r'){ i++; }else{ gps_data[i]='\0'; if( sscanf(gps_data, "$GPGGA,%f,%f,%c,%f,%c,%d",&w_time,&hokui,&ns,&tokei,&ew,&rlock) >= 1){ if(rlock==1){ // pc.printf("Status:Lock(%d)\n\r",rlock); //logitude d_tokei= int(tokei/100); m_tokei= (tokei-d_tokei*100)/60; g_tokei= d_tokei+m_tokei; //Latitude d_hokui=int(hokui/100); m_hokui=(hokui-d_hokui*100)/60; g_hokui=d_hokui+m_hokui; //現在地のgpsデータ pc.printf("Lat:%.6f, Lon:%.6f\n\r",g_hokui, g_tokei); twelite.printf("%.6f,%.6f\n\r",g_hokui, g_tokei); //前回の計測からの変化量 //pc.printf("ch_Lat:%.6f, ch_Lon:%.6f\n\r",old_hokui-g_hokui, old_tokei-g_tokei); //pc.printf("dis : %fm\n\r", 1000*6378.137*acos(sin(y*PI/180)*sin(g_hokui*PI/180)+cos(y*PI/180)*cos(g_hokui*PI/180)*cos(x*PI/180-g_tokei*PI/180))); //別の距離の出し方 distance(); geoDirection(); old_hokui=g_hokui; old_tokei=g_tokei; }else{//gpsデータ未受信時 //pc.printf("\n\rStatus:unLock(%d)\n\r",rlock); ////pc.printf("%s",gps_data); } } } } __disable_irq(); //割り込み禁止 } //ヒューベニの公式で距離出す void distance(){ float rlat1 = y*PI/180, rlon1 = x*PI/180; float rlat2 = g_hokui*PI/180, rlon2 = g_tokei*PI/180; float a=6378137.000, a2=pow(a,2), e=sqrt((a2-pow(6356752.314,2))/a2); float lat_diff = rlat1-rlat2; float lon_diff = rlon1-rlon2; float lat_ave = (rlat1+rlat2)/2; float w = sqrt(1-pow(e,2)*pow(sin(lat_ave),2)); float meridian = a*(1-pow(e,2))/pow(w,3); float n=a/w; float distance2 = sqrt(pow(lat_diff*meridian,2)+pow(lon_diff*n*cos(lat_ave),2)); //pc.printf("dis2 : %fm\n\r",distance2); } //角度出す void geoDirection() { // 緯度 g_hokui(lat1),経度 g_tokei(lng1) の点を出発として、緯度 y(lat2),経度 x(lng2) への方位 // 北を0度で右回りの角度0~360度 float Y = cos(x*PI/180)*sin(y*PI/180-g_hokui*PI/180); float X = cos(g_tokei*PI/180)*sin(x*PI/180)-sin(g_tokei*PI/180)*cos(x*PI/180)*cos(y*PI/180-g_hokui*PI/180); float dirE0 = 180*atan2(Y, X)/PI; if(dirE0 < 0){ dirE0 = dirE0 + 360; } float dirN0 = (int)(dirE0 + 90) % 360; pc.printf("%f\n\r",dirN0); } //方角だす void compass(){ double maveX = 0, maveY = 0, maveZ = 0; int16_t ax, ay, az; float accX, accY, accZ, acc; int16_t mx, my, mz; float magX, magY, magZ, mag; double rad; double degree; double roll; double pitch; //補正する為に取得 accX = ax * accRange / 32768.0;//[G]に変換 accY = ay * accRange / 32768.0;//[G]に変換 accZ = az * accRange / 32768.0;//[G]に変換 roll = atan2(accY, accZ); pitch = atan2(-accX, sin(accY) + cos(accZ)); //磁気の値を取得し、方位判定 for(int i = 0;i < 150;i++){ Mag_Read(&mx, &my, &mz); maveX += mx; maveY += my; maveZ += mz; wait_ms(10); } maveX /= 150; maveY /= 150; maveZ /= 150; magX = (maveX - 168.75) / 32768.0f * 4800.0f;//[uT]に変換 magY = (maveY - 18.75) / 32768.0f * 4800.0f;//[uT]に変換 magZ = mz / 32768.0f * 4800.0f;//[uT]に変換 pc.printf("%f,%f\n\r", magX, magY); //ID = IDcheck(); //pc.printf("%f\n\r", ID); rad = atan2(magZ * sin(roll) - magY * cos(roll), magX * cos(pitch) + magY * sin(pitch) * sin(roll) + magZ * sin(pitch) * cos(roll)); degree = -((int)(rad * 180.0 / 3.141592 + 270.0 - 7.5) % 360 - 360.0); /* if(degree < 0){ degree += 360; } */ pc.printf("%d\n\r",(int)degree); __enable_irq(); //割り込み許可 }