ジャイロ補正を追加したプログラム
Dependencies: mbed YKNCT_Movement SBDBT BNO055 YKNCT_MD YKNCT_I2C
main.cpp
- Committer:
- yoshikawaryota
- Date:
- 2020-03-14
- Revision:
- 1:b9f698be841c
- Parent:
- 0:9e851dc42cde
File content as of revision 1:b9f698be841c:
/** ******************************************************************************** * @file main.c * @author You * @version V?.?.? * @date Today * @brief メインファイル ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include <main.h> /* 型定義 --------------------------------------------------------------------*/ /* ロボットの加速度 */ ROCATION NowAcc; /* ロボットの座標 */ ROCATION NowLoc; /* 定数定義 ------------------------------------------------------------------*/ /* マクロ定義 ----------------------------------------------------------------*/ /* 関数プロトタイプ宣言 -------------------------------------------------------*/ /* タイマ呼び出し用 */ void IT_CallBack(void); /* 自己位置推定処理 */ void LocEstimate(void); /* 変数定義 ------------------------------------------------------------------*/ /* 操作権 0…なし 1…手動 2…自動 */ int operate=0; /* 自動シーケンス */ int auto_mode=0; /* 直読みエンコーダ角度保存(degree) */ double EncoderDeg[EncoderMAX] = {0}; /* 足回り値保存変数 */ int MovMotor[4]={0}; /* 自動yaw補整目標角度 */ double TarTheta=0; /* 補正値用定数 */ int cor=4; /* クラス定義 ----------------------------------------------------------------*/ /* 割り込み用クラス */ Ticker flipper; /* gyro用タイマ */ Timer yawCnt; /* UART (Tx,Rx) */ Serial telemetry(USBTX, USBRX, 115200); /* コントローラー */ SBDBT DS3(PA_0, PA_1, 9600); /* オンボードLED */ DigitalOut led(LED2); /* USERボタン */ DigitalIn UB(PC_13,PullDown); /* エンコーダーピン CS */ DigitalOut CS[] = {PA_2,PA_3}; DigitalOut CL[] = {PA_4,PA_5}; DigitalIn DO[] = {PA_6,PA_7}; /* 足回り動作クラス定義 */ Move omuni(MovMotor,NowLoc.theta); /* I2C MDのクラス定義 */ YKNCT_MD_I2C MD(PB_9,PB_8); /* ジャイロのピン設定 */ BNO055 bno(PB_9, PB_8); /*----------------------------------- main ----------------------------------*/ int main() { telemetry.printf("\n\rMainStart"); /* 割り込みの設定 * IT_CallBack関数を0.1msで割り込み */ flipper.attach_us(&IT_CallBack, 100); /* ジャイロの設定 */ bno.setmode(OPERATION_MODE_IMUPLUS); /* I2CMDの設定 */ MD.Init(0,MD_SMB); MD.Init(1,MD_SMB); MD.Init(2,MD_SMB); MD.Init(3,MD_SMB); telemetry.printf("\n\rMainLoopStart"); /* メインループ --------------------------------------------------------------*/ while(1) { /* オンボードLED点滅 */ led=!led; /* 表示改行 */ telemetry.printf("\n\r"); /* 自動処理関連テレメトリ */ telemetry.printf("ope:%d ",operate); /* 座標テレメトリ */ telemetry.printf("X:%4.0f Y:%4.0f T:%4.0f ",NowLoc.X,NowLoc.Y,NowLoc.theta); /* 自己位置推定更新 */ LocEstimate(); /* I2CMD実行 */ MD.Exe(); /* タイマ-スタート */ yawCnt.start(); /* タイマーリセット */ yawCnt.reset(); /* 操縦権変更 ×停止 △手動 〇自動 */ if(DS3.CROSS) operate=0; if(DS3.TRIANGLE) operate=1; if(DS3.CIRCLE) operate=2; /* 操縦権:なし 停止動作 */ if(operate==0){ /* 足回り停止 */ omuni.XmarkOmni_Move(0,0,0); for (int i = 0; i < 4; i++) { MD.Set(i,MovMotor[i]); } } /* 操縦権:手動 */ else if(operate==1){ /* 足回り手動動作 */ int x_val = (double)(DS3.LX-64)*100/64; int y_val = (double)(64-DS3.LY)*100/64; int r_val = (double)(DS3.RX-64)*100/64; /* 目標角更新 */ if(DS3.RX!=64) yawCnt.reset(); if(yawCnt.read_ms()<1000) TarTheta=NowLoc.theta; /* gyro値による補正 */ r_val += (TarTheta-NowLoc.theta)*cor; omuni.XmarkOmni_Move(x_val,y_val,r_val); for (int i = 0; i < 4; i++) { MD.Set(i,MovMotor[i]); } } /* 操縦権:自動 */ else if(operate==2){ switch(auto_mode){ /* スタート待機処理 */ case 0: /* オンボードSWで次のステップに */ if(UB) auto_mode++; break; /* 〇〇の処理 */ case 1: /* 〇〇の時次のステップに */ if(1) auto_mode++; break; /* 終了処理 */ default: auto_mode=0; operate=0; break; } } } } /******************************************************************************* * @概要 自己位置推定関数 * @引数 なし * @返り値 なし *******************************************************************************/ void LocEstimate(void){ static double GyroDeg[2]={0}; static double EncDeg[2][2]={0}; static double disp[3]={0}; /* ジャイロの値取得 */ bno.get_angles(); GyroDeg[1]=GyroDeg[0]; GyroDeg[0]=bno.euler.yaw; if(GyroDeg[0]!=0) { /* 359→0を跨いだ時,前回の値を0から逆回転で負の値で表記 */ if(GyroDeg[1]<90 && GyroDeg[0]>270) GyroDeg[1]+=360; /* 0→359を跨いだ時,前回の値を360以上の値で表記 */ else if(GyroDeg[1]>270 && GyroDeg[0]<90) GyroDeg[1]-=360; /* 差を求める*/ disp[2]=GyroDeg[1]-GyroDeg[0]; } /* Enc2つの差分求める */ for(int i=0;i<2;i++){ EncDeg[i][1]=EncDeg[i][0]; EncDeg[i][0]=EncoderDeg[i]; disp[i]=EncDeg[i][1]-EncDeg[i][0]; } /* 差分を加速度として保存 */ NowAcc.theta = disp[2]; NowAcc.X = disp[0] * cos(NowLoc.theta) + disp[1] * sin(NowLoc.theta)+200*disp[2]; NowAcc.Y = -disp[0] * sin(NowLoc.theta) + disp[1] * cos(NowLoc.theta)+200*disp[2]; /* 差分を累積して現在位置を保存 */ NowLoc.X += NowAcc.X; NowLoc.Y += NowAcc.Y; NowLoc.theta += NowAcc.theta; } /* 割り込み(100us) *************************************************************/ void IT_CallBack(void) { static int cnt = 0; static int data[EncoderMAX] = {0}; static double EncDeg[EncoderMAX][2] = {0}; for(int i=0;i<EncoderMAX;i++) switch(cnt){ /* 最初の処理 */ case 0: data[i] = 0; CS[i] = 0; CL[i] = 1; break; /* 最後の処理 */ case 25: CS[i]=1; /* 前回の値更新 今回の値更新(エンコーダの値(0~4096)を角度(0~360)に) */ EncDeg[i][1] = EncDeg[i][0]; EncDeg[i][0] = (double)data[i] * 360.0 / 4096; /* 359→0を跨いだ時,前回の値を0から逆回転で負の値で表記 */ if ((270 <= EncDeg[i][1]) && (EncDeg[i][0] < 90)) EncDeg[i][1] -= 360; /* 0→359を跨いだ時,前回の値を360以上の値で表記 */ else if ((EncDeg[i][1] < 90) && (270 <= EncDeg[i][0])) EncDeg[i][1] += 360; /* 差を求める*/ EncoderDeg[i] += EncDeg[i][0] - EncDeg[i][1]; break; /* 通常の処理 */ default: CL[i]=!CL[i]; /* 最初でも最後でもなく奇数回で最初以外の時読み取り処理 */ if(cnt != 1 && cnt % 2){ data[i] |= (DO[i]==1); data[i] = data[i] << 1; } break; } cnt++; cnt%=26; }