2016年度伊豆大島共同打ち上げ実験で使用したプログラム
Dependencies: Battery_monitoring ExternalTrigger GPS_interrupt LPS25H_ver2 MadgwickFilter Nicrom Quaternion SDFileSystem Servo XbeeApiLib mbed mpu9250_i2c
Hybrid_main_FirstEdtion.cpp@0:3e847864d796, 2017-07-17 (annotated)
- Committer:
- Gaku0606
- Date:
- Mon Jul 17 10:09:15 2017 +0000
- Revision:
- 0:3e847864d796
www
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Gaku0606 | 0:3e847864d796 | 1 | #include "mbed.h" |
Gaku0606 | 0:3e847864d796 | 2 | #include "SDFileSystem.h" |
Gaku0606 | 0:3e847864d796 | 3 | #include "Quaternion.hpp" |
Gaku0606 | 0:3e847864d796 | 4 | #include "MadgwickFilter.hpp" |
Gaku0606 | 0:3e847864d796 | 5 | #include "mpu9250_i2c.h" |
Gaku0606 | 0:3e847864d796 | 6 | #include "GPS_interrupt.h" |
Gaku0606 | 0:3e847864d796 | 7 | #include "ExternalTrigger.hpp" |
Gaku0606 | 0:3e847864d796 | 8 | #include "nicrom.hpp" |
Gaku0606 | 0:3e847864d796 | 9 | #include "battery_monitoring.hpp" |
Gaku0606 | 0:3e847864d796 | 10 | #include "XbeeApiLib.h" // XbeeApiLib のインクルード |
Gaku0606 | 0:3e847864d796 | 11 | #include "Servo.h" |
Gaku0606 | 0:3e847864d796 | 12 | #include <string> |
Gaku0606 | 0:3e847864d796 | 13 | //------------------------------------------------------------------------------ |
Gaku0606 | 0:3e847864d796 | 14 | // なんかこう計算を速くしたり,よく使うもの |
Gaku0606 | 0:3e847864d796 | 15 | //------------------------------------------------------------------------------ |
Gaku0606 | 0:3e847864d796 | 16 | const double PI = 3.1415926535897932384626433832795;//4.0*atan(1.0); |
Gaku0606 | 0:3e847864d796 | 17 | const double DEG_TO_RAD = 0.01745329251994329576923690768489;//PI / 180.0; |
Gaku0606 | 0:3e847864d796 | 18 | const double RAD_TO_DEG = 57.295779513082320876798154814105;//180.0 / PI; |
Gaku0606 | 0:3e847864d796 | 19 | const double ACC_LPF_COEF = 0.95; |
Gaku0606 | 0:3e847864d796 | 20 | const double GYRO_LPF_COEF = 0.5f; |
Gaku0606 | 0:3e847864d796 | 21 | const double MAG_LPF_COEF = 0.95; |
Gaku0606 | 0:3e847864d796 | 22 | #define EARTH_EQUATOR_RADIUS 6378136.6//地球の赤道半径[m] |
Gaku0606 | 0:3e847864d796 | 23 | #define EARTH_POLAR_RADIUS 6356751.9//地球の極半径[m] |
Gaku0606 | 0:3e847864d796 | 24 | static int phaseNumber = 0; |
Gaku0606 | 0:3e847864d796 | 25 | static unsigned long system_count = 0; |
Gaku0606 | 0:3e847864d796 | 26 | FILE *fp; |
Gaku0606 | 0:3e847864d796 | 27 | char datafile[64] = "datafile0.txt"; |
Gaku0606 | 0:3e847864d796 | 28 | //#include <new> |
Gaku0606 | 0:3e847864d796 | 29 | |
Gaku0606 | 0:3e847864d796 | 30 | DigitalOut sdWriteLed(LED3); |
Gaku0606 | 0:3e847864d796 | 31 | /* |
Gaku0606 | 0:3e847864d796 | 32 | void no_memory () { |
Gaku0606 | 0:3e847864d796 | 33 | printf("panic: can't allocate to memory!\r\n"); |
Gaku0606 | 0:3e847864d796 | 34 | exit(-1); |
Gaku0606 | 0:3e847864d796 | 35 | } |
Gaku0606 | 0:3e847864d796 | 36 | // |
Gaku0606 | 0:3e847864d796 | 37 | extern "C" void HardFault_Handler() { |
Gaku0606 | 0:3e847864d796 | 38 | printf("Hard Fault!\n"); |
Gaku0606 | 0:3e847864d796 | 39 | while(1); |
Gaku0606 | 0:3e847864d796 | 40 | }*/ |
Gaku0606 | 0:3e847864d796 | 41 | //------------------------------------------------------------------------------ |
Gaku0606 | 0:3e847864d796 | 42 | // すぐに変更できたらいいもの |
Gaku0606 | 0:3e847864d796 | 43 | //------------------------------------------------------------------------------ |
Gaku0606 | 0:3e847864d796 | 44 | #define SET_ACC_LPF NO_USE |
Gaku0606 | 0:3e847864d796 | 45 | #define SET_GYRO _1000DPS |
Gaku0606 | 0:3e847864d796 | 46 | #define SET_ACC _16G |
Gaku0606 | 0:3e847864d796 | 47 | const double nine_offset[9] = {0.32766334f, 3.067240359f, -0.326759467f, |
Gaku0606 | 0:3e847864d796 | 48 | 0.0052546f, -0.009152758f, 0.142725298f, |
Gaku0606 | 0:3e847864d796 | 49 | 10.875, -24, 41.55f}; |
Gaku0606 | 0:3e847864d796 | 50 | //------------------------------------------------------------------------------ |
Gaku0606 | 0:3e847864d796 | 51 | // 諸々のパラメータ |
Gaku0606 | 0:3e847864d796 | 52 | //------------------------------------------------------------------------------ |
Gaku0606 | 0:3e847864d796 | 53 | #define SECOND_SEPA_DELAY_TIME 5.0f//[s] 気圧で1段目分離機構を作動させてから2段目を起動させるまでの時間 |
Gaku0606 | 0:3e847864d796 | 54 | #define MAIN_PARA_WAIT_TIME 15.0f//フライトピンが抜けてから分離するまでの時間[s] |
Gaku0606 | 0:3e847864d796 | 55 | #define DROGUE_WAIT_TIME 10.0f |
Gaku0606 | 0:3e847864d796 | 56 | #define FALLING_THRESHOLD -0.04//hPa 落下しているとみなせる気圧差 |
Gaku0606 | 0:3e847864d796 | 57 | const float SAFETY_TIME = 6.0f;//フライトピンが抜けてから分離しない時間 |
Gaku0606 | 0:3e847864d796 | 58 | |
Gaku0606 | 0:3e847864d796 | 59 | const int FALLING_COUNT = 100;//この回数,気圧が連続で上昇したら落下とする |
Gaku0606 | 0:3e847864d796 | 60 | |
Gaku0606 | 0:3e847864d796 | 61 | //------------------------------------------------------------------------------ |
Gaku0606 | 0:3e847864d796 | 62 | // ダウンリンク系のインスタンス生成 |
Gaku0606 | 0:3e847864d796 | 63 | //------------------------------------------------------------------------------ |
Gaku0606 | 0:3e847864d796 | 64 | Serial pc(USBTX,USBRX, 115200); |
Gaku0606 | 0:3e847864d796 | 65 | void downLink(); |
Gaku0606 | 0:3e847864d796 | 66 | //------------------------------------------------------------------------------ |
Gaku0606 | 0:3e847864d796 | 67 | // 内部時間タイマー |
Gaku0606 | 0:3e847864d796 | 68 | //------------------------------------------------------------------------------ |
Gaku0606 | 0:3e847864d796 | 69 | Timer innerTime; |
Gaku0606 | 0:3e847864d796 | 70 | |
Gaku0606 | 0:3e847864d796 | 71 | //------------------------------------------------------------------------------ |
Gaku0606 | 0:3e847864d796 | 72 | // 9軸センサー |
Gaku0606 | 0:3e847864d796 | 73 | //------------------------------------------------------------------------------ |
Gaku0606 | 0:3e847864d796 | 74 | #define NINE_SDA p9 |
Gaku0606 | 0:3e847864d796 | 75 | #define NINE_SCL p10 |
Gaku0606 | 0:3e847864d796 | 76 | |
Gaku0606 | 0:3e847864d796 | 77 | I2C i2cBus(NINE_SDA, NINE_SCL); |
Gaku0606 | 0:3e847864d796 | 78 | mpu9250 nine(i2cBus, AD0_HIGH); |
Gaku0606 | 0:3e847864d796 | 79 | |
Gaku0606 | 0:3e847864d796 | 80 | //------------------------------------------------------------------------------ |
Gaku0606 | 0:3e847864d796 | 81 | // サーボモーター ドラッグシュート放出用分離機構 |
Gaku0606 | 0:3e847864d796 | 82 | //------------------------------------------------------------------------------ |
Gaku0606 | 0:3e847864d796 | 83 | int fastPressureFlag = 0;//気圧による分離命令がタイマーより先だったとき 1 になる. |
Gaku0606 | 0:3e847864d796 | 84 | #define MAX_PULSE 0.00245//[s] |
Gaku0606 | 0:3e847864d796 | 85 | #define MIN_PULSE 0.00065//[s] |
Gaku0606 | 0:3e847864d796 | 86 | #define SERVO_PIN p26 |
Gaku0606 | 0:3e847864d796 | 87 | #define SERVO_PIN2 p25 |
Gaku0606 | 0:3e847864d796 | 88 | Servo servo(SERVO_PIN, MAX_PULSE, MIN_PULSE); |
Gaku0606 | 0:3e847864d796 | 89 | Servo servo2(SERVO_PIN2, MAX_PULSE, MIN_PULSE); |
Gaku0606 | 0:3e847864d796 | 90 | volatile int drogueSepaFlag = 0;//ドラッグシュート放出フラグ |
Gaku0606 | 0:3e847864d796 | 91 | Timeout drogueSeparationTimer;//ドラッグシュート放出タイマー |
Gaku0606 | 0:3e847864d796 | 92 | float currentAngle = 0; |
Gaku0606 | 0:3e847864d796 | 93 | float zeroAngle = 0; |
Gaku0606 | 0:3e847864d796 | 94 | |
Gaku0606 | 0:3e847864d796 | 95 | void drogueSeparation(){ |
Gaku0606 | 0:3e847864d796 | 96 | if(fastPressureFlag == 0){ |
Gaku0606 | 0:3e847864d796 | 97 | drogueSepaFlag = 1; |
Gaku0606 | 0:3e847864d796 | 98 | } |
Gaku0606 | 0:3e847864d796 | 99 | return; |
Gaku0606 | 0:3e847864d796 | 100 | } |
Gaku0606 | 0:3e847864d796 | 101 | //------------------------------------------------------------------------------ |
Gaku0606 | 0:3e847864d796 | 102 | // ニクロム線 メインパラシュート放出分離機構 |
Gaku0606 | 0:3e847864d796 | 103 | //------------------------------------------------------------------------------ |
Gaku0606 | 0:3e847864d796 | 104 | #define NICROM_PIN p30 |
Gaku0606 | 0:3e847864d796 | 105 | #define NICROM_PIN2 p23 |
Gaku0606 | 0:3e847864d796 | 106 | Nicrom nicrom(NICROM_PIN); |
Gaku0606 | 0:3e847864d796 | 107 | Nicrom nicrom2(NICROM_PIN2); |
Gaku0606 | 0:3e847864d796 | 108 | |
Gaku0606 | 0:3e847864d796 | 109 | int mainParaSepaFlag = 0; |
Gaku0606 | 0:3e847864d796 | 110 | Timeout mainParaSeparationTimer;//メインパラシュート放出タイマー |
Gaku0606 | 0:3e847864d796 | 111 | |
Gaku0606 | 0:3e847864d796 | 112 | void mainParaSeparation(){ |
Gaku0606 | 0:3e847864d796 | 113 | if(fastPressureFlag == 0){ |
Gaku0606 | 0:3e847864d796 | 114 | mainParaSepaFlag = 1; |
Gaku0606 | 0:3e847864d796 | 115 | } |
Gaku0606 | 0:3e847864d796 | 116 | return; |
Gaku0606 | 0:3e847864d796 | 117 | } |
Gaku0606 | 0:3e847864d796 | 118 | |
Gaku0606 | 0:3e847864d796 | 119 | //------------------------------------------------------------------------------ |
Gaku0606 | 0:3e847864d796 | 120 | // フライトピン用外部割り込み設定 |
Gaku0606 | 0:3e847864d796 | 121 | //------------------------------------------------------------------------------ |
Gaku0606 | 0:3e847864d796 | 122 | |
Gaku0606 | 0:3e847864d796 | 123 | #define FLIGHT_PIN p24 |
Gaku0606 | 0:3e847864d796 | 124 | static volatile int flightPinFlag = 0; |
Gaku0606 | 0:3e847864d796 | 125 | static volatile int flightPinOKFlag = 0; |
Gaku0606 | 0:3e847864d796 | 126 | |
Gaku0606 | 0:3e847864d796 | 127 | void flightPinCallFunc(){//この関数内でニクロム線に電流を流してもいいかなと考えたりもした |
Gaku0606 | 0:3e847864d796 | 128 | flightPinFlag = 1; |
Gaku0606 | 0:3e847864d796 | 129 | return; |
Gaku0606 | 0:3e847864d796 | 130 | } |
Gaku0606 | 0:3e847864d796 | 131 | //InterruptIn flightPin(FLIGHT_PIN); |
Gaku0606 | 0:3e847864d796 | 132 | ExtTrigger flightPin(FLIGHT_PIN, FALL, &flightPinCallFunc, 0.2f);//ピン番号,立ち下がり,呼び出す関数,チャタリング待ち時間 |
Gaku0606 | 0:3e847864d796 | 133 | |
Gaku0606 | 0:3e847864d796 | 134 | //------------------------------------------------------------------------------ |
Gaku0606 | 0:3e847864d796 | 135 | // 分離検知 |
Gaku0606 | 0:3e847864d796 | 136 | //------------------------------------------------------------------------------ |
Gaku0606 | 0:3e847864d796 | 137 | #define DETECT_SEPARATION_PIN1 p12 |
Gaku0606 | 0:3e847864d796 | 138 | static int detectSepaFlag1 = 0; |
Gaku0606 | 0:3e847864d796 | 139 | void detectDrogueSepa(){ |
Gaku0606 | 0:3e847864d796 | 140 | detectSepaFlag1 = 1; |
Gaku0606 | 0:3e847864d796 | 141 | return; |
Gaku0606 | 0:3e847864d796 | 142 | } |
Gaku0606 | 0:3e847864d796 | 143 | ExtTrigger DetectDrogueSeparation(DETECT_SEPARATION_PIN1, RISE, &detectDrogueSepa, 0.2f); |
Gaku0606 | 0:3e847864d796 | 144 | |
Gaku0606 | 0:3e847864d796 | 145 | //------------------------------------------------------------------------------ |
Gaku0606 | 0:3e847864d796 | 146 | // バッテリー電圧チェック |
Gaku0606 | 0:3e847864d796 | 147 | //------------------------------------------------------------------------------ |
Gaku0606 | 0:3e847864d796 | 148 | #define MAIN_BATTERY_PIN p18 |
Gaku0606 | 0:3e847864d796 | 149 | #define EXT_BATTERY_PIN p19 |
Gaku0606 | 0:3e847864d796 | 150 | #define USING_MAIN_PIN p20 |
Gaku0606 | 0:3e847864d796 | 151 | battery_monitoring bt(2.6118, 2.9647, MAIN_BATTERY_PIN ); |
Gaku0606 | 0:3e847864d796 | 152 | battery_monitoring ext_bt(2.6118, 2.9647, EXT_BATTERY_PIN); |
Gaku0606 | 0:3e847864d796 | 153 | battery_monitoring usingMainbt(2.6118, 2.9647, USING_MAIN_PIN); |
Gaku0606 | 0:3e847864d796 | 154 | |
Gaku0606 | 0:3e847864d796 | 155 | //------------------------------------------------------------------------------ |
Gaku0606 | 0:3e847864d796 | 156 | // GPS 関連 |
Gaku0606 | 0:3e847864d796 | 157 | //------------------------------------------------------------------------------ |
Gaku0606 | 0:3e847864d796 | 158 | Serial mygps(p28, p27, 115200); |
Gaku0606 | 0:3e847864d796 | 159 | GPS_interrupt gps(&mygps); |
Gaku0606 | 0:3e847864d796 | 160 | /* |
Gaku0606 | 0:3e847864d796 | 161 | static double K = 0; |
Gaku0606 | 0:3e847864d796 | 162 | static double I = 0;*/ |
Gaku0606 | 0:3e847864d796 | 163 | static double KI[2] = {0.0, 0.0}; |
Gaku0606 | 0:3e847864d796 | 164 | static int satellitesNumber = 0;//捕捉衛星数 |
Gaku0606 | 0:3e847864d796 | 165 | static double altitude = 0;//高度 |
Gaku0606 | 0:3e847864d796 | 166 | static double speed_knot = 0;//対地速度[m/s] |
Gaku0606 | 0:3e847864d796 | 167 | static double head = 0;//進行方角,北から左回り正,0~359[°] |
Gaku0606 | 0:3e847864d796 | 168 | |
Gaku0606 | 0:3e847864d796 | 169 | //------------------------------------------------------------------------------ |
Gaku0606 | 0:3e847864d796 | 170 | // microSDカードの設定 |
Gaku0606 | 0:3e847864d796 | 171 | //------------------------------------------------------------------------------ |
Gaku0606 | 0:3e847864d796 | 172 | #define MOSI p5 |
Gaku0606 | 0:3e847864d796 | 173 | #define MISO p6 |
Gaku0606 | 0:3e847864d796 | 174 | #define SCK p7 |
Gaku0606 | 0:3e847864d796 | 175 | #define CS_SD p8 |
Gaku0606 | 0:3e847864d796 | 176 | SDFileSystem sd(MOSI, MISO, SCK, CS_SD, "sd"); |
Gaku0606 | 0:3e847864d796 | 177 | static double sdBuff[14] = {0.0}; |
Gaku0606 | 0:3e847864d796 | 178 | //------------------------------------------------------------------------------ |
Gaku0606 | 0:3e847864d796 | 179 | // 割り込みでMadgwickFilterを回す |
Gaku0606 | 0:3e847864d796 | 180 | //------------------------------------------------------------------------------ |
Gaku0606 | 0:3e847864d796 | 181 | static double imu[6] = {0};//角速度xyz,加速度xyz |
Gaku0606 | 0:3e847864d796 | 182 | static double mag[3] = {0};//地磁気xyz |
Gaku0606 | 0:3e847864d796 | 183 | static Quaternion myQ(1.0f,0.0f,0.0f,0.0f);//姿勢のクォータニオン |
Gaku0606 | 0:3e847864d796 | 184 | |
Gaku0606 | 0:3e847864d796 | 185 | |
Gaku0606 | 0:3e847864d796 | 186 | |
Gaku0606 | 0:3e847864d796 | 187 | //------------------------------------------------------------------------------ |
Gaku0606 | 0:3e847864d796 | 188 | // LPS25H |
Gaku0606 | 0:3e847864d796 | 189 | //------------------------------------------------------------------------------ |
Gaku0606 | 0:3e847864d796 | 190 | #include "LPS25H.h" |
Gaku0606 | 0:3e847864d796 | 191 | MyLPS25H lps25h(i2cBus); |
Gaku0606 | 0:3e847864d796 | 192 | |
Gaku0606 | 0:3e847864d796 | 193 | double pressure = 0; |
Gaku0606 | 0:3e847864d796 | 194 | uint32_t pressureRaw = 0; |
Gaku0606 | 0:3e847864d796 | 195 | int fallingFlag = 0; |
Gaku0606 | 0:3e847864d796 | 196 | |
Gaku0606 | 0:3e847864d796 | 197 | //------------------------------------------------------------------------------ |
Gaku0606 | 0:3e847864d796 | 198 | // ダウンリンク |
Gaku0606 | 0:3e847864d796 | 199 | //------------------------------------------------------------------------------ |
Gaku0606 | 0:3e847864d796 | 200 | // パケット受信時に呼ばれてほしい関数のプロトタイプ宣言 Length: データ長 *message: データ |
Gaku0606 | 0:3e847864d796 | 201 | void OnXbeeDataReceived(int Length, char *message); |
Gaku0606 | 0:3e847864d796 | 202 | |
Gaku0606 | 0:3e847864d796 | 203 | XbeeApi xbeeAPI(p13, p14, 115200, OnXbeeDataReceived); |
Gaku0606 | 0:3e847864d796 | 204 | static uint64_t downlinkCount = 0; |
Gaku0606 | 0:3e847864d796 | 205 | char flightPinSeparationFlag = 0b00000000; |
Gaku0606 | 0:3e847864d796 | 206 | inline void downLink(){ |
Gaku0606 | 0:3e847864d796 | 207 | |
Gaku0606 | 0:3e847864d796 | 208 | if(gps.gps_readable){ |
Gaku0606 | 0:3e847864d796 | 209 | KI[0] = (double)gps.Longitude(); |
Gaku0606 | 0:3e847864d796 | 210 | KI[1] = (double)gps.Latitude(); |
Gaku0606 | 0:3e847864d796 | 211 | satellitesNumber = gps.Number(); |
Gaku0606 | 0:3e847864d796 | 212 | altitude = gps.Height(); |
Gaku0606 | 0:3e847864d796 | 213 | speed_knot = gps.Knot(); |
Gaku0606 | 0:3e847864d796 | 214 | head = gps.Degree(); |
Gaku0606 | 0:3e847864d796 | 215 | } |
Gaku0606 | 0:3e847864d796 | 216 | else{ |
Gaku0606 | 0:3e847864d796 | 217 | KI[0]= 0.0; KI[1] = 0.0; satellitesNumber = 0; altitude = 0.0; speed_knot = 0.0; head = 0.0; |
Gaku0606 | 0:3e847864d796 | 218 | } |
Gaku0606 | 0:3e847864d796 | 219 | |
Gaku0606 | 0:3e847864d796 | 220 | if(phaseNumber == 1){//フライトピンが抜けるまで |
Gaku0606 | 0:3e847864d796 | 221 | if(downlinkCount % 20 == 0){ |
Gaku0606 | 0:3e847864d796 | 222 | xbeeAPI.StartPacket(0x11); |
Gaku0606 | 0:3e847864d796 | 223 | xbeeAPI.Write((float)bt.debug()*9.9f); |
Gaku0606 | 0:3e847864d796 | 224 | xbeeAPI.Write((float)ext_bt.debug()*9.90f); |
Gaku0606 | 0:3e847864d796 | 225 | xbeeAPI.Write((float)usingMainbt.debug()*9.90f); |
Gaku0606 | 0:3e847864d796 | 226 | xbeeAPI.Write((float)altitude); |
Gaku0606 | 0:3e847864d796 | 227 | xbeeAPI.Write((double)pressure);//気圧 |
Gaku0606 | 0:3e847864d796 | 228 | xbeeAPI.Write((char)flightPinSeparationFlag); |
Gaku0606 | 0:3e847864d796 | 229 | xbeeAPI.EndPacket(); |
Gaku0606 | 0:3e847864d796 | 230 | } |
Gaku0606 | 0:3e847864d796 | 231 | else{ |
Gaku0606 | 0:3e847864d796 | 232 | xbeeAPI.StartPacket(0x10); |
Gaku0606 | 0:3e847864d796 | 233 | xbeeAPI.Write((float)myQ.x);//姿勢クォータニオン |
Gaku0606 | 0:3e847864d796 | 234 | xbeeAPI.Write((float)myQ.y); |
Gaku0606 | 0:3e847864d796 | 235 | xbeeAPI.Write((float)myQ.z); |
Gaku0606 | 0:3e847864d796 | 236 | xbeeAPI.Write((float)myQ.w); |
Gaku0606 | 0:3e847864d796 | 237 | xbeeAPI.Write((float)(KI[0] - 139.0));//130.901722222);//gps.Longitude());//GPS座標 |
Gaku0606 | 0:3e847864d796 | 238 | xbeeAPI.Write((float)(KI[1] - 34.0));//30.4103833333);//gps.Latitude()); |
Gaku0606 | 0:3e847864d796 | 239 | xbeeAPI.EndPacket(); |
Gaku0606 | 0:3e847864d796 | 240 | } |
Gaku0606 | 0:3e847864d796 | 241 | } |
Gaku0606 | 0:3e847864d796 | 242 | else if(phaseNumber == 2){//飛行中 |
Gaku0606 | 0:3e847864d796 | 243 | if(downlinkCount % 10 == 0){ |
Gaku0606 | 0:3e847864d796 | 244 | |
Gaku0606 | 0:3e847864d796 | 245 | xbeeAPI.StartPacket(0x12); |
Gaku0606 | 0:3e847864d796 | 246 | xbeeAPI.Write((int)innerTime.read_us()); |
Gaku0606 | 0:3e847864d796 | 247 | xbeeAPI.Write((float)altitude);//100.0f);//(float)gps.Height()); |
Gaku0606 | 0:3e847864d796 | 248 | xbeeAPI.Write((float)speed_knot);//80.0f);//(float)gps.Knot()); |
Gaku0606 | 0:3e847864d796 | 249 | xbeeAPI.Write((float)head);//270.0f);//(float)gps.Degree()); |
Gaku0606 | 0:3e847864d796 | 250 | xbeeAPI.Write((double)pressure);//気圧 |
Gaku0606 | 0:3e847864d796 | 251 | xbeeAPI.Write(flightPinSeparationFlag); |
Gaku0606 | 0:3e847864d796 | 252 | xbeeAPI.EndPacket(); |
Gaku0606 | 0:3e847864d796 | 253 | } |
Gaku0606 | 0:3e847864d796 | 254 | else{ |
Gaku0606 | 0:3e847864d796 | 255 | xbeeAPI.StartPacket(0x10); |
Gaku0606 | 0:3e847864d796 | 256 | xbeeAPI.Write((float)myQ.x);//姿勢クォータニオン |
Gaku0606 | 0:3e847864d796 | 257 | xbeeAPI.Write((float)myQ.y); |
Gaku0606 | 0:3e847864d796 | 258 | xbeeAPI.Write((float)myQ.z); |
Gaku0606 | 0:3e847864d796 | 259 | xbeeAPI.Write((float)myQ.w); |
Gaku0606 | 0:3e847864d796 | 260 | xbeeAPI.Write((float)(KI[0] - 139.0));//gps.Longitude());//GPS座標 |
Gaku0606 | 0:3e847864d796 | 261 | xbeeAPI.Write((float)(KI[1] - 34.0));//gps.Latitude()); |
Gaku0606 | 0:3e847864d796 | 262 | xbeeAPI.EndPacket(); |
Gaku0606 | 0:3e847864d796 | 263 | //pc.printf("%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\r\n",innerTime.read(),myQ.x,myQ.y,myQ.z,myQ.w,gps.Longitude(),gps.Latitude(),pressure); |
Gaku0606 | 0:3e847864d796 | 264 | } |
Gaku0606 | 0:3e847864d796 | 265 | } |
Gaku0606 | 0:3e847864d796 | 266 | else if(phaseNumber == 3){//回収待機中 |
Gaku0606 | 0:3e847864d796 | 267 | xbeeAPI.StartPacket(0x13); |
Gaku0606 | 0:3e847864d796 | 268 | xbeeAPI.Write((float)(KI[0] - 139.0));//130.901722222);//gps.Longitude());//GPS座標 |
Gaku0606 | 0:3e847864d796 | 269 | xbeeAPI.Write((float)(KI[1] - 34.0));//30.4103833333);//gps.Latitude()); |
Gaku0606 | 0:3e847864d796 | 270 | //xbeeAPI.Write((double)pressure); |
Gaku0606 | 0:3e847864d796 | 271 | xbeeAPI.Write((float)bt.debug()*9.9f); |
Gaku0606 | 0:3e847864d796 | 272 | xbeeAPI.Write((float)ext_bt.debug()*9.90f); |
Gaku0606 | 0:3e847864d796 | 273 | xbeeAPI.Write((float)usingMainbt.debug()*9.90f); |
Gaku0606 | 0:3e847864d796 | 274 | xbeeAPI.EndPacket(); |
Gaku0606 | 0:3e847864d796 | 275 | } |
Gaku0606 | 0:3e847864d796 | 276 | downlinkCount++; |
Gaku0606 | 0:3e847864d796 | 277 | } |
Gaku0606 | 0:3e847864d796 | 278 | |
Gaku0606 | 0:3e847864d796 | 279 | inline void Print(char* str){ |
Gaku0606 | 0:3e847864d796 | 280 | //pc.printf("%s\r\n", str); |
Gaku0606 | 0:3e847864d796 | 281 | string s(str); |
Gaku0606 | 0:3e847864d796 | 282 | xbeeAPI.StartPacket(0x50); |
Gaku0606 | 0:3e847864d796 | 283 | xbeeAPI.Write(s);//文字列 |
Gaku0606 | 0:3e847864d796 | 284 | xbeeAPI.EndPacket(); |
Gaku0606 | 0:3e847864d796 | 285 | return; |
Gaku0606 | 0:3e847864d796 | 286 | } |
Gaku0606 | 0:3e847864d796 | 287 | // パケット受信時の処理 Length: データ長 *message: データ |
Gaku0606 | 0:3e847864d796 | 288 | void OnXbeeDataReceived(int Length, char *message){ |
Gaku0606 | 0:3e847864d796 | 289 | pc.printf("%d\t%s\r\n",Length, message); |
Gaku0606 | 0:3e847864d796 | 290 | if(message[0] == 0x58){//'X'サーボ |
Gaku0606 | 0:3e847864d796 | 291 | if(message[1] == 0xFF){ |
Gaku0606 | 0:3e847864d796 | 292 | zeroAngle = currentAngle; |
Gaku0606 | 0:3e847864d796 | 293 | Print("Set Zero Angle"); |
Gaku0606 | 0:3e847864d796 | 294 | } |
Gaku0606 | 0:3e847864d796 | 295 | else{ |
Gaku0606 | 0:3e847864d796 | 296 | currentAngle = (double)(message[1] - 90); |
Gaku0606 | 0:3e847864d796 | 297 | servo = currentAngle; |
Gaku0606 | 0:3e847864d796 | 298 | servo2 = currentAngle; |
Gaku0606 | 0:3e847864d796 | 299 | char mojiretu[32] = ""; |
Gaku0606 | 0:3e847864d796 | 300 | sprintf(mojiretu, "Set Servo: %d", (int)message[1]); |
Gaku0606 | 0:3e847864d796 | 301 | Print(mojiretu); |
Gaku0606 | 0:3e847864d796 | 302 | } |
Gaku0606 | 0:3e847864d796 | 303 | } |
Gaku0606 | 0:3e847864d796 | 304 | else if(message[0] == 0x46){//'F' フライトピン待機開始許可フラグ |
Gaku0606 | 0:3e847864d796 | 305 | if((flightPin.read() == 1) && (message[1] == 0x4F)){//'O' Flightpin OK |
Gaku0606 | 0:3e847864d796 | 306 | flightPinOKFlag = 1; |
Gaku0606 | 0:3e847864d796 | 307 | Print("Start Wait Flight Pin"); |
Gaku0606 | 0:3e847864d796 | 308 | } |
Gaku0606 | 0:3e847864d796 | 309 | else if(message[1] == 0x4E){ |
Gaku0606 | 0:3e847864d796 | 310 | flightPinOKFlag = 0; |
Gaku0606 | 0:3e847864d796 | 311 | Print("Flight Pin Reset!!\r\n"); |
Gaku0606 | 0:3e847864d796 | 312 | } |
Gaku0606 | 0:3e847864d796 | 313 | } |
Gaku0606 | 0:3e847864d796 | 314 | //指令分離 |
Gaku0606 | 0:3e847864d796 | 315 | else if((flightPinFlag == 1) && (Length > 5) && (message[0] == 'J')){//J B K C M D |
Gaku0606 | 0:3e847864d796 | 316 | if(message[1] == 'B'){ |
Gaku0606 | 0:3e847864d796 | 317 | if(message[2] == 'K'){ |
Gaku0606 | 0:3e847864d796 | 318 | if(message[3] == 'C'){ |
Gaku0606 | 0:3e847864d796 | 319 | if(message[4] == 'M'){ |
Gaku0606 | 0:3e847864d796 | 320 | if(message[5] == 'D'){ |
Gaku0606 | 0:3e847864d796 | 321 | mainParaSepaFlag = 1; |
Gaku0606 | 0:3e847864d796 | 322 | } |
Gaku0606 | 0:3e847864d796 | 323 | } |
Gaku0606 | 0:3e847864d796 | 324 | } |
Gaku0606 | 0:3e847864d796 | 325 | } |
Gaku0606 | 0:3e847864d796 | 326 | } |
Gaku0606 | 0:3e847864d796 | 327 | } |
Gaku0606 | 0:3e847864d796 | 328 | } |
Gaku0606 | 0:3e847864d796 | 329 | |
Gaku0606 | 0:3e847864d796 | 330 | //------------------------------------------------------------------------------ |
Gaku0606 | 0:3e847864d796 | 331 | // スケジュール割り込み関数 |
Gaku0606 | 0:3e847864d796 | 332 | //------------------------------------------------------------------------------ |
Gaku0606 | 0:3e847864d796 | 333 | const int CALL_PERIOD = 50000;//us |
Gaku0606 | 0:3e847864d796 | 334 | |
Gaku0606 | 0:3e847864d796 | 335 | Ticker ScheduleCallTimer;//schedule |
Gaku0606 | 0:3e847864d796 | 336 | int sdSaveFlag = 0; |
Gaku0606 | 0:3e847864d796 | 337 | void autoCallFunc(){ |
Gaku0606 | 0:3e847864d796 | 338 | |
Gaku0606 | 0:3e847864d796 | 339 | //static uint64_t timingCount = 0; |
Gaku0606 | 0:3e847864d796 | 340 | sdSaveFlag = 1; |
Gaku0606 | 0:3e847864d796 | 341 | downLink(); |
Gaku0606 | 0:3e847864d796 | 342 | //timingCount++; |
Gaku0606 | 0:3e847864d796 | 343 | } |
Gaku0606 | 0:3e847864d796 | 344 | /** |
Gaku0606 | 0:3e847864d796 | 345 | * 0.2秒ごとに増えていく |
Gaku0606 | 0:3e847864d796 | 346 | */ |
Gaku0606 | 0:3e847864d796 | 347 | int sepaCount = 0; |
Gaku0606 | 0:3e847864d796 | 348 | Ticker SepaCountTimer; |
Gaku0606 | 0:3e847864d796 | 349 | void SepaCountFunc(){ |
Gaku0606 | 0:3e847864d796 | 350 | sepaCount++; |
Gaku0606 | 0:3e847864d796 | 351 | return; |
Gaku0606 | 0:3e847864d796 | 352 | } |
Gaku0606 | 0:3e847864d796 | 353 | |
Gaku0606 | 0:3e847864d796 | 354 | //------------------------------------------------------------------------------ |
Gaku0606 | 0:3e847864d796 | 355 | // 1段目分離からの2段目分離タイマー |
Gaku0606 | 0:3e847864d796 | 356 | //------------------------------------------------------------------------------ |
Gaku0606 | 0:3e847864d796 | 357 | Timeout secondSepaDelayTimer; |
Gaku0606 | 0:3e847864d796 | 358 | void secondSepaDelayFunc(){ |
Gaku0606 | 0:3e847864d796 | 359 | mainParaSepaFlag = 1; |
Gaku0606 | 0:3e847864d796 | 360 | return; |
Gaku0606 | 0:3e847864d796 | 361 | } |
Gaku0606 | 0:3e847864d796 | 362 | //------------------------------------------------------------------------------ |
Gaku0606 | 0:3e847864d796 | 363 | // フライトピンが抜けてから6秒は分離しないというセーフティ的な何か |
Gaku0606 | 0:3e847864d796 | 364 | //------------------------------------------------------------------------------ |
Gaku0606 | 0:3e847864d796 | 365 | int safetyFlag = 0; |
Gaku0606 | 0:3e847864d796 | 366 | Timeout safetyTimer; |
Gaku0606 | 0:3e847864d796 | 367 | void safetyFunc(){ |
Gaku0606 | 0:3e847864d796 | 368 | safetyFlag = 1; |
Gaku0606 | 0:3e847864d796 | 369 | return; |
Gaku0606 | 0:3e847864d796 | 370 | } |
Gaku0606 | 0:3e847864d796 | 371 | |
Gaku0606 | 0:3e847864d796 | 372 | //------------------------------------------------------------------------------ |
Gaku0606 | 0:3e847864d796 | 373 | // 0.04秒ごとに気圧取得許可フラグを立てる |
Gaku0606 | 0:3e847864d796 | 374 | //------------------------------------------------------------------------------ |
Gaku0606 | 0:3e847864d796 | 375 | Ticker PressureGetTimer; |
Gaku0606 | 0:3e847864d796 | 376 | int pressureGetFlag = 0; |
Gaku0606 | 0:3e847864d796 | 377 | void pressureGetFunc(){ |
Gaku0606 | 0:3e847864d796 | 378 | pressureGetFlag = 1; |
Gaku0606 | 0:3e847864d796 | 379 | return; |
Gaku0606 | 0:3e847864d796 | 380 | } |
Gaku0606 | 0:3e847864d796 | 381 | |
Gaku0606 | 0:3e847864d796 | 382 | int main() { |
Gaku0606 | 0:3e847864d796 | 383 | //setPress(); |
Gaku0606 | 0:3e847864d796 | 384 | //XBee初期設定 |
Gaku0606 | 0:3e847864d796 | 385 | // 0番目の宛先アドレス |
Gaku0606 | 0:3e847864d796 | 386 | xbeeAPI.SetAddress(0, 0x0013A200, 0x40A88F02); |
Gaku0606 | 0:3e847864d796 | 387 | // 1番目の宛先アドレス |
Gaku0606 | 0:3e847864d796 | 388 | xbeeAPI.SetAddress(1, 0x0013A200, 0x40E7D43E); |
Gaku0606 | 0:3e847864d796 | 389 | // 2番目の宛先アドレス |
Gaku0606 | 0:3e847864d796 | 390 | xbeeAPI.SetAddress(2, 0x0013A200, 0x40DC2538); |
Gaku0606 | 0:3e847864d796 | 391 | //3番目の宛先アドレス |
Gaku0606 | 0:3e847864d796 | 392 | xbeeAPI.SetAddress(3, 0x0013A200, 0x40BABC20); |
Gaku0606 | 0:3e847864d796 | 393 | |
Gaku0606 | 0:3e847864d796 | 394 | flightPinSeparationFlag = 0b00000000; |
Gaku0606 | 0:3e847864d796 | 395 | |
Gaku0606 | 0:3e847864d796 | 396 | Print("start\r\n"); |
Gaku0606 | 0:3e847864d796 | 397 | Print("-----------------------------------------"); |
Gaku0606 | 0:3e847864d796 | 398 | Print("Boot Phase:"); |
Gaku0606 | 0:3e847864d796 | 399 | pc.printf("start\r\n"); |
Gaku0606 | 0:3e847864d796 | 400 | pc.printf("\r\n-----------------------------------------\r\n"); |
Gaku0606 | 0:3e847864d796 | 401 | pc.printf("Boot Phase:\r\n"); |
Gaku0606 | 0:3e847864d796 | 402 | for(char i = 0;i < 100;i++){ |
Gaku0606 | 0:3e847864d796 | 403 | pc.printf("Loading: %3d [%%]\r", i); |
Gaku0606 | 0:3e847864d796 | 404 | wait_ms(30); |
Gaku0606 | 0:3e847864d796 | 405 | } |
Gaku0606 | 0:3e847864d796 | 406 | Print("Loading: 100 [%%] -> finished!!"); |
Gaku0606 | 0:3e847864d796 | 407 | Print("-----------------------------------------"); |
Gaku0606 | 0:3e847864d796 | 408 | pc.printf("Loading: 100 [%%] -> finished!!\r\n"); |
Gaku0606 | 0:3e847864d796 | 409 | pc.printf("\r\n-----------------------------------------\r\n"); |
Gaku0606 | 0:3e847864d796 | 410 | |
Gaku0606 | 0:3e847864d796 | 411 | /*========================================================================== |
Gaku0606 | 0:3e847864d796 | 412 | フェーズⅠ < 発射待機・システムチェック > |
Gaku0606 | 0:3e847864d796 | 413 | ===========================================================================*/ |
Gaku0606 | 0:3e847864d796 | 414 | phaseNumber = 1; |
Gaku0606 | 0:3e847864d796 | 415 | int temp_time = 0; |
Gaku0606 | 0:3e847864d796 | 416 | Print("----------------"); |
Gaku0606 | 0:3e847864d796 | 417 | Print("Phase I START"); |
Gaku0606 | 0:3e847864d796 | 418 | pc.printf("\r\n----------------\r\n"); |
Gaku0606 | 0:3e847864d796 | 419 | pc.printf("Phase I START\r\n"); |
Gaku0606 | 0:3e847864d796 | 420 | |
Gaku0606 | 0:3e847864d796 | 421 | Print("SD check ->"); |
Gaku0606 | 0:3e847864d796 | 422 | pc.printf("SD check -> "); |
Gaku0606 | 0:3e847864d796 | 423 | fp = fopen("/sd/check.txt", "w"); |
Gaku0606 | 0:3e847864d796 | 424 | if(fp == NULL){ |
Gaku0606 | 0:3e847864d796 | 425 | while(1){ |
Gaku0606 | 0:3e847864d796 | 426 | Print("SD ERROR"); |
Gaku0606 | 0:3e847864d796 | 427 | error("SD ERROR\r\n"); |
Gaku0606 | 0:3e847864d796 | 428 | } |
Gaku0606 | 0:3e847864d796 | 429 | } |
Gaku0606 | 0:3e847864d796 | 430 | else{ |
Gaku0606 | 0:3e847864d796 | 431 | pc.printf("OK\r\n"); |
Gaku0606 | 0:3e847864d796 | 432 | Print("\tOK"); |
Gaku0606 | 0:3e847864d796 | 433 | fprintf(fp,"this file is made by checking sd card program.\r\n"); |
Gaku0606 | 0:3e847864d796 | 434 | fclose(fp); |
Gaku0606 | 0:3e847864d796 | 435 | } |
Gaku0606 | 0:3e847864d796 | 436 | |
Gaku0606 | 0:3e847864d796 | 437 | while(1){ |
Gaku0606 | 0:3e847864d796 | 438 | static int fileCount = 0; |
Gaku0606 | 0:3e847864d796 | 439 | sprintf(datafile, "/sd/datafile%d.txt", fileCount); |
Gaku0606 | 0:3e847864d796 | 440 | fp = fopen(datafile, "rb"); |
Gaku0606 | 0:3e847864d796 | 441 | if(fp != NULL){ |
Gaku0606 | 0:3e847864d796 | 442 | fclose(fp); |
Gaku0606 | 0:3e847864d796 | 443 | fileCount++; |
Gaku0606 | 0:3e847864d796 | 444 | } |
Gaku0606 | 0:3e847864d796 | 445 | else{ |
Gaku0606 | 0:3e847864d796 | 446 | fp = fopen(datafile, "wb"); |
Gaku0606 | 0:3e847864d796 | 447 | if(fp == NULL){//ファイルオープン失敗 |
Gaku0606 | 0:3e847864d796 | 448 | while(1){ |
Gaku0606 | 0:3e847864d796 | 449 | Print("file open error\r\n"); |
Gaku0606 | 0:3e847864d796 | 450 | pc.printf("file open error\r\n"); |
Gaku0606 | 0:3e847864d796 | 451 | wait(1.0); |
Gaku0606 | 0:3e847864d796 | 452 | } |
Gaku0606 | 0:3e847864d796 | 453 | } |
Gaku0606 | 0:3e847864d796 | 454 | fclose(fp); |
Gaku0606 | 0:3e847864d796 | 455 | fp = fopen(datafile, "wb"); |
Gaku0606 | 0:3e847864d796 | 456 | if(fp != NULL){ |
Gaku0606 | 0:3e847864d796 | 457 | fclose(fp); |
Gaku0606 | 0:3e847864d796 | 458 | } |
Gaku0606 | 0:3e847864d796 | 459 | break; |
Gaku0606 | 0:3e847864d796 | 460 | } |
Gaku0606 | 0:3e847864d796 | 461 | } |
Gaku0606 | 0:3e847864d796 | 462 | |
Gaku0606 | 0:3e847864d796 | 463 | |
Gaku0606 | 0:3e847864d796 | 464 | //内部タイマースタート |
Gaku0606 | 0:3e847864d796 | 465 | innerTime.reset(); |
Gaku0606 | 0:3e847864d796 | 466 | innerTime.start(); |
Gaku0606 | 0:3e847864d796 | 467 | lps25h.SetPress(); |
Gaku0606 | 0:3e847864d796 | 468 | |
Gaku0606 | 0:3e847864d796 | 469 | //9軸センサ 初期設定 |
Gaku0606 | 0:3e847864d796 | 470 | nine.setAccLPF(SET_ACC_LPF); |
Gaku0606 | 0:3e847864d796 | 471 | nine.setGyro(SET_GYRO); |
Gaku0606 | 0:3e847864d796 | 472 | nine.setAcc(SET_ACC); |
Gaku0606 | 0:3e847864d796 | 473 | //9軸センサ オフセット設定 |
Gaku0606 | 0:3e847864d796 | 474 | nine.setOffset(nine_offset[0], nine_offset[1], nine_offset[2], |
Gaku0606 | 0:3e847864d796 | 475 | nine_offset[3], nine_offset[4], nine_offset[5], |
Gaku0606 | 0:3e847864d796 | 476 | nine_offset[6], nine_offset[7], nine_offset[8]); |
Gaku0606 | 0:3e847864d796 | 477 | |
Gaku0606 | 0:3e847864d796 | 478 | Print("finished mpu9250 setting"); |
Gaku0606 | 0:3e847864d796 | 479 | pc.printf("finished mpu9250 setting"); |
Gaku0606 | 0:3e847864d796 | 480 | |
Gaku0606 | 0:3e847864d796 | 481 | //割り込みセンサーアクセス関数セット |
Gaku0606 | 0:3e847864d796 | 482 | MadgwickFilter attitude(0.1); |
Gaku0606 | 0:3e847864d796 | 483 | ScheduleCallTimer.attach_us(&autoCallFunc, CALL_PERIOD);//&downLink, 50000);// |
Gaku0606 | 0:3e847864d796 | 484 | PressureGetTimer.attach(&pressureGetFunc, 0.04f); |
Gaku0606 | 0:3e847864d796 | 485 | |
Gaku0606 | 0:3e847864d796 | 486 | |
Gaku0606 | 0:3e847864d796 | 487 | //フライトピンをさすループ |
Gaku0606 | 0:3e847864d796 | 488 | waitFlightPinLabel: |
Gaku0606 | 0:3e847864d796 | 489 | flightPin.clear(); |
Gaku0606 | 0:3e847864d796 | 490 | flightPinOKFlag = 0; |
Gaku0606 | 0:3e847864d796 | 491 | Print("wait for connect Flight Pin"); |
Gaku0606 | 0:3e847864d796 | 492 | pc.printf("wait for connect Flight Pin"); |
Gaku0606 | 0:3e847864d796 | 493 | |
Gaku0606 | 0:3e847864d796 | 494 | flightPinSeparationFlag = 0b10000000;//7bit目を0に |
Gaku0606 | 0:3e847864d796 | 495 | |
Gaku0606 | 0:3e847864d796 | 496 | while(1){ |
Gaku0606 | 0:3e847864d796 | 497 | nine.getGyroAcc(imu);//慣性データ取得 |
Gaku0606 | 0:3e847864d796 | 498 | nine.getMag(mag);//地磁気データ取得 |
Gaku0606 | 0:3e847864d796 | 499 | attitude.MadgwickAHRSupdate(imu[0]*DEG_TO_RAD, imu[1]*DEG_TO_RAD, imu[2]*DEG_TO_RAD, imu[3], imu[4], imu[5], mag[0], mag[1], mag[2]);//姿勢推定 |
Gaku0606 | 0:3e847864d796 | 500 | attitude.getAttitude(&myQ); //姿勢をクォータニオンで取得 |
Gaku0606 | 0:3e847864d796 | 501 | if(pressureGetFlag){ |
Gaku0606 | 0:3e847864d796 | 502 | pressureGetFlag = 0; |
Gaku0606 | 0:3e847864d796 | 503 | lps25h.GetPress(&pressure, &pressureRaw); |
Gaku0606 | 0:3e847864d796 | 504 | } |
Gaku0606 | 0:3e847864d796 | 505 | pc.printf("Attitude:%f,%f,%f,%f\r\n", myQ.x, myQ.y, myQ.z, myQ.w); |
Gaku0606 | 0:3e847864d796 | 506 | pc.printf("%f\r\n",pressure); |
Gaku0606 | 0:3e847864d796 | 507 | //pc.printf("%f\t%f\r\n", KI[0], KI[1]); |
Gaku0606 | 0:3e847864d796 | 508 | if(flightPin.read() == 1){ |
Gaku0606 | 0:3e847864d796 | 509 | flightPinSeparationFlag = flightPinSeparationFlag & 0b01111111;//7bit目を0に |
Gaku0606 | 0:3e847864d796 | 510 | if(flightPinOKFlag == 1){ |
Gaku0606 | 0:3e847864d796 | 511 | break; |
Gaku0606 | 0:3e847864d796 | 512 | } |
Gaku0606 | 0:3e847864d796 | 513 | else if(pc.readable()){//デバッグ |
Gaku0606 | 0:3e847864d796 | 514 | char flightChar = pc.getc(); |
Gaku0606 | 0:3e847864d796 | 515 | if(flightChar == 'F'){ |
Gaku0606 | 0:3e847864d796 | 516 | flightPinOKFlag = 1; |
Gaku0606 | 0:3e847864d796 | 517 | break; |
Gaku0606 | 0:3e847864d796 | 518 | } |
Gaku0606 | 0:3e847864d796 | 519 | } |
Gaku0606 | 0:3e847864d796 | 520 | } |
Gaku0606 | 0:3e847864d796 | 521 | else flightPinSeparationFlag |= 0b10000000; |
Gaku0606 | 0:3e847864d796 | 522 | |
Gaku0606 | 0:3e847864d796 | 523 | if(abs(temp_time - innerTime.read_ms()) > 500){ |
Gaku0606 | 0:3e847864d796 | 524 | // Print("wait for connect Flight Pin and send F."); |
Gaku0606 | 0:3e847864d796 | 525 | pc.printf("wait for connect Flight Pin and send F."); |
Gaku0606 | 0:3e847864d796 | 526 | temp_time = innerTime.read_ms(); |
Gaku0606 | 0:3e847864d796 | 527 | } |
Gaku0606 | 0:3e847864d796 | 528 | |
Gaku0606 | 0:3e847864d796 | 529 | //分離機構が作動してしまった時の例のやつ |
Gaku0606 | 0:3e847864d796 | 530 | if(DetectDrogueSeparation.read() == 1){ |
Gaku0606 | 0:3e847864d796 | 531 | flightPinSeparationFlag = flightPinSeparationFlag | 0b00100000; |
Gaku0606 | 0:3e847864d796 | 532 | } |
Gaku0606 | 0:3e847864d796 | 533 | else{ |
Gaku0606 | 0:3e847864d796 | 534 | flightPinSeparationFlag = flightPinSeparationFlag & 0b11011111; |
Gaku0606 | 0:3e847864d796 | 535 | } |
Gaku0606 | 0:3e847864d796 | 536 | } |
Gaku0606 | 0:3e847864d796 | 537 | |
Gaku0606 | 0:3e847864d796 | 538 | //フライトピン待機 |
Gaku0606 | 0:3e847864d796 | 539 | temp_time = innerTime.read_ms(); |
Gaku0606 | 0:3e847864d796 | 540 | flightPinFlag = 0; |
Gaku0606 | 0:3e847864d796 | 541 | |
Gaku0606 | 0:3e847864d796 | 542 | flightPinSeparationFlag = flightPinSeparationFlag | 0b01000000;//6bit目を1に |
Gaku0606 | 0:3e847864d796 | 543 | |
Gaku0606 | 0:3e847864d796 | 544 | while(flightPinFlag == 0){ |
Gaku0606 | 0:3e847864d796 | 545 | |
Gaku0606 | 0:3e847864d796 | 546 | nine.getGyroAcc(imu);//慣性データ取得 |
Gaku0606 | 0:3e847864d796 | 547 | nine.getMag(mag);//地磁気データ取得 |
Gaku0606 | 0:3e847864d796 | 548 | attitude.MadgwickAHRSupdate(imu[0]*DEG_TO_RAD, imu[1]*DEG_TO_RAD, imu[2]*DEG_TO_RAD, imu[3], imu[4], imu[5], mag[0], mag[1], mag[2]);//姿勢推定 |
Gaku0606 | 0:3e847864d796 | 549 | attitude.getAttitude(&myQ); //姿勢をクォータニオンで取得 |
Gaku0606 | 0:3e847864d796 | 550 | pc.printf("Attitude:%f,%f,%f,%f\r\n", myQ.x, myQ.y, myQ.z, myQ.w); |
Gaku0606 | 0:3e847864d796 | 551 | if(pressureGetFlag){ |
Gaku0606 | 0:3e847864d796 | 552 | pressureGetFlag = 0; |
Gaku0606 | 0:3e847864d796 | 553 | lps25h.GetPress(&pressure, &pressureRaw); |
Gaku0606 | 0:3e847864d796 | 554 | } |
Gaku0606 | 0:3e847864d796 | 555 | if(abs(temp_time - innerTime.read_ms()) > 5000){ |
Gaku0606 | 0:3e847864d796 | 556 | pc.printf("Wait for Flight Pin Left"); |
Gaku0606 | 0:3e847864d796 | 557 | temp_time = innerTime.read_ms(); |
Gaku0606 | 0:3e847864d796 | 558 | } |
Gaku0606 | 0:3e847864d796 | 559 | if(flightPinOKFlag == 0){ |
Gaku0606 | 0:3e847864d796 | 560 | goto waitFlightPinLabel; |
Gaku0606 | 0:3e847864d796 | 561 | } |
Gaku0606 | 0:3e847864d796 | 562 | |
Gaku0606 | 0:3e847864d796 | 563 | //分離機構が作動してしまった時の例のやつ |
Gaku0606 | 0:3e847864d796 | 564 | if(DetectDrogueSeparation.read() == 1){ |
Gaku0606 | 0:3e847864d796 | 565 | flightPinSeparationFlag = flightPinSeparationFlag | 0b00100000; |
Gaku0606 | 0:3e847864d796 | 566 | } |
Gaku0606 | 0:3e847864d796 | 567 | else{ |
Gaku0606 | 0:3e847864d796 | 568 | flightPinSeparationFlag = flightPinSeparationFlag & 0b11011111; |
Gaku0606 | 0:3e847864d796 | 569 | } |
Gaku0606 | 0:3e847864d796 | 570 | } |
Gaku0606 | 0:3e847864d796 | 571 | |
Gaku0606 | 0:3e847864d796 | 572 | flightPinSeparationFlag = flightPinSeparationFlag | 0b10000000;//7bit目を1に 0b11000000になっているはず |
Gaku0606 | 0:3e847864d796 | 573 | Print("Detect Flight Pin!!"); |
Gaku0606 | 0:3e847864d796 | 574 | pc.printf("Detect Flight Pin!!"); |
Gaku0606 | 0:3e847864d796 | 575 | Print("Launch!!!!Launch!!!!"); |
Gaku0606 | 0:3e847864d796 | 576 | Print("Phase I END"); |
Gaku0606 | 0:3e847864d796 | 577 | pc.printf("Launch!!!!Launch!!!!"); |
Gaku0606 | 0:3e847864d796 | 578 | pc.printf("Phase I END"); |
Gaku0606 | 0:3e847864d796 | 579 | /*========================================================================== |
Gaku0606 | 0:3e847864d796 | 580 | フェーズII < 飛行中 > |
Gaku0606 | 0:3e847864d796 | 581 | ==========================================================================*/ |
Gaku0606 | 0:3e847864d796 | 582 | Print("Phase II START"); |
Gaku0606 | 0:3e847864d796 | 583 | pc.printf("Phase II START"); |
Gaku0606 | 0:3e847864d796 | 584 | //色々初期化 |
Gaku0606 | 0:3e847864d796 | 585 | innerTime.reset();//内部時間 |
Gaku0606 | 0:3e847864d796 | 586 | phaseNumber = 2;//フェーズナンバー |
Gaku0606 | 0:3e847864d796 | 587 | downlinkCount = 0;// |
Gaku0606 | 0:3e847864d796 | 588 | detectSepaFlag1 = 0; |
Gaku0606 | 0:3e847864d796 | 589 | safetyFlag = 0; |
Gaku0606 | 0:3e847864d796 | 590 | safetyTimer.attach(&safetyFunc, SAFETY_TIME); |
Gaku0606 | 0:3e847864d796 | 591 | |
Gaku0606 | 0:3e847864d796 | 592 | drogueSeparationTimer.attach(&drogueSeparation, DROGUE_WAIT_TIME); |
Gaku0606 | 0:3e847864d796 | 593 | mainParaSeparationTimer.attach(&mainParaSeparation, MAIN_PARA_WAIT_TIME); |
Gaku0606 | 0:3e847864d796 | 594 | |
Gaku0606 | 0:3e847864d796 | 595 | static int SepaStartFlag = 0; |
Gaku0606 | 0:3e847864d796 | 596 | double oldPressure = (double)lps25h.GetPress(); |
Gaku0606 | 0:3e847864d796 | 597 | double deltaP = 0; |
Gaku0606 | 0:3e847864d796 | 598 | int pressureCount = 0; |
Gaku0606 | 0:3e847864d796 | 599 | |
Gaku0606 | 0:3e847864d796 | 600 | while(1){ |
Gaku0606 | 0:3e847864d796 | 601 | |
Gaku0606 | 0:3e847864d796 | 602 | //分離機構が作動してしまった時の例のやつ |
Gaku0606 | 0:3e847864d796 | 603 | if(DetectDrogueSeparation.read() == 1) flightPinSeparationFlag = flightPinSeparationFlag | 0b00100000; |
Gaku0606 | 0:3e847864d796 | 604 | else flightPinSeparationFlag = flightPinSeparationFlag & 0b11011111; |
Gaku0606 | 0:3e847864d796 | 605 | |
Gaku0606 | 0:3e847864d796 | 606 | temp_time = innerTime.read_ms(); |
Gaku0606 | 0:3e847864d796 | 607 | nine.getGyroAcc(imu);//慣性データ取得 |
Gaku0606 | 0:3e847864d796 | 608 | nine.getMag(mag);//地磁気データ取得 |
Gaku0606 | 0:3e847864d796 | 609 | attitude.MadgwickAHRSupdate(imu[0]*DEG_TO_RAD, imu[1]*DEG_TO_RAD, imu[2]*DEG_TO_RAD, imu[3], imu[4], imu[5], mag[0], mag[1], mag[2]);//姿勢推定 |
Gaku0606 | 0:3e847864d796 | 610 | attitude.getAttitude(&myQ); //姿勢をクォータニオンで取得 |
Gaku0606 | 0:3e847864d796 | 611 | |
Gaku0606 | 0:3e847864d796 | 612 | if(pressureGetFlag){//0.04秒ごとに気圧取得&比較 |
Gaku0606 | 0:3e847864d796 | 613 | pressureGetFlag = 0; |
Gaku0606 | 0:3e847864d796 | 614 | lps25h.GetPress(&pressure, &pressureRaw);//気圧取得 |
Gaku0606 | 0:3e847864d796 | 615 | |
Gaku0606 | 0:3e847864d796 | 616 | //pc.printf("%f\t%f\r\n",innerTime.read(), pressure); |
Gaku0606 | 0:3e847864d796 | 617 | |
Gaku0606 | 0:3e847864d796 | 618 | //気圧による分離条件式 |
Gaku0606 | 0:3e847864d796 | 619 | deltaP = pressure - oldPressure;//気圧の変化勾配 |
Gaku0606 | 0:3e847864d796 | 620 | if((deltaP > FALLING_THRESHOLD) && (safetyFlag == 1) && (pressure != 0.0)){//気圧差 > -0.04 かつ 6秒以上経過 |
Gaku0606 | 0:3e847864d796 | 621 | pressureCount++; |
Gaku0606 | 0:3e847864d796 | 622 | if(pressureCount > 5){//ドラッグシュート分離 |
Gaku0606 | 0:3e847864d796 | 623 | //fastPressureFlag = 1; |
Gaku0606 | 0:3e847864d796 | 624 | drogueSepaFlag = 1; |
Gaku0606 | 0:3e847864d796 | 625 | secondSepaDelayTimer.attach(&secondSepaDelayFunc, SECOND_SEPA_DELAY_TIME); |
Gaku0606 | 0:3e847864d796 | 626 | } |
Gaku0606 | 0:3e847864d796 | 627 | } |
Gaku0606 | 0:3e847864d796 | 628 | else{ |
Gaku0606 | 0:3e847864d796 | 629 | pressureCount = 0; |
Gaku0606 | 0:3e847864d796 | 630 | } |
Gaku0606 | 0:3e847864d796 | 631 | oldPressure = pressure; |
Gaku0606 | 0:3e847864d796 | 632 | } |
Gaku0606 | 0:3e847864d796 | 633 | |
Gaku0606 | 0:3e847864d796 | 634 | if(drogueSepaFlag == 1 ){//ドラッグシュート分離機構作動 |
Gaku0606 | 0:3e847864d796 | 635 | |
Gaku0606 | 0:3e847864d796 | 636 | if(SepaStartFlag == 0){ |
Gaku0606 | 0:3e847864d796 | 637 | pc.printf("Separation %f [s]\r\n", innerTime.read()); |
Gaku0606 | 0:3e847864d796 | 638 | //ビットフラグ更新 |
Gaku0606 | 0:3e847864d796 | 639 | flightPinSeparationFlag = (flightPinSeparationFlag & 0b11000111) | 0b00010000;//3bit目を1に, 作動させたがまだわからない |
Gaku0606 | 0:3e847864d796 | 640 | SepaStartFlag = 1; |
Gaku0606 | 0:3e847864d796 | 641 | SepaCountTimer.attach(&SepaCountFunc, 0.2f); |
Gaku0606 | 0:3e847864d796 | 642 | sepaCount = 0; |
Gaku0606 | 0:3e847864d796 | 643 | Print("Try Drogue Separation!!"); |
Gaku0606 | 0:3e847864d796 | 644 | pc.printf("Try Drogue Separation!!\r\n"); |
Gaku0606 | 0:3e847864d796 | 645 | servo = 30.0 + zeroAngle; |
Gaku0606 | 0:3e847864d796 | 646 | servo2 = 30.0 + zeroAngle; |
Gaku0606 | 0:3e847864d796 | 647 | } |
Gaku0606 | 0:3e847864d796 | 648 | else{ |
Gaku0606 | 0:3e847864d796 | 649 | if(sepaCount != 0){ |
Gaku0606 | 0:3e847864d796 | 650 | if(sepaCount % 2 == 0){ |
Gaku0606 | 0:3e847864d796 | 651 | servo = 35.0 + zeroAngle; |
Gaku0606 | 0:3e847864d796 | 652 | servo2 = 35.0 + zeroAngle; |
Gaku0606 | 0:3e847864d796 | 653 | } |
Gaku0606 | 0:3e847864d796 | 654 | else if(sepaCount % 2 == 1){ |
Gaku0606 | 0:3e847864d796 | 655 | servo = 25.0 + zeroAngle; |
Gaku0606 | 0:3e847864d796 | 656 | servo2 = 25.0 + zeroAngle; |
Gaku0606 | 0:3e847864d796 | 657 | } |
Gaku0606 | 0:3e847864d796 | 658 | } |
Gaku0606 | 0:3e847864d796 | 659 | //ドラッグシュート分離機構が作動したか (これは常に確認する |
Gaku0606 | 0:3e847864d796 | 660 | /*if(detectSepaFlag1 == 1){ |
Gaku0606 | 0:3e847864d796 | 661 | flightPinSeparationFlag = (flightPinSeparationFlag & 0b11000111) | 0b00111000;//2bit目を1に |
Gaku0606 | 0:3e847864d796 | 662 | Print("Succeeded Drogue Separation!!\r\n"); |
Gaku0606 | 0:3e847864d796 | 663 | Print("Finished Controling Servo Motor\r\n"); |
Gaku0606 | 0:3e847864d796 | 664 | pc.printf("Succeeded Drogue Separation!!\r\n"); |
Gaku0606 | 0:3e847864d796 | 665 | pc.printf("Finished Controling Servo Motor\r\n"); |
Gaku0606 | 0:3e847864d796 | 666 | }*/ |
Gaku0606 | 0:3e847864d796 | 667 | |
Gaku0606 | 0:3e847864d796 | 668 | if(sepaCount > 24){//2秒間経過 |
Gaku0606 | 0:3e847864d796 | 669 | mainParaSepaFlag = 1; |
Gaku0606 | 0:3e847864d796 | 670 | drogueSepaFlag = 0;//ドラッグシュート分離を停止. |
Gaku0606 | 0:3e847864d796 | 671 | /*if(detectSepaFlag1 == 0){//2秒間サーボを動かして,だめだったとき |
Gaku0606 | 0:3e847864d796 | 672 | //pc.printf("Separation2 %f [s]\r\n", innerTime.read()); |
Gaku0606 | 0:3e847864d796 | 673 | flightPinSeparationFlag = (flightPinSeparationFlag & 0b11000111) | 0b00110000; |
Gaku0606 | 0:3e847864d796 | 674 | drogueSepaFlag = 0; |
Gaku0606 | 0:3e847864d796 | 675 | Print("Failed Drogue Separation...\r\n"); |
Gaku0606 | 0:3e847864d796 | 676 | pc.printf("Failed Drogue Separation...\r\n"); |
Gaku0606 | 0:3e847864d796 | 677 | //mainParaSepaFlag = 1;//強制メインパラ分離 |
Gaku0606 | 0:3e847864d796 | 678 | Print("Finished Controling Servo Motor\r\n"); |
Gaku0606 | 0:3e847864d796 | 679 | pc.printf("Finished Controling Servo Motor\r\n"); |
Gaku0606 | 0:3e847864d796 | 680 | }*/ |
Gaku0606 | 0:3e847864d796 | 681 | pc.printf("Finished Controling Servo Motor\r\n"); |
Gaku0606 | 0:3e847864d796 | 682 | } |
Gaku0606 | 0:3e847864d796 | 683 | } |
Gaku0606 | 0:3e847864d796 | 684 | } |
Gaku0606 | 0:3e847864d796 | 685 | |
Gaku0606 | 0:3e847864d796 | 686 | if(mainParaSepaFlag == 1){ |
Gaku0606 | 0:3e847864d796 | 687 | flightPinSeparationFlag = flightPinSeparationFlag | 0b00000111; |
Gaku0606 | 0:3e847864d796 | 688 | pc.printf("Separation2 %f [s]\r\n", innerTime.read()); |
Gaku0606 | 0:3e847864d796 | 689 | Print("Try Main Separation!!"); |
Gaku0606 | 0:3e847864d796 | 690 | pc.printf("Try Main Separation!!\r\n"); |
Gaku0606 | 0:3e847864d796 | 691 | nicrom.autoStop(5.0f); |
Gaku0606 | 0:3e847864d796 | 692 | mainParaSepaFlag = 0; |
Gaku0606 | 0:3e847864d796 | 693 | Print("Finished Nicrom Control"); |
Gaku0606 | 0:3e847864d796 | 694 | pc.printf("Finished Nicrom Control\r\n"); |
Gaku0606 | 0:3e847864d796 | 695 | break; |
Gaku0606 | 0:3e847864d796 | 696 | } |
Gaku0606 | 0:3e847864d796 | 697 | |
Gaku0606 | 0:3e847864d796 | 698 | //SD保存 |
Gaku0606 | 0:3e847864d796 | 699 | |
Gaku0606 | 0:3e847864d796 | 700 | if(sdSaveFlag == 1){ |
Gaku0606 | 0:3e847864d796 | 701 | sdWriteLed = 1; |
Gaku0606 | 0:3e847864d796 | 702 | sdSaveFlag = 0; |
Gaku0606 | 0:3e847864d796 | 703 | temp_time = innerTime.read_us(); |
Gaku0606 | 0:3e847864d796 | 704 | fp = fopen(datafile, "ab");//14 |
Gaku0606 | 0:3e847864d796 | 705 | if(fp != NULL){ |
Gaku0606 | 0:3e847864d796 | 706 | for(int i = 0; i < 6;i++){ |
Gaku0606 | 0:3e847864d796 | 707 | sdBuff[i] = imu[i]; |
Gaku0606 | 0:3e847864d796 | 708 | } |
Gaku0606 | 0:3e847864d796 | 709 | for(int i = 0;i < 3;i++){ |
Gaku0606 | 0:3e847864d796 | 710 | sdBuff[i+6] = mag[i]; |
Gaku0606 | 0:3e847864d796 | 711 | } |
Gaku0606 | 0:3e847864d796 | 712 | sdBuff[9] = myQ.x; sdBuff[10] = myQ.y; sdBuff[11] = myQ.z; sdBuff[12] = myQ.w; sdBuff[13] = pressure; |
Gaku0606 | 0:3e847864d796 | 713 | fwrite(&temp_time, sizeof(int), 1, fp); |
Gaku0606 | 0:3e847864d796 | 714 | fwrite(&flightPinSeparationFlag, sizeof(char), 1, fp); |
Gaku0606 | 0:3e847864d796 | 715 | fwrite(sdBuff, sizeof(double), 14, fp); |
Gaku0606 | 0:3e847864d796 | 716 | fclose(fp); |
Gaku0606 | 0:3e847864d796 | 717 | } |
Gaku0606 | 0:3e847864d796 | 718 | sdWriteLed = 0; |
Gaku0606 | 0:3e847864d796 | 719 | } |
Gaku0606 | 0:3e847864d796 | 720 | } |
Gaku0606 | 0:3e847864d796 | 721 | temp_time = innerTime.read_ms(); |
Gaku0606 | 0:3e847864d796 | 722 | while(1){ |
Gaku0606 | 0:3e847864d796 | 723 | nine.getGyroAcc(imu);//慣性データ取得 |
Gaku0606 | 0:3e847864d796 | 724 | nine.getMag(mag);//地磁気データ取得 |
Gaku0606 | 0:3e847864d796 | 725 | attitude.MadgwickAHRSupdate(imu[0]*DEG_TO_RAD, imu[1]*DEG_TO_RAD, imu[2]*DEG_TO_RAD, imu[3], imu[4], imu[5], mag[0], mag[1], mag[2]);//姿勢推定 |
Gaku0606 | 0:3e847864d796 | 726 | attitude.getAttitude(&myQ); //姿勢をクォータニオンで取得 |
Gaku0606 | 0:3e847864d796 | 727 | if(pressureGetFlag){ |
Gaku0606 | 0:3e847864d796 | 728 | pressureGetFlag = 0; |
Gaku0606 | 0:3e847864d796 | 729 | lps25h.GetPress(&pressure, &pressureRaw); |
Gaku0606 | 0:3e847864d796 | 730 | } |
Gaku0606 | 0:3e847864d796 | 731 | if(abs(innerTime.read_ms() - temp_time) > 30000){ |
Gaku0606 | 0:3e847864d796 | 732 | break; |
Gaku0606 | 0:3e847864d796 | 733 | } |
Gaku0606 | 0:3e847864d796 | 734 | } |
Gaku0606 | 0:3e847864d796 | 735 | Print("Phase II END"); |
Gaku0606 | 0:3e847864d796 | 736 | pc.printf("Phase II END\r\n"); |
Gaku0606 | 0:3e847864d796 | 737 | /*========================================================================== |
Gaku0606 | 0:3e847864d796 | 738 | フェーズⅢ < 回収待機 > |
Gaku0606 | 0:3e847864d796 | 739 | ==========================================================================*/ |
Gaku0606 | 0:3e847864d796 | 740 | Print("Phase III START"); |
Gaku0606 | 0:3e847864d796 | 741 | pc.printf("Phase III START"); |
Gaku0606 | 0:3e847864d796 | 742 | phaseNumber = 3; |
Gaku0606 | 0:3e847864d796 | 743 | downlinkCount = 0; |
Gaku0606 | 0:3e847864d796 | 744 | |
Gaku0606 | 0:3e847864d796 | 745 | temp_time = innerTime.read_ms(); |
Gaku0606 | 0:3e847864d796 | 746 | while(1){ |
Gaku0606 | 0:3e847864d796 | 747 | nine.getGyroAcc(imu);//慣性データ取得 |
Gaku0606 | 0:3e847864d796 | 748 | nine.getMag(mag);//地磁気データ取得 |
Gaku0606 | 0:3e847864d796 | 749 | attitude.MadgwickAHRSupdate(imu[0]*DEG_TO_RAD, imu[1]*DEG_TO_RAD, imu[2]*DEG_TO_RAD, imu[3], imu[4], imu[5], mag[0], mag[1], mag[2]);//姿勢推定 |
Gaku0606 | 0:3e847864d796 | 750 | attitude.getAttitude(&myQ); //姿勢をクォータニオンで取得 |
Gaku0606 | 0:3e847864d796 | 751 | if(pressureGetFlag == 1){ |
Gaku0606 | 0:3e847864d796 | 752 | pressureGetFlag = 0; |
Gaku0606 | 0:3e847864d796 | 753 | lps25h.GetPress(&pressure, &pressureRaw); |
Gaku0606 | 0:3e847864d796 | 754 | } |
Gaku0606 | 0:3e847864d796 | 755 | if(abs(innerTime.read_ms() - temp_time) > 5000){ |
Gaku0606 | 0:3e847864d796 | 756 | pc.printf("%f\t%f\t%f\t%f\r\n",innerTime.read(), gps.Longitude(), gps.Latitude(), pressure); |
Gaku0606 | 0:3e847864d796 | 757 | temp_time = innerTime.read_ms(); |
Gaku0606 | 0:3e847864d796 | 758 | } |
Gaku0606 | 0:3e847864d796 | 759 | } |
Gaku0606 | 0:3e847864d796 | 760 | } |