2

Dependencies:   AQM0802A HMC6352 PID Servo mbed

main.cpp

Committer:
lilac0112_1
Date:
2015-02-22
Revision:
2:de6958cb7072
Parent:
1:438016436d16

File content as of revision 2:de6958cb7072:

/***********************************
 *RoboCupJunior Soccer B Open 2014 
 *Koshinnestu progrum
 *
 * 
 * データからロボットの移動やキッカー等のモータの動作を決定する処理を行う
 *
 * MotorDriverにmaxonに命令
 * 
 * servoにステアリング指示
 * 
 * LCDでデバック
 *
 * スイッチ4つとスタートスイッチで処理を実行
 *  

 ************************* 
 *  Pin Map 
 *  
 *  p5~p8   >> InterruptIn >> LineSensor 
 *
 *  p9,p10  >> I2C         >> LPC1114FN28/102 read
 *
 *  p13,p14 >> Serial      >> Motor
 * 
 *  p21     >> PwmOut      >> Servo 
 *
 *  p22~p26 >> DigitalIn   >> DebugSw and StartSw 
 *
 *  p27,p28 >> I2C         >> DebugLCD
 *
 *  p29     >> DigitalOut  >> Kicker 
 *    
 *  **now , never use pin number p11,p12,p15,p16,p17,p18,p19,p20, p29,p30
 *
 *  will use kicker, any Pin set in DigitalOut  soon.
 *   
 *  
 ******************************/






#include "mbed.h"
#include "PID.h"
#include "AQM0802A.h"
#include "HMC6352.h"
#include "Servo.h"
#include "main.h"
#include <math.h>
#include <sstream>

/*回り込みの計算用*/
#define PI 3.1415926

/*LPC1114 I2C Slave Address*/
#define ADDRESS_R 0xAA
#define ADDRESS_L 0xC0

/*BusIn sw 入力値*/
#define Calibration 0x01
#define Kicker 0x02
#define Debug1 0x04
#define Debug2 0x08
#define StartS 0x10

/*send to LPC1114 ,receive data choice*/
#define READ_IR    0x01 
#define READ_PING  0x02




BusIn   Sw(p22,p23,p24,p25,p26);
BusIn   Line(p5,p6,p7,p8);//No reading line → 0b1111 ,not pull up
DigitalOut  Led[4] = {LED1,LED2,LED3,LED4};
DigitalOut  Kick(p29);

Servo       S555(p21);
I2C         Sensor(p9,p10);//sda,scl
HMC6352     hmc6352(p9,p10);//sda,scl
AQM0802A    Lcd(p28,p27);//sda,scl
Serial      Motor(p13,p14);//tx,rx
Serial      pc(USBTX,USBRX);

extern string StringFIN;
extern void array(int,int,int,int);

int speed[4] = {0};            

typedef enum {FRONT = 1, RIGHT, BACK, LEFT, NA} Direction;



uint8_t IrReceive(uint8_t IrData[]){
    /*
     *Irdata[0] : 1位,2位の場所(1位*13+2位)
     *Irdata[1] : 1位の値
     *return    : 1位の場所
     */
    char data_r[3],data_l[3];
    bool val;
    Sensor.write(READ_IR);//一斉送信のつもり
    
    val = Sensor.read(ADDRESS_R|1, data_r, 3);// IRデータを受信
    Led[0] = val;
    wait_ms(5);
    val = Sensor.read(ADDRESS_L|1, data_l, 3);
    Led[0] = !val;
    
    if((data_r[0] == 0)||(data_l[0] == 0)){/*ボールを検知しているかチェック*/
        if((data_r[0] == 0)&&(data_l[0] == 0)){
            IrData[0] = 12*13 + 12;
            return 12;
        }
        if(data_r[0] == 0){
            IrData[0] = (data_l[0]/6+6)*13 + (data_l[0]%6+6);  
            IrData[1] = data_l[1];
            return data_l[0]/6+6;
            
        }
        
        IrData[0] = (data_r[0]/6)*13 + (data_r[0]%6);  
        IrData[1] = data_r[1];
        return data_r[0]/6;
    }
    
    if(data_r[2]<data_l[2]){
        if(data_r[2]<data_l[1]){   
            IrData[0] = (data_r[0]/6)*13 + (data_r[0]%6);
            IrData[1] = data_r[1];
            return data_r[0]/6;
        }
         
        IrData[0] = (data_r[0]/6)*13 + (data_l[0]/6+6);
        IrData[1] = data_r[1];
        return data_r[0]/6;
        
    }else{
        if(data_l[2]<data_r[1]){   
            IrData[0] = (data_l[0]/6+6)*13 + (data_l[0]%6+6);
            IrData[1] = data_l[1];
            return (data_l[0]/6+6);
        }
         
        IrData[0] = (data_l[0]/6+6)*13 + (data_r[0]/6);
        IrData[1] = data_l[1];
        return (data_l[0]/6+6);      
    }
    
    
}

void PingReceiveRL(char ping[]){
    /*
     * ping[0] : Right ping data
     * ping[1] : Left  ping data
     */
    char ReadSelect[1] = {READ_PING};
    bool val;
    val = Sensor.write(ADDRESS_R|0, ReadSelect , 1);
    Led[2] = val;
    val = Sensor.read(ADDRESS_R|1, ping, 2);
    Led[2] = !val;
    
}

void PingReceiveFB(char ping[]){
    /*
     * ping[0] : FRONT ping data
     * ping[1] : BACK  ping data
     */
    char ReadSelect[1] = {READ_PING};
    bool val;
    val = Sensor.write(ADDRESS_L|0, ReadSelect , 1);
    Led[2] = val;
    val = Sensor.read(ADDRESS_L|1, ping, 2);
    Led[2] = !val;
    
    
}



void move(int vr, int vl){
    /**
     * pwm[1] : right wheel(+data = forward/ -data = backward)
     * pwm[2] : left  wheel(+data = forward/ -data = backward)
     * pwm[3] : not used
     * pwm[4] : not used
     *
     */
    
    double pwm[4] = {0};
    uint8_t i = 0;
    pwm[0] = -vr;
    pwm[1] = 0;
    pwm[2] = 0;
    pwm[3] = vl;

    for(i = 0; i < 4; i++){
            if(pwm[i] > 100){
                pwm[i] = 100;
            }else if(pwm[i] < -100){
                pwm[i] = -100;
            }
        speed[i] = pwm[i];
    }
}


void IrFrontAction(int *CompassDef , uint8_t IrMemo[])//ball 12 or 0 o-clock
{
/*前にボールがある場合の動作*/
    int Compass;
    char Ping[2];
    uint8_t Line,LineIr;
    unsigned int IrNumMax; 
    
    
    if(IrReceive(IrMemo)<=150){//適当な150
        /*ステッピングを正面に設定*/
        /*busy_wait()*/
        /*モーターを前進*/
        return;
    }
    PingReceiveRL(Ping);
    if((Ping[0]>90)&&(Ping[1]>40)){//数値は適当
        /*ステッピングを少しだけ傾ける*/
        /*モーターを左右差つけて回す(ロボットは少し傾く)*/
        /*busy_wait()*/
        /*モーターを前進*/
        while(1){
        
            if(Line){ //ラインを検知していないか
                //LineIr = Line & (IrReceiveS()/3 + 1);//計算により方位を合わせる。
                while(LineIr){
                    move(0,0);//
                    Led[1] = Led[2] = Led[3] = 1;  
                
                    //LineIr = LineReceive() & (IrReceiveS()/3 + 1);
                }
                Led[1] = Led[2] = Led[3] = 0;
                
                Compass = ((hmc6352.sample() / 10) + 540 - *CompassDef) % 360;
                while(!((Compass>=150)&&(Compass<=210))){
                    move(20,-20);//適当な回転。
                    Compass = ((hmc6352.sample() / 10) + 540 - *CompassDef) % 360;
                }
                return;
            }
            Kick = 1;
            wait_ms(200);
            Kick = 0;
            
            //IrNumMax = IrReceiveSM();//位置と大きさ
            
            if(!((IrNumMax&0x00)>>8) == 1){//この1はボールの関数の1を表す.
                Compass = ((hmc6352.sample() / 10) + 540 - *CompassDef) % 360;
                while(!((Compass>=150)&&(Compass<=210))){
                    move(20,-20);//適当な回転。
                    Compass = ((hmc6352.sample() / 10) + 540 - *CompassDef) % 360;
                }
                return;
            }    
            
            if((IrNumMax&0x00FF)<150){
                Compass = ((hmc6352.sample() / 10) + 540 - *CompassDef) % 360;
                while(!((Compass>=150)&&(Compass<=210))){
                    move(20,-20);//適当な回転。
                    Compass = ((hmc6352.sample() / 10) + 540 - *CompassDef) % 360;
                }
                return;
            }                    
            
        }
        
    }else if((Ping[0]>40)&&(Ping[1]>90)){
        
    }else{
        
    }
        
}

void IrBackAction(int *CompassDef , uint8_t IrMemo[])//ball found six o-clock
{
    /***
     * 6時にボールがある場合の処理.右と左のスペースを確認して広い方から回り込む
     *
     **/
     char Ping[2];
     
     PingReceiveRL(Ping);
     
    
    if(IrMemo[0] == 6){//check ir number
        return ;
    }
    if(Ping[0]<Ping[1]){
        /*右が大きい*/
        
        
        return;
    }
    /*左が大きい*/
    
    
    
    
    }
void GoHome(int *CompassDef , uint8_t IrMemo[])//Ball is not found.
{
    /*line検知をしないバージョン*/
    int Compass;
    char Ping[2] = {0};

     
    PingReceiveFB(Ping);
    if(Ping[1] >=60){//後ろからの距離60cm
        move(-20,-20);
        PingReceiveFB(Ping);
        return ;
    } 
        
    move(0,0);//stop
    
}


uint8_t SwRead(){
/******
 *retrun : sw_state
 *Calibration = 0x01;
 *Kicker = 0x02;
 *Debug1 = 0x04;
 *Debug2 = 0x08;
 *StartS = 0x10;
 *
 *****/
    uint8_t i,temp,temp2;
    temp = Sw;
    if(!(temp == Calibration
       ||temp == Kicker
       ||temp == Debug1
       ||temp == Debug2
       ||temp == StartS)) return 0;/*スイッチが押されていない*/
    if(temp !=0x00){
        for(i = 0; i < 50; i++);
        temp2 = Sw;
        if(temp == temp2){
            return temp;
        }
    }
    return 0;
}

//通信(モータ用)
void tx_motor(){
    array(speed[0],speed[1],speed[3],speed[2]);
    Motor.printf("%s",StringFIN.c_str());
}

void SetUp(int *compass_def){
    /*初期化*/
    
    Kick = 0;
    Sw.mode(PullUp);
    
    Motor.baud(115200);                             //ボーレート設定
    Motor.printf("1F0002F0003F0004F000\r\n");       //モータ停止
    Motor.attach(&tx_motor,Serial::TxIrq);          //送信空き割り込み(モータ用)
    //move(0,0);//停止

    S555.calibrate(0.0005, 120.0);
    S555.position(0.0);    //初期位置にセット
    
    hmc6352.setOpMode(HMC6352_CONTINUOUS, 1, 20);
    *compass_def = (hmc6352.sample() / 10);
    
    //Lcd.cls();
    
}
void StartLoop(){
    /*
     *スイッチが押されるまでロボットはスタートしない.
     *
     *switch割り当て
     *1.コンパスのキャリブレーション実行スイッチ
     *2.キッカーのキック(check用)
     *3,4.自由
     *5.StartSw
     */
     uint8_t State = 0;
     
     while(1){
         
        State = SwRead();
        if(State == 0) continue;
        
        if(State == Calibration){
            /*calibration command enter...
             *
             *
             */ 
            continue;   
        }
        if(State == Kicker){
            /*
             *kicker check 
             *
             *
             */
            continue;
        }
        if(State == Debug1){
            /* debug command free  
             *
             *display out to selected 3 menus. compass, ir, ping, line,etc... 
             *
             **/
            
        }
        if(State == Debug2){
            /* debug command free  
             *
             * decide movement of the beginning.  
             *
             *
             **/
            
        }
        if(State == StartS){
            /*game start...*/ 
           return;
        }
        
    }     
    
}
int main() {
    
    /*Ir*/
    uint8_t IrNum;//場所によるirの数を表したもの0~11まではボールがある状態12はボールがない状態
    uint8_t IrData[2];//0:1位*13+2位,1:1位の値
    /*Line*/
    uint8_t LineData = 0;
    
    /*Compass*/
    int CompassDef = 0, Compass = 0;
    hmc6352.setOpMode(HMC6352_CONTINUOUS, 1, 20);
    
    /*State */ 
    //Direction LineIr = NA;//方位設定奴...エラーでてめんどくさいので後でまたやることにする。
    uint8_t LineIr = NA;
    uint8_t IrChange[13] ={1,1,1,2,2,2,4,4,4,8,8,8};

    /*関数ポインタ*/
    void (*AnotherAction[3])(int *, uint8_t []);//irの位置による分岐
    AnotherAction[0] = IrFrontAction;
    AnotherAction[1] = IrBackAction;
    AnotherAction[2] = GoHome;
    
    
    SetUp(&CompassDef);/*set up routine*/
    //StartLoop(); /*loop stat, switch push end*/
    
    int val = 0;
    int compassy;
    char data[3] = {0};
    char order[1] = {0};
    while(1) {
        
        
        
        /*白線を読んでいないか確認する*/
        /*
        LineData = (~Line+0x00) & 0x0F; 
        if(LineData){
            IrNum = IrReceive(IrData);
            LineIr = LineData & IrChange[IrNum];    //一箇所でも一致すればlineを検知している.
            while(LineIr){
                move(0,0);//
                Led[1] = Led[2] = Led[3] = 1;  
                LineData = (~Line+0x00) & 0x0F;
                IrNum = IrReceive(IrData);
                LineIr = LineData & IrChange[IrNum];//一箇所でも一致すればlineを検知している.
            }
            Led[1] = Led[2] = Led[3] = 0;
            continue;
        }
        */
        
        
        
        /*ロボットの向いている向きが正面か確認する*/
        /*
        Compass = ((hmc6352.sample() / 10) + 540 - CompassDef) % 360;    
        if(!((Compass>=150)&&(Compass<=210))){
            while(!((Compass>=150)&&(Compass<=210))){
                move(20,-20);
                Compass = ((hmc6352.sample() / 10) + 540 - CompassDef) % 360;
            }
            continue;
        
        }
        */
        /*ボールの位置を知る*/
        //IrNum = IrReceive(IrData);
        
        order[0] = 0x00;
        for(int i=0; i<3; i++) data[i]=100;
        
        val = Sensor.write(ADDRESS_R&0xFE, order , 1);
           
        Led[0] = 0;       
        Led[1] = !val;
        
        wait_ms(.25);
        
        val = Sensor.read(ADDRESS_R|1, data, 3);// IRデータを受信
        
        Led[0] = !val;
        Led[1] = 0;
        
        wait_ms(.25);
        
        pc.printf("num = %d irData1 = %d irData2 = %d\n",(int)data[0],(int)data[1],(int)data[2]);
        
        for(int i=0; i<3; i++) data[i]=100;
        
        
        
        
        
        
        
        
        val = Sensor.write((ADDRESS_R+2)&0xFE, order , 1);
           
        Led[0] = 0;       
        Led[1] = !val;
        
        wait_ms(.25);
        
        val = Sensor.read((ADDRESS_R+2)|1, data, 3);// IRデータを受信
        
        Led[0] = !val;
        Led[1] = 0;
        
        wait_ms(.25);
        
        pc.printf("num = %d irData1 = %d irData2 = %d\n",(int)data[0],(int)data[1],(int)data[2]);
        
        for(int i=0; i<3; i++) data[i]=100;
        
        
        
        
        
        //pc.printf("Heading is: %03d\n",(int)((hmc6352.sample()/10.0)+0.5));
        
        compassy = (
                        (
                            ((int)(hmc6352.sample()/10.0))
                            + 540
                            - CompassDef
                        )%360
                    );
        
        Lcd.cls();
        Lcd.printf("Hello\n %d", compassy );
        
        wait_ms(.25);
        
        for(int i=0; i<3; i++) data[i]=100;
        
        
        /*複雑な処理が必要な箇所については関数に飛ばす*/
        /*
        
        if(IrNum == 0 || IrNum == 6||IrNum == 12){
            (*AnotherAction[IrNum/6])(&CompassDef,IrData); //Front OR Back Action
            continue;
        }
        
        */
        
        /*残りの箇所についての処理を行う*/    
        
        
        
        //wait_ms(0);
    
    
    }
    
    
    while(0){
    /*デモプログラム*/

        
    }
    

    
    
}