sotsuken

Dependencies:   IncEncoder mbed

Revision:
0:a1f453dd2bb5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Mon Dec 12 05:50:18 2022 +0000
@@ -0,0 +1,492 @@
+#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送信
+}
\ No newline at end of file