a

Dependencies:   mbed

main.cpp

Committer:
Tom0108
Date:
2019-08-23
Revision:
4:236e5c58e8ee
Parent:
3:1063aa133b62
Child:
5:fcc79e507610

File content as of revision 4:236e5c58e8ee:

/*今日 やること*/

/******************************************************************************/
#include "main.h"
//#include "gyro.h"
#include <math.h>

/******************************************************************************/
#define CIRCLE sbdbt.CIRCLE
#define SQUARE sbdbt.SQUARE
#define CROSS  sbdbt.CROSS
#define TRIANGLE  sbdbt.TRIANGLE
#define LEFTkey  sbdbt.LEFTkey
#define RIGHTkey  sbdbt.RIGHTkey
#define UPkey  sbdbt.UPkey
#define DOWNkey  sbdbt.DOWNkey

/******************************************************************************/

/* 型定義 --------------------------------------------------------------------*/

MD_I2C_Data_TypeDef MD_Data[Motor_MAX] = {
    { 8, 0, 0, 0, {0}},     //足回り
    { 9, 1, 0, 0, {0}},
    {10, 0, 0, 0, {0}},
    {11, 1, 0, 0, {0}},
    {12, 0, 0, 0, {0}},     // 洗濯物回収
    {13, 1, 0, 0, {0}},     // 上下機構
    {14, 0, 0, 0, {0}},     // 洗濯物排出
    {15, 1, 0, 0, {0}}      // 左右移動
};

IN_I2C_Data_TypeDef In_Data[] = {
    {1,0,0},        // 洗濯物排出(初期位置)
    {1,1,0},        // 洗濯物排出(停止)
    {1,2,0},        // 腕(最大  タオル)
    {1,3,0},         // 腕(初期位置)
    {3,0,0},        // 上下機構(上)
    {3,1,0},        //        (下)
    {3,2,0},         // 腕(シーツ兼シャツ)
};

OUT_I2C_Data_TypeDef Out_Data[] = {
    {0,0,0},        // 腕の上下
    {0,1,0},        // 爪
    {0,2,0},        // タオルの先
    {0,3,0},        // タオル展開
    {1,0,0},        // タオルの中央
};
/* 関数宣言 ------------------------------------------------------------------*/
void mecanum_Move(void);
void mecanum_Turn(void);
void mecanum_Stop(void);

/* 変数宣言 ------------------------------------------------------------------*/
//かご回転用
int kago=0, kago_f=0;

//コントローラーの状態を保存するため
int once=0;

//タオル引く用
int pull=0, pull_f=0;

//タオル掴む用
//sgrab_f: 中央のリミットでつかむ
int grab=0, grab_f=0, sgrab_f=0;

//タオル横展開用
int unfold_f=0;

//90度回転のフラグ
int left_f=0, right_f=0;

//y_deg: 起動時から絶対の角度
//yaw: 相対角 初期状態が0になるようにする
//offset: 初期状態を0にするために引く値
double y_deg, offset;
int yaw=0;

//Turn_val: 補正の目標値
//dif_val: 補正値との差
double Turn_val, dif_val;

//short_lim: 腕中央
//max_lim: 腕奥側
//short_lim: 腕手前側
int short_lim, max_lim, start_lim;

//機体の前方を変更する
int dir=0;

int limit_up,limit_down;            // リミットスイッチ
int slide_start,slide_stop;     //かごのリミット

int lx,ly,rx,L,R;        // 足回り
int g;

int as=0;

/*クラス宣言-------------------------------------------------------------------*/
Ticker flipper1;                 // 割込み
Y_I2C i2c(PB_9, PB_8);           // I2C
DigitalOut myled(LED1);          // オンボードLED
SBDBT sbdbt(PA_0, PA_1, 9600);   // SDBDT
MyMPU6050 mpu(PC_9, PA_8);       // ジャイロセンサ

DigitalOut blue(PA_10);
DigitalOut green(PB_4);
DigitalOut red(PB_5);

//半自動の時に使う
Timer tim;

/*----------------------------------- main -----------------------------------*/
/* @brief  メインプログラム
* @param  なし
* @retval なし
*/
int main()
{
    //flipper1.attach(&flip1, 0.001);    // 割り込み
    while(1) {
        //自動系のタイマースタート
        tim.start();
        mpu.loop();
        if(sbdbt.State_check()) {

            for(int i=0; i<7; i++) i2c.In(In_Data,i);

//            y_deg = (double)mpu.ypr[0] * 180 / M_PI;
//            yaw = offset-y_deg;
            yaw=90*dir;
            yaw%=360;
            dif_val = y_deg-Turn_val;

            lx = ((64-sbdbt.LY)*100.0/64)*sin(yaw*M_PI/180)+((sbdbt.LX-64)*100.0/64)*cos(yaw*M_PI/180);
            ly = ((64-sbdbt.LY)*100.0/64)*cos(yaw*M_PI/180)-((sbdbt.LX-64)*100.0/64)*sin(yaw*M_PI/180);
            rx = (sbdbt.RX - 64)*100/64;
            L = lx+ly;
            R = ly-lx;

            if(sbdbt.LX !=64 || sbdbt.LY !=64) {

                mecanum_Move();

                // 以下,ジャイロセンサーのプログラム
                if(g) {
                    if(abs(ly) > 10) {
                        if(ly>10) {
                            (MD_Data+0)->PWMVal = MD_GET_PWM(MD_Data,0)-dif_val;
                            (MD_Data+1)->PWMVal = MD_GET_PWM(MD_Data,1)+dif_val;
                        } else {
                            (MD_Data+0)->PWMVal = MD_GET_PWM(MD_Data,0)+dif_val;
                            (MD_Data+1)->PWMVal = MD_GET_PWM(MD_Data,1)-dif_val;
                        }
                    }

                    if(abs(lx) > 10) {
                        if(lx>10) {
                            (MD_Data+0)->PWMVal = MD_GET_PWM(MD_Data,0)-dif_val;
                            (MD_Data+2)->PWMVal = MD_GET_PWM(MD_Data,2)+dif_val;
                        } else {
                            (MD_Data+0)->PWMVal = MD_GET_PWM(MD_Data,0)+dif_val;
                            (MD_Data+2)->PWMVal = MD_GET_PWM(MD_Data,2)-dif_val;
                        }
                    }

                    if((abs(ly)-abs(lx)) > 0) {
                        (MD_Data+2)->PWMVal = MD_GET_PWM(MD_Data,0);
                        (MD_Data+3)->PWMVal = MD_GET_PWM(MD_Data,1);
                    } else {
                        (MD_Data+1)->PWMVal = MD_GET_PWM(MD_Data,0);
                        (MD_Data+3)->PWMVal = MD_GET_PWM(MD_Data,2);
                    }
                }     // if(g)
            }// if(LX !=64 || LY !=64)
            else if(sbdbt.RX != 64) {         // 旋回
                Turn_val=y_deg;
                mecanum_Turn();
            } else {
                mecanum_Stop();
            }

            // 90°旋回
            if(left_f) {
                if(abs(yaw)<60) {
                    for(int i=0; i<4; i++) {
                        MD_SET_PWM(MD_Data, i,60);
                        MD_SET_DRIVE(MD_Data, i,MD_REVERSE);
                    }
                } else {
                    left_f=0;
                    Turn_val=y_deg;
                    mecanum_Stop();
                }
            }
            if(right_f) {
                if(yaw>-60) {
                    for(int i=0; i<4; i++) {
                        MD_SET_PWM(MD_Data, i,60);
                        MD_SET_DRIVE(MD_Data, i,MD_FORWARD);
                    }
                } else {
                    right_f=0;
                    Turn_val=y_deg;
                    mecanum_Stop();
                }
            }

            /*---ハンガーかけるやつ----------------------------------------------*/
            if(sbdbt.SELECT)as=1;//selectキー

            if(as==1 && limit_up == 0) {
                MD_SET_DRIVE(MD_Data, 5,MD_REVERSE);
                MD_SET_PWM(MD_Data, 5,50);
            } else if(UPkey && limit_up == 0) {
                as=0;
                MD_SET_DRIVE(MD_Data, 5,MD_REVERSE);
                MD_SET_PWM(MD_Data, 5,50);
            } else if(as==1 && limit_up == 1) {
                as=0;
                MD_SET_PWM(MD_Data,5,0);
                MD_SET_DRIVE(MD_Data, 5,MD_BRAKE);
            } else if(DOWNkey && limit_down == 0) {
                MD_SET_DRIVE(MD_Data, 5,MD_FORWARD);
                MD_SET_PWM(MD_Data, 5,50);
            } else {
                MD_SET_PWM(MD_Data,5,0);
                MD_SET_DRIVE(MD_Data, 5,MD_BRAKE);
            }

            //タオルつかむ 四角
            if(grab_f || sgrab_f) {
                switch(grab) {
                    //腕を前に動かす
                    case 0:
                        //爪開く
                        i2c.Out_Set(Out_Data,1,1);
                        MD_SET_DRIVE(MD_Data,4,MD_REVERSE);
                        MD_SET_PWM(MD_Data,4,40);
                        if((sgrab_f && short_lim) || max_lim==1) {
                            grab++;
                            tim.reset();
                        }
                        break;

                    case 1:
                        //腕停止
                        MD_SET_DRIVE(MD_Data,4,MD_BRAKE);
                        MD_SET_PWM(MD_Data,4,0);

                        //腕おろす
                        i2c.Out_Set(Out_Data,0,1);
                        if(tim.read_ms()>300) {
                            grab++;
                            tim.reset();
                        }
                        break;

                    case 2:
                        //爪閉じる
                        i2c.Out_Set(Out_Data,1,0);
                        if(tim.read_ms()>100) {
                            grab++;
                            tim.reset();
                        }
                        break;

                    case 3:
                        //腕上げる
                        i2c.Out_Set(Out_Data,0,0);
                        if(tim.read_ms()>300) {
                            grab++;
                            tim.reset();
                        }
                        break;

                    case 4:
                        MD_SET_DRIVE(MD_Data,4,MD_FORWARD);
                        MD_SET_PWM  (MD_Data,4,60);
                        if(start_lim==1) {
                            grab_f=0;
                            sgrab_f=0;
                        }
                        break;
                }
            } //if(grab_f)

            //タオル引く 丸
            else if(pull_f) {
                switch(pull) {
                    //腕を前に動かす
                    case 0:
                        //爪閉じる
                        i2c.Out_Set(Out_Data,1,0);
                        MD_SET_DRIVE(MD_Data,4,MD_REVERSE);
                        MD_SET_PWM  (MD_Data,4,60);
                        if(max_lim==1) {
                            pull++;
                            tim.reset();
                        }
                        break;

                    case 1:
                        //腕停止
                        MD_SET_DRIVE(MD_Data,4,MD_BRAKE);
                        MD_SET_PWM  (MD_Data,4,0);

                        //腕おろす
                        i2c.Out_Set(Out_Data,0,1);
                        if(tim.read_ms()>300) {
                            pull++;
                            tim.reset();
                        }
                        break;

                    case 2:
                        if(tim.read_ms()>300) {
                            pull++;
                            tim.reset();
                        }
                        break;

                    case 3:
                        MD_SET_DRIVE(MD_Data,4,MD_FORWARD);
                        MD_SET_PWM  (MD_Data,4,60);
                        if(start_lim==1) pull_f=0;
                        break;
                }
            } //if(pull_f)

            //かごを倒す
            else if(kago_f) {
                //腕の先を閉じておく
                i2c.Out_Set(Out_Data,1,0);

                switch(kago) {
                    //腕を前に動かす
                    case 0:
                        MD_SET_DRIVE(MD_Data,4,MD_REVERSE);
                        MD_SET_PWM  (MD_Data,4,60);
                        if(max_lim==1) {
                            kago++;
                            tim.reset();
                        }
                        break;

                    case 1:
                        //腕停止
                        MD_SET_DRIVE(MD_Data,4,MD_BRAKE);
                        MD_SET_PWM  (MD_Data,4,0);

                        //かご回転
                        MD_SET_DRIVE(MD_Data,6,MD_FORWARD);
                        MD_SET_PWM  (MD_Data,6,80);
                        if(slide_stop==1 || tim.read_ms()>3000) {
                            kago++;
                            tim.reset();
                            MD_SET_DRIVE(MD_Data,6,MD_BRAKE);
                            MD_SET_PWM  (MD_Data,6,0);
                        }
                        break;

                    case 2:
                        if(tim.read_ms()>1000) {
                            kago++;
                            tim.reset();
                        }
                        break;

                    case 3:
                        MD_SET_DRIVE(MD_Data,6,MD_REVERSE);
                        MD_SET_PWM  (MD_Data,6,80);
                        if(slide_start==1 || tim.read_ms()>3000) kago++;
                        break;

                    case 4:
                        MD_SET_DRIVE(MD_Data,4,MD_FORWARD);
                        MD_SET_PWM  (MD_Data,4,60);
                        if(start_lim==1)    kago_f=0;
                        break;
                }
            } else {
                //かごと腕を停止
                MD_SET_DRIVE(MD_Data,4,MD_BRAKE);
                MD_SET_PWM  (MD_Data,4,0);
                MD_SET_DRIVE(MD_Data,6,MD_BRAKE);
                MD_SET_PWM  (MD_Data,6,0);

                //爪開く
                i2c.Out_Set(Out_Data,1,1);
                //腕上げる
                i2c.Out_Set(Out_Data,0,0);

                kago=0;
                pull=0;
                grab=0;

                tim.reset();
            }

            //-------------- 出力 --------------//
            //第二引数には使う最大の個数
            i2c.Out(Out_Data,5);

            //モータ出力
            for(int i=0; i<8; i++) i2c.MD_I2C(MD_Data,i);

            /* ----------- りみっと --------------- */
            limit_up    = (In_Data+4)->in_data;
            limit_down  = (In_Data+5)->in_data;
            max_lim  = (In_Data+1)->in_data;
            start_lim  =(In_Data+2)->in_data;
            short_lim = (In_Data+6)->in_data;
            slide_start  =  (In_Data+3)->in_data;
            slide_stop   =  (In_Data+0)->in_data;

            //半自動のデバック
//            pc.printf("pull %2d%2d ",pull,pull_f);
//            pc.printf("grab %2d%2d ",grab,grab_f);
//            pc.printf("kago %2d%2d ",kago,kago_f);
//            pc.printf("deg:%f dif:%f ",y_deg,dif_val);
//            pc.printf("%2d ",dir);
            pc.printf("\n\r");


            /* --------------電磁弁系-------------------- */
            /*タオル掛け*/
            if(sbdbt.L2)i2c.Out_Set(Out_Data,2,1);
            else i2c.Out_Set(Out_Data,2,0);

            /*タオルを引っ張るやつ*/
            if(sbdbt.R2)i2c.Out_Set(Out_Data,4,1);
            else i2c.Out_Set(Out_Data,4,0);

            if(unfold_f)i2c.Out_Set(Out_Data,3,1);
            else i2c.Out_Set(Out_Data,3,0);


            /* ----------------ボタン系--------------- */
            //補正角リセット
            if(sbdbt.L1) {
                Turn_val=y_deg;
                offset=y_deg;
            }
            //90度回転して補正の角度を固定する
            if(LEFTkey) {
                if(once==0) {
                    dir++;
//                    left_f++;
//                    left_f%=2;
                    once++;
                }
            } else if(RIGHTkey) {
                if(once==0) {
                    dir--;
//                    right_f++;
//                    right_f%=2;
                    once++;
                }
            }
            //かごを倒す
            else if(CROSS) {
                if(once==0) {
                    kago_f++;
                    kago_f%=2;
                    once++;
                }
            }
            //タオルを掴んで動かす
            else if(SQUARE) {
                if(once==0) {
                    grab_f++;
                    grab_f%=2;
                    once++;
                }
            } else if(TRIANGLE) {
                if(once==0) {
                    sgrab_f++;
                    sgrab_f%=2;
                    once++;
                }
            }
            //倒すを引いて動かす
            else if(CIRCLE) {
                if(once==0) {
                    pull_f++;
                    pull_f%=2;
                    once++;
                }
            }
            //タオル展開用
            else if(sbdbt.START) {
                if(once==0) {
                    unfold_f++;
                    unfold_f%=2;
                    once++;
                }
            } else once=0;


        }    // if(sbdbt.State_check())
    }     // while(1)
}       // int main()

/* メカナムの基本移動 */
void mecanum_Move(void)
{
    int val1,val2;

    MD_SET_DRIVE(MD_Data, 0,(L > 0) ? MD_FORWARD : MD_REVERSE);
    MD_SET_DRIVE(MD_Data, 1,(R > 0) ? MD_REVERSE : MD_FORWARD);
    MD_SET_DRIVE(MD_Data, 2,(R > 0) ? MD_FORWARD : MD_REVERSE);
    MD_SET_DRIVE(MD_Data, 3,(L > 0) ? MD_REVERSE : MD_FORWARD);

    val1 = (int)sqrt( 1.0*abs( abs(lx)*lx + abs(ly)*ly ) );
    val2 = (int)sqrt( 1.0*abs( abs(ly)*ly - abs(lx)*lx ) );

    MD_SET_PWM(MD_Data,0,val1);
    MD_SET_PWM(MD_Data,1,val2);
    MD_SET_PWM(MD_Data,2,val2);
    MD_SET_PWM(MD_Data,3,val1);


    if(MD_GET_PWM(MD_Data,0)*2 < MD_GET_PWM(MD_Data,1) ) {
        MD_SET_PWM(MD_Data, 0, 0);
        g = 0;
    } else if(  MD_GET_PWM(MD_Data,1)*2 < MD_GET_PWM(MD_Data,0) ) {
        MD_SET_PWM(MD_Data, 1, 0);
        g = 0;
    }

    // 斜めじゃないなら大きいほうにPWMをそろえて完全縦横移動
    else if( MD_GET_PWM(MD_Data,0) < MD_GET_PWM(MD_Data,1) ) {
        MD_SET_PWM(MD_Data, 0, MD_GET_PWM(MD_Data,1));
        g = 1;

    } else {
        MD_SET_PWM(MD_Data, 1, MD_GET_PWM(MD_Data,0));
        g = 1;
    }

    MD_SET_PWM(MD_Data, 2, MD_GET_PWM(MD_Data,1));
    MD_SET_PWM(MD_Data, 3, MD_GET_PWM(MD_Data,0));

}

/* メカナム旋回 */
void mecanum_Turn(void)
{
    for(int i=0; i<4; i++) {
        MD_SET_PWM(MD_Data, i,sbdbt.R1?abs(sbdbt.RX - 64)*50/64:abs(sbdbt.RX - 64)*100/64);
        MD_SET_DRIVE(MD_Data, i,(sbdbt.RX < 64)? MD_REVERSE: MD_FORWARD);
    }
}

/* 停止 */
void mecanum_Stop(void)
{
    for(int i=0; i<4; i++) {
        MD_SET_PWM(MD_Data, i, 0);
        MD_SET_DRIVE(MD_Data, i, MD_BRAKE);
    }
}

/*操作法*/
/*
〇 ボタン  ==   回収(引きずる)
? ボタン  ==   籠
△ ボタン  ==   回収(シーツ兼シャツ)
□  ボタン  ==   回収(タオル)
上 ボタン  ==   ハンガーかけ機構 上昇
下 ボタン  ==   ハンガーかけ機構 下降
左 ボタン  ==   90回転
右 ボタン  ==   90回転
L1 ボタン  ==   リセット(足回り)
L2 ボタン  ==  タオル掛け
R1 ボタン  ==  押しながら回転でゆっくりになる
R2 ボタン  ==  タオルひっぱる奴
select     ==  ハンガー掛け 最大まで上昇
start      ==  ハンガー展開
*/
/*その他注意点*/
/*
動かすときはジャイロの値を安定させるため15秒から20秒待つ
メカナムは振動が大きいせいかナット等が外れやすいため、定期的に確認をする(特に足回り)
あまり急発進をさせない(たまに暴走)
暴走したときはコントローラーを動かしたら治るはず
コントローラー接続が切れたらSTMの黒い奴を押す(わからないときは近くの回路班へ)
*/