sotsuken

Dependencies:   IncEncoder mbed

main.cpp

Committer:
koki_konishi
Date:
23 months ago
Revision:
0:a1f453dd2bb5

File content as of revision 0:a1f453dd2bb5:

#include "mbed.h"
#include "IncEncoder.h"
#include <math.h>

#define PI 3.14159265358979

#define BELT_RPP 512
#define ANG_RPP 512
#define LIFT_RPP 256

#define BELT_PER 1050
#define BELT_Rratio 5

#define LIFT_PCD 54 

#define BELT_UC 30 //モータ出力オフセット
#define ANG_UC 25
#define LIFT_UC 36

#define VELO_dt 0.010
#define BELT_dt 0.010
#define ANG_dt 0.010
#define LIFT_dt 0.010

#define VELO_Ke 1
#define VELO_Kp 0.005
#define VELO_Ki 0.000012
#define VELO_Kd 0.0000

#define BELT_Ke 1
#define BELT_Kp 1.2
#define BELT_Ki 0.005
#define BELT_Kd 0.03

#define ANG_Ke 4
#define ANG_Kp 1.2
#define ANG_Ki 0.005
#define ANG_Kd 0.03

#define LIFT_Ke 2
#define LIFT_Kp 1.8
#define LIFT_Ki 0.013
#define LIFT_Kd 0.03

#define ARM_SERVO_OFFSET 7500
#define ARM_SERVO_VPA 29.6296296

//モータードライバのアドレス
#define beltR_MOTOR 0x02
#define angR_MOTOR 0x04

//モータードライバへの命令
#define STOP 0
#define CW 1
#define CCW -1
#define bSTOP 10
#define bCW 11
#define bCCW -11

#define sCW 21
#define sCCW -21
#define sSTOP 20
#define shCW 31
#define shCCW -31

#define lCW 51
#define lCCW -51
#define lSTOP 50
#define lsCW 61
#define lsCCW -61
#define lsSTOP 60

#define rON 41
#define rOFF -41

//通信初期化
Serial mecha_ins(USBTX,USBRX,115200);
I2C md_i2c_tx(PD_13,PD_12);

//GPIO初期化
InterruptIn beltR_i_(PC_1);

DigitalIn angR_zero(PE_15);

//QEI初期化
IncEncoder beltR_RE(PC_2,PC_3,IncEncoder::x2_Resolution);
IncEncoder angR_RE(PF_9,PC_0,IncEncoder::x2_Resolution);

//プロトタイプ関数宣言
void ins_recieve();
void BELTR_PID();
void ANGR_PID();
void belt_reset();
void beltR_reset();
void md_setoutput(unsigned char address, int rotate, int duty);

volatile char led_command = 0xFF;

volatile char mecha_prep = 0;
volatile int triggerR_flag = 0, triggerL_flag = 0;

volatile int lift_pid_flag_R = 1, lift_pid_flag_L = 1;

volatile int kick_R = 0, kick_L = 0;
volatile int pid_off_R = 0, pid_off_L = 0;

volatile int beltR_delaycnt = 0, beltL_delaycnt = 0;
volatile int beltR_delayflag = 1, beltL_delayflag = 1;

volatile int delayR_cnt = 0, delayL_cnt = 0;
volatile int delayR_flag = 1, delayL_flag = 1;

volatile int liftR_reset = 0, liftL_reset = 0;
volatile int stateR_num = 0, stateL_num = 0;
volatile int cntR = 0, cntL = 0;

volatile int BELTR_flag = 0, BELTL_flag = 0;

volatile int beltR_POWER = 0;
volatile int beltL_POWER = 0;
volatile int beltR_TRIGGER = 0;
volatile int beltL_TRIGGER = 0;

volatile int beltR_UMAX = 100;
volatile int beltL_UMAX = 100;

volatile int beltR_MOTOR_Rdir;
volatile int beltL_MOTOR_Rdir;
volatile double beltR_DES = 20;
volatile double beltL_DES = 20;
volatile double beltR_STATE = 0;
volatile double beltL_STATE = 0;
volatile double beltR_U;
volatile double beltL_U;
volatile double beltR_ERROR[2] = {};
volatile double beltL_ERROR[2] = {};
volatile double beltR_INTEGRAL = 0;
volatile double beltL_INTEGRAL = 0;

volatile int angR_MOTOR_Rdir;
volatile int angL_MOTOR_Rdir;
volatile double ANGR_DES = 0;
volatile double ANGL_DES = 0;
volatile double ANGR_STATE = 0;
volatile double ANGL_STATE = 0;
volatile double ANGR_U;
volatile double ANGL_U;
volatile double ANGR_ERROR[2] = {};
volatile double ANGL_ERROR[2] = {};
volatile double ANGR_INTEGRAL = 0;
volatile double ANGL_INTEGRAL = 0;

volatile int liftR_MOTOR_Rdir;
volatile int liftL_MOTOR_Rdir;
volatile double liftR_DES = 0;
volatile double liftL_DES = 0;
volatile double liftR_STATE = 0;
volatile double liftL_STATE = 0;
volatile double liftR_U;
volatile double liftL_U;
volatile double liftR_ERROR[2] = {};
volatile double liftL_ERROR[2] = {};
volatile double liftR_INTEGRAL = 0;
volatile double liftL_INTEGRAL = 0;

//main
int main(){
    md_i2c_tx.frequency(400000); //MD用I2C
    
    beltR_RE.reset();
    angR_RE.reset();
    
    angR_zero.mode(PullUp);
    
    beltR_i_.mode(PullDown);
    
    beltR_i_.rise(&beltR_reset);
    
    wait_ms(300);
    
    while(!angR_zero){
        if(!angR_zero){
            md_setoutput(angR_MOTOR,bCCW,50);
        }else{
            md_setoutput(angR_MOTOR,bSTOP,0);
        }
    }
    
    angR_RE.reset();
    
    belt_reset();
    
    while(mecha_ins.readable()){
        char dummy = mecha_ins.getc();
    }
    
    mecha_ins.attach(&ins_recieve, Serial::RxIrq);
    
    while(1){
        if(1){
            //追従処理呼び出し なぜかTickerが新マザーで正常動作しないため\(^o^)/
            if(!beltR_TRIGGER){
                BELTR_PID();
            }
            
            ANGR_PID();
            
            //発射処理
            if(beltR_TRIGGER == 1){
                
                beltR_TRIGGER++;
            }
            
            if(beltR_TRIGGER == 2){
                if(pid_off_R){
                    md_setoutput(beltR_MOTOR,CW,beltR_POWER);
                }else{
                    md_setoutput(beltR_MOTOR,sCW,beltR_POWER);
                }
                
                triggerR_flag = 0; 
            }
            
            if(kick_R){
                if(beltR_RE.GetIncPulses()/(BELT_RPP*2) >= 2.0 && beltR_TRIGGER == 2){
                    pid_off_R = 0;
                    beltR_delaycnt = 50;
                    beltR_delayflag = 0;
                    beltR_TRIGGER++;
                }
            }else{
                if(beltR_RE.GetIncPulses()/(BELT_RPP*2) >= 0.5 && beltR_TRIGGER == 2){
                    pid_off_R = 0;
                    beltR_delaycnt = 50;
                    beltR_delayflag = 0;
                    beltR_TRIGGER++;
                }
            }
            
            if(beltR_TRIGGER == 3){
                kick_R = 0;
                md_setoutput(beltR_MOTOR,bSTOP,0);
            }
            
            if(beltR_delayflag && beltR_TRIGGER == 3){
                beltR_TRIGGER++;
            }
            
            if(beltR_TRIGGER == 4){
                md_setoutput(beltR_MOTOR,bCW,70);
            }
            
            if(beltR_RE.GetIncPulses()/(BELT_RPP*2) >= 5 && beltR_TRIGGER == 4){
                BELTR_flag = 1;
                beltR_TRIGGER++;
            }
            
            if(beltR_TRIGGER == 5){
                md_setoutput(beltR_MOTOR,bCCW,70);
            }
            
            if(!BELTR_flag && beltR_TRIGGER == 5){
                md_setoutput(beltR_MOTOR,bSTOP,0);
                beltR_INTEGRAL = 0;
                beltR_TRIGGER = 0;
            }
        }
        
        mecha_prep = 0x00;
        
        if(triggerR_flag){
            mecha_prep = 0x80;
        }
        if(triggerL_flag){
            mecha_prep = 0x40;
        }
        if(beltR_TRIGGER){
            mecha_prep = 0x20;
        }
        if(beltL_TRIGGER){
            mecha_prep = 0x10;
        }
        if(stateR_num){
            mecha_prep = 0x08;
        }
        if(stateL_num){
            mecha_prep = 0x04;
        }
        if(liftR_reset || liftL_reset){
            mecha_prep = 0x02;
        }
        
        mecha_ins.putc(mecha_prep);
        
        wait_ms(10);
    }
}

//右発射角追従制御
void ANGR_PID(){
    ANGR_STATE = 360 * -angR_RE.GetIncPulses()/(ANG_RPP*2);
    
    ANGR_ERROR[0] = ANGR_ERROR[1];
    ANGR_ERROR[1] = (double)ANG_Ke * (ANGR_STATE - ANGR_DES);
    ANGR_INTEGRAL += ANGR_ERROR[1]*ANG_dt;
    
    ANGR_U = ANG_Kp * ANGR_ERROR[1] + ANG_Ki * ANGR_INTEGRAL + ANG_Kd * (ANGR_ERROR[1] - ANGR_ERROR[0])/ANG_dt;
    
    if(ANGR_U >= 0){
        angR_MOTOR_Rdir = bCCW;
    }else{
        angR_MOTOR_Rdir = bCW;
        ANGR_U *= -1;
    }
    
    if(ANGR_U >= 100){
        ANGR_U = 100;
    }
    
    if(angR_zero && angR_MOTOR_Rdir == bCCW){
        md_setoutput(angR_MOTOR,bSTOP,0);
    }else{
        md_setoutput(angR_MOTOR,angR_MOTOR_Rdir,ANGR_U+ANG_UC);
    }
}

//右ベルト位置追従制御
void BELTR_PID(){
    beltR_STATE = BELT_PER * beltR_RE.GetIncPulses()/(BELT_RPP*2*BELT_Rratio);
    
    beltR_ERROR[0] = beltR_ERROR[1];
    beltR_ERROR[1] = (double)BELT_Ke * (beltR_STATE - beltR_DES);
    beltR_INTEGRAL += beltR_ERROR[1]*BELT_dt;
    
    beltR_U = BELT_Kp * beltR_ERROR[1] + BELT_Ki * beltR_INTEGRAL + BELT_Kd * (beltR_ERROR[1] - beltR_ERROR[0])/BELT_dt;
    
    if(beltR_U >= 0){
        beltR_MOTOR_Rdir = bCCW;
    }else{
        beltR_MOTOR_Rdir = bCW;
        beltR_U *= -1;
    }
    
    if(beltR_U >= beltR_UMAX){
        beltR_U = beltR_UMAX;
    }
    
    md_setoutput(beltR_MOTOR,beltR_MOTOR_Rdir,beltR_U+BELT_UC);
}

void belt_reset(){
    int beltR_flag = 1;
    
    while(beltR_flag){
        if(360 * beltR_RE.GetIncPulses()/(BELT_RPP*2) < 180){
            md_setoutput(beltR_MOTOR,bCW,70);
        }else{
            md_setoutput(beltR_MOTOR,bSTOP,0);
            beltR_flag = 0;
        }
    }
    
    BELTR_flag = 1;
    
    while(BELTR_flag){
        if(BELTR_flag){
            md_setoutput(beltR_MOTOR,bCCW,70);
        }else{
            md_setoutput(beltR_MOTOR,bSTOP,0);
        }
    }
    
    wait_ms(10);
}

//命令受信処理
void ins_recieve(){
    char ins_byte = mecha_ins.getc();
    
    switch(ins_byte){
        case 0x0F : 
            cntR = mecha_ins.getc();
            cntL = mecha_ins.getc();
            liftR_reset = 1;
            liftL_reset = 1;
            break;
        case 0xA1 : 
            beltR_POWER = mecha_ins.getc();
            beltR_TRIGGER = 1;
            break;
        case 0xA2 : 
            cntR = mecha_ins.getc();
            stateR_num = 1;
            break;
        case 0xA3 : 
            ANGR_DES = mecha_ins.getc();
            break;
        case 0xB1 : 
             beltL_POWER = mecha_ins.getc();
             beltL_TRIGGER = 1;
            break;
        case 0xB2 : 
            cntL = mecha_ins.getc();
            stateL_num = 1;
            break;
        case 0xB3 : 
            ANGL_DES = mecha_ins.getc();
            break;
        case 0xAA : 
            beltR_POWER = mecha_ins.getc();
            beltR_TRIGGER = 1;
            pid_off_R = 1;
            kick_R = 1;
            break;
        case 0xAB : 
            beltR_POWER = mecha_ins.getc();
            beltR_TRIGGER = 1;
            kick_R = 1;
            break;
        case 0xBA : 
            beltL_POWER = mecha_ins.getc();
            beltL_TRIGGER = 1;
            pid_off_L = 1;
            kick_L = 1;
            break;
        case 0xBB : 
            beltL_POWER = mecha_ins.getc();
            beltL_TRIGGER = 1;
            kick_L = 1;
            break;
        case 0xAF : 
            beltR_POWER = mecha_ins.getc();
            beltR_TRIGGER = 1;
            pid_off_R = 1;
            break;
        case 0xBF : 
            beltL_POWER = mecha_ins.getc();
            beltL_TRIGGER = 1;
            pid_off_L = 1;
            break;
        case 0xFF : 
            led_command = mecha_ins.getc();
            break;
    }
    
    while(mecha_ins.readable()){
        char dummy = mecha_ins.getc();
    }
}

void beltR_reset(){
    if(BELTR_flag){
        beltR_RE.reset();
        BELTR_flag = 0;
    }
}

//MD用I2C通信処理
void md_setoutput(unsigned char address, int rotate, int duty){
    char data[2];

    // モーター駆動制御モード
    switch (rotate) {
        case CW:    data[0] = 'F'; break;// 電圧比例制御モード(PWMがLの区間はフリー)
        case CCW:   data[0] = 'R'; break;
        case STOP:  data[0] = 'S'; break;
    
        case bCW:   data[0] = 'f'; break; // 電圧比例制御モード(PWMがLの区間はブレーキ)
        case bCCW:  data[0] = 'r'; break;
        case bSTOP: data[0] = 's'; break;
    
        case sCW:   data[0] = 'A'; break; // 速度比例制御モード
        case sCCW:  data[0] = 'B'; break;
        case sSTOP: data[0] = 'T'; break;
    
        case shCW:   data[0] = 'a'; break; // 速度比例制御モード(命令パケット最上位ビットに指令値9ビット目を入れることで分解能2倍)
        case shCCW:  data[0] = 'b'; break;
    
        case lCW:   data[0] = 'L'; break; // 通常LAP
        case lCCW:  data[0] = 'M'; break;
        case lSTOP: data[0] = 'N'; break;
        case lsCW:   data[0] = 'l'; break; // 速調LAP
        case lsCCW:  data[0] = 'm'; break;
        case lsSTOP: data[0] = 'n'; break;
    
        case rON: data[0] = 'P'; break; //リレー駆動モード
        case rOFF: data[0] = 'p'; break;
    }
    
    data[1] = duty & 0xFF;
    md_i2c_tx.write(address << 1, data, 2); //duty送信
}