modified 0511

Dependencies:   mbed-dev FastPWM3

Revision:
63:5946297ba2b0
Parent:
62:d43fcdd2d48b
Child:
64:fd695fb9865b
--- a/main.cpp	Mon Mar 07 01:39:20 2022 +0000
+++ b/main.cpp	Tue Mar 08 12:01:01 2022 +0000
@@ -3,22 +3,24 @@
 /// Hardware documentation can be found at build-its.blogspot.com
 /// Written for the STM32F446, but can be implemented on other STM32 MCU's with some further register-diddling
 /// Version for the TI DRV8323 Everything Chip
-
+ 
 #define REST_MODE 0
 #define MOTOR_MODE 1
 #define HALL_CALIBRATE 2 //hall sensor calibration
 #define SETUP_MODE 3
 #define CALIBRATION_MODE 4
 #define ENCODER_MODE 5
-
-#define VERSION_NUM 5
-
-
+ 
+#define VERSION_NUM 6
+ 
+ 
 //float __float_reg[64];                                                          // Floats stored in flash
-float __float_reg[67]; // Floats stored in flash(add three floats: kp, ki, kd)
+//float __float_reg[67]; // Floats stored in flash(add three floats: kp, ki, kd)
+//float __float_reg[68]; // add calibrate offset
+float __float_reg[69]; // add calibrate speed
 int __int_reg[257]; //新增calibrate旋轉方向(+1: 逆時針旋轉、-1: 順時針旋轉)
 //int __int_reg[256];                                                             // Ints stored in flash.  Includes position sensor calibration lookup table
-
+ 
 #include "mbed.h"
 #include "PositionSensor.h"
 #include "structs.h"
@@ -35,41 +37,40 @@
 #include "PreferenceWriter.h"
 #include "CAN_com.h"
 #include "DRV.h"
-
+ 
 //DigitalOut *CAN_DEBUG = new DigitalOut(PB_15); 
 //DigitalOut *GPIO_PID_DEBUG = new DigitalOut(PC_6); 
-
+ 
 DigitalIn *HALL_IO = new DigitalIn(PC_6); 
-
+ 
 PreferenceWriter prefs(6);
-
+ 
 GPIOStruct gpio;
 ControllerStruct controller;
 ObserverStruct observer;
 COMStruct com;
 Serial pc(PA_2, PA_3);
-
-
+ 
+ 
 CAN          can(PB_8, PB_9, 1000000);      // CAN Rx pin name, CAN Tx pin name
 CANMessage   rxMsg;
 CANMessage   txMsg;
-
-
+ 
+ 
 SPI drv_spi(PA_7, PA_6, PA_5);
 DigitalOut drv_cs(PA_4);
 //DigitalOut drv_en_gate(PA_11);
 DRV832x drv(&drv_spi, &drv_cs);
-
+ 
 PositionSensorAM5147 spi(16384, 0.0, NPP);  
-
+ 
 volatile int count = 0;
 volatile int state = REST_MODE;
 volatile int state_change;
-
+ 
 void ChangeParameter(CANMessage msg) ;
 bool complete_changepara = false;
-bool set_zero = 0;
-
+ 
 /*Hall sensor calibration*/
 volatile int hall_input = 1;
 volatile int hall_preinput = 1;
@@ -83,7 +84,7 @@
 volatile int calibrate_count = 0;
 volatile int calibrate_state = 0;
 //
-
+ 
 void onMsgReceived() {
     //static int can_state = 0;
     //msgAvailable = true;
@@ -104,10 +105,8 @@
             gpio.led->write(0);
         }
         else if(((rxMsg.data[0]==0xFF) & (rxMsg.data[1]==0xFF) & (rxMsg.data[2]==0xFF) & (rxMsg.data[3]==0xFF) * (rxMsg.data[4]==0xFF) & (rxMsg.data[5]==0xFF) & (rxMsg.data[6]==0xFF) & (rxMsg.data[7]==0xFE))){
-            set_zero = 1;
             spi.ZeroPosition();
             controller.p_des = 0;
-            set_zero = 0;
         }
         else if(state == REST_MODE && rxMsg.data[0]==0xFE){
             printf("Change Parameters\n\r");
@@ -116,7 +115,6 @@
         }
         else if(((rxMsg.data[0]==0xFF) & (rxMsg.data[1]==0xFF) & (rxMsg.data[2]==0xFF) & (rxMsg.data[3]==0xFF) * (rxMsg.data[4]==0xFF) & (rxMsg.data[5]==0xFF) & (rxMsg.data[6]==0xFF) & (rxMsg.data[7]==0xFA))){
             //printf("Hall Calibration\n\r");
-            state = HALL_CALIBRATE;
             calibrate_count = 0;
             calibrate_state = 1; // calibrating
             //step1:讀目前位置
@@ -126,9 +124,9 @@
             float _f_cal_round;
             modf(cal_pcmd/(2*PI),&_f_cal_round);
             cal_pcmd = cal_pcmd - _f_cal_round*2*PI;
-            if(cal_pcmd < 0)
-                cal_pcmd = cal_pcmd + 2*PI;
-            
+            if(cal_pcmd < 0) cal_pcmd = cal_pcmd + 2*PI;
+
+            state = HALL_CALIBRATE ;
             state_change = 1;    
         }
         else if(state == MOTOR_MODE){
@@ -142,7 +140,7 @@
         }
     
 }
-
+ 
 //Use CAN Bus to change parameters
 void ChangeParameter(CANMessage msg){
     int kp_int = (msg.data[2]<<4)|(msg.data[3]>>4);
@@ -164,7 +162,7 @@
     controller.ki = MOTOR_KI;
     controller.kd = MOTOR_KD;
 }
-
+ 
 void enter_menu_state(void){
     drv.disable_gd();
     gpio.enable->write(0);
@@ -186,7 +184,7 @@
     state_change = 0;
     gpio.led->write(0);
 }
-
+ 
 void enter_setup_state(void){
     printf("\n\r\n\r Configuration Options \n\r\n\n");
     wait_us(10);
@@ -208,6 +206,12 @@
     printf(" %-4s %-31s %-5s %-6s %d\n\r", "c", "Calibration Direction", "-1", "1", CALIBRATE_DIR);
     wait_us(10);
     
+    printf(" %-4s %-31s %-5s %-6s %.1f\n\r", "e", "Calibration offset", "0.0", "143.0", CALIBRATE_OFFSET);
+    wait_us(10);
+    
+    printf(" %-4s %-31s %-5s %-6s %.1f\n\r", "s", "Calibration Speed", "0.0", "10.0", CALIBRATE_SPEED);
+    wait_us(10);
+    
     printf(" %-4s %-31s %.2f  %.2f %.2f\n\r", "p", "MOTOR_KP", KP_MIN, KP_MAX, MOTOR_KP);
     wait_us(10);
     printf(" %-4s %-31s %.2f  %.2f  %.2f\n\r", "i", "MOTOR_KI", KI_MIN, KI_MAX, MOTOR_KI);
@@ -252,19 +256,18 @@
     //printf("%d\n\r", spi.GetRawPosition());
     wait(.001);
     }
-
+ 
 /// Current Sampling Interrupt ///
 /// This runs at 40 kHz, regardless of of the mode the controller is in ///
 extern "C" void TIM1_UP_TIM10_IRQHandler(void) {
   if (TIM1->SR & TIM_SR_UIF ) {
-        hall_input = HALL_IO->read(); // read hall sensor
         //GPIO_PID_DEBUG->write(1);
-
+ 
         ///Sample current always ///
         ADC1->CR2  |= 0x40000000;                                               // Begin sample and conversion
         //volatile int delay;   
         //for (delay = 0; delay < 55; delay++);
-
+ 
         spi.Sample(DT);                                                           // sample position sensor
         controller.adc2_raw = ADC2->DR;                                         // Read ADC Data Registers
         controller.adc1_raw = ADC1->DR;
@@ -274,7 +277,99 @@
         controller.dtheta_mech = (1.0f/GR)*spi.GetMechVelocity();  
         controller.dtheta_elec = spi.GetElecVelocity();
         controller.v_bus = 0.95f*controller.v_bus + 0.05f*((float)controller.adc3_raw)*V_SCALE; //filter the dc link voltage measurement
-        ///
+        
+        // Calibration function
+        if(calibrate_state == 0 || calibrate_state >= 2 ) ;
+        else{
+            // read hall sensor
+            hall_input = HALL_IO->read() ;
+            // calculate new pos
+            if((CALIBRATE_DIR == 1 && controller.theta_mech >= hall_presentpos + 2*PI) || (CALIBRATE_DIR == -1 && controller.theta_mech <= hall_presentpos - 2*PI)){
+                calibrate_state = 3 ;
+                state = REST_MODE ;
+                state_change = 1 ;
+            }
+            else{
+                // step3: 馬達正反轉讀hall sensor(1: 沒有感應到磁鐵,0:有感應到磁鐵)
+                // 記住1->0瞬間的位置(in_pos),繼續旋轉
+                // 記住0->1瞬間的位置(out_pos),停止旋轉,計算in_pos與out_pos的平均值,再讓馬達慢慢轉到位置
+                if(hall_input != hall_preinput ) {
+                    calibrate_count += 1 ;
+                    if(hall_input == 0) hall_in_pos = controller.theta_mech ;
+                    else{
+                        hall_out_pos = controller.theta_mech ;
+                        hall_mid_pos = (hall_in_pos + hall_out_pos)/2.0f ;
+                    }
+                }
+
+                if(calibrate_count <= 1) cal_pcmd = cal_pcmd + CALIBRATE_DIR*(1.0f/(40000.0f)*CALIBRATE_SPEED ) ;
+                else{
+                    if(CALIBRATE_DIR == 1 ){
+                        if(CALIBRATE_OFFSET == 0){
+                            //keep turning
+                            if(controller.theta_mech >= hall_mid_pos) cal_pcmd = cal_pcmd - CALIBRATE_DIR*1.0f/40000.0f*CALIBRATE_SPEED ;
+                            else{//stop
+                                cal_pcmd = 0.0f;
+                                calibrate_state = 2; //success
+                                spi.ZeroPosition();
+                                //count = 0;
+                                //歸零
+                                calibrate_count = 0 ;
+                                state = MOTOR_MODE;
+                            }
+                        }
+                        else{
+                            if(controller.theta_mech <= hall_mid_pos + CALIBRATE_OFFSET*PI/180)  cal_pcmd = cal_pcmd + CALIBRATE_DIR*1.0f/40000.0f*CALIBRATE_SPEED ;
+                            else{ //stop
+                                cal_pcmd = 0.0f;
+                                calibrate_state = 2; //success
+                                spi.ZeroPosition();
+                                //歸零
+                                calibrate_count = 0 ;
+                                state = MOTOR_MODE;
+                            }         
+                        
+                        
+                        }
+                    }
+                    else if(CALIBRATE_DIR == -1){
+                        if(CALIBRATE_OFFSET == 0){
+                            //keep turning
+                            if(controller.theta_mech <= hall_mid_pos) cal_pcmd = cal_pcmd - CALIBRATE_DIR*1.0f/40000.0f*CALIBRATE_SPEED ;
+                            else{//stop
+                                cal_pcmd = 0.0f;
+                                calibrate_state = 2; //success
+                                spi.ZeroPosition();
+                                //歸零
+                                calibrate_count = 0 ;
+                                state = MOTOR_MODE;
+                            }
+                        }
+                        else{ //calibrate_offset != 0
+                            if(controller.theta_mech >= hall_mid_pos - CALIBRATE_OFFSET*PI/180)  cal_pcmd = cal_pcmd + CALIBRATE_DIR*1.0f/40000.0f*CALIBRATE_SPEED ;
+                            else{ //stop
+                                cal_pcmd = 0.0f;
+                                calibrate_state = 2; //success
+                                spi.ZeroPosition();
+                                //歸零
+                                calibrate_count = 0 ;
+                                state = MOTOR_MODE;
+                            }
+                        
+                        }
+                        
+
+                    
+                    }
+                }
+                
+                cal_pcmd = (cal_pcmd>2*PI) ? cal_pcmd-=2*PI : cal_pcmd ;
+                cal_pcmd = (cal_pcmd < 0)  ? cal_pcmd+=2*PI : cal_pcmd ;
+                controller.p_des = cal_pcmd ;
+            }
+
+            hall_preinput = hall_input ;
+        }
         
         /// Check state machine state, and run the appropriate function ///
         switch(state){
@@ -283,14 +378,10 @@
                     if(calibrate_state != 2) //success
                         enter_menu_state();
                     else{
-//                        if(calibrate_count != 0){
-                            drv.disable_gd();
-                            gpio.enable->write(0);
-                            state_change = 0;
-                            gpio.led->write(0);
-//                        }
-//                        state = MOTOR_MODE;
-//                        state_change = 1;
+                        drv.disable_gd();
+                        gpio.enable->write(0);
+                        state_change = 0;
+                        gpio.led->write(0);
                     }
                 }
                 break;
@@ -317,7 +408,7 @@
                     printf("OVP Triggered!\n\r");
                     }
                     */  
-
+ 
                     if((controller.timeout > CAN_TIMEOUT) && (CAN_TIMEOUT > 0)){
                         controller.i_d_ref = 0;
                         controller.i_q_ref = 0;
@@ -325,119 +416,56 @@
                         controller.kd = 0;
                         controller.t_ff = 0;                                                                                                                                     
                     } 
+ 
+                    torque_control(&controller);
+                    commutate(&controller, &observer, &gpio, controller.theta_elec);           // Run current loop
 
-                    if(!set_zero){
+                    controller.timeout++;
+                    count++;
+            
+                }     
+                break;
+            case HALL_CALIBRATE:
+                    if(state_change){
+                        enter_torque_mode();
+                        count = 0;
+                    }
+                    else{
+                        if((controller.timeout > CAN_TIMEOUT) && (CAN_TIMEOUT > 0)){
+                            controller.i_d_ref = 0;
+                            controller.i_q_ref = 0;
+                            controller.kp = 0;
+                            controller.kd = 0;
+                            controller.t_ff = 0;                                                                                                                                     
+                        } 
+     
                         torque_control(&controller);
                         commutate(&controller, &observer, &gpio, controller.theta_elec);           // Run current loop
-
+    
                         controller.timeout++;
                         count++;
+            
                     } 
-            
-                }     
                 break;
             case SETUP_MODE:
                 if(state_change){
                     enter_setup_state();
                 }
                 break;
-            case HALL_CALIBRATE:
-                if(state_change){
-                    //step2:馬達激磁
-                    enter_torque_mode();
-                    calibrate_state = 1;
-                    count = 0;
-                }
-                else{
-                        //若轉超過一圈就算失敗
-                        if((CALIBRATE_DIR == 1 && controller.theta_mech >= hall_presentpos + 2*PI) || (CALIBRATE_DIR == -1 && controller.theta_mech <= hall_presentpos - 2*PI)){
-                            calibrate_state = 3;
-                            state = REST_MODE;
-                            state_change = 1;
-                        }
-                        else{
-                                //step3: 馬達正反轉讀hall sensor(1: 沒有感應到磁鐵,0:有感應到磁鐵)
-                                //記住1->0瞬間的位置(in_pos),繼續旋轉
-                                //記住0->1瞬間的位置(out_pos),停止旋轉,計算in_pos與out_pos的平均值,再讓馬達慢慢轉到位置
-                                if(hall_input != hall_preinput){
-                                    calibrate_count += 1;
-                                    if(hall_input == 0)
-                                        hall_in_pos = controller.theta_mech;
-                                    else{
-                                        hall_out_pos = controller.theta_mech;
-                                        hall_mid_pos = (hall_in_pos + hall_out_pos)/2;
-                                    }
-                                }
-                        
-                                if(calibrate_count <= 1){
-                                    cal_pcmd = cal_pcmd + CALIBRATE_DIR*(1.0f/(40000.0f)*calibrate_speed);
-                                }
-                                else{
-                                    if(CALIBRATE_DIR == 1){
-                                        if(controller.theta_mech >= hall_mid_pos) //keep turning
-                                            cal_pcmd = cal_pcmd - CALIBRATE_DIR*1.0f/40000.0f*calibrate_speed;
-                                        else{//stop
-                                            cal_pcmd = 0;
-                                            calibrate_state = 2; //success
-                                            spi.ZeroPosition();
-                                            controller.p_des = 0;
-                                            state = REST_MODE;
-                                            state_change = 1;
-                                            //count = 0;
-                                            //歸零
-                                            calibrate_count = 0;
-                                            
-                                        }
-                                    }
-                                    else if(CALIBRATE_DIR == -1){
-                                        if(controller.theta_mech <= hall_mid_pos) //keep turning
-                                            cal_pcmd = cal_pcmd - CALIBRATE_DIR*(1.0f/(40000.0f)*calibrate_speed);
-                                        else{//stop
-                                            cal_pcmd = controller.theta_mech;
-                                            calibrate_state = 2; //success
-                                            spi.ZeroPosition();
-                                            controller.p_des = 0;
-                                            //歸零
-                                            calibrate_count = 0;
-                                        }
-                                    }
-                                }
-                                
-                                cal_pcmd = (cal_pcmd>2*PI) ? cal_pcmd-=2*PI : cal_pcmd;
-                                cal_pcmd = (cal_pcmd < 0)  ? cal_pcmd+=2*PI : cal_pcmd;
-                                controller.p_des = cal_pcmd;
-                                if((controller.timeout > CAN_TIMEOUT) && (CAN_TIMEOUT > 0)){
-                                    controller.i_d_ref = 0;
-                                    controller.i_q_ref = 0;
-                                    controller.kp = 0;
-                                    controller.ki = 0;
-                                    controller.kd = 0;
-                                    controller.t_ff = 0;                                                                                                                                     
-                                } 
-    
-                                torque_control(&controller);
-                                commutate(&controller, &observer, &gpio, controller.theta_elec);           // Run current loop
-            
-                                controller.timeout++;
-                                count++;
-                        }
-                }
-                break;
             case ENCODER_MODE:
                 print_encoder();
                 break;
                 }                 
       }
     TIM1->SR = 0x0;                                                               // reset the status register
-    hall_preinput = hall_input;
   //GPIO_PID_DEBUG->write(0);
 }
-
-
+ 
+ 
 char cmd_val[8] = {0};
 char cmd_id = 0;
 char char_count = 0;
-
+ 
 /// Manage state machine with commands from serial terminal or configurator gui ///
 /// Called when data received over serial ///
 void serial_interrupt(void){
@@ -509,6 +537,12 @@
                     case 'c':
                         CALIBRATE_DIR = atoi(cmd_val);
                         break;
+                    case 'e':
+                        CALIBRATE_OFFSET = fmaxf(fminf(atof(cmd_val), 143.0f), 0.0f);
+                        break;
+                    case 's':
+                        CALIBRATE_SPEED = fmaxf(fminf(atof(cmd_val), 10.0f), 0.0f);
+                        break;
                     case 'p':
                         MOTOR_KP = fmaxf(fminf(atof(cmd_val), KP_MAX), KP_MIN);;
                         break;
@@ -565,7 +599,7 @@
             
         }
     }
-
+ 
 void GPIO_SETUP(){
      //GPIOB->MODER |= 0x40000000;
      //GPIOC->MODER |= 0x0000100f;
@@ -595,7 +629,7 @@
     zero_current(&controller.adc1_offset, &controller.adc2_offset);             // Measure current sensor zero-offset
     drv.disable_gd();
     gpio.enable->write(0);
-
+ 
     wait(.1);
     /*
     gpio.enable->write(1);
@@ -637,6 +671,8 @@
     if(isnan(MOTOR_KI) || MOTOR_KI==-1){MOTOR_KI = 0;}
     if(isnan(MOTOR_KD) || MOTOR_KD==-1){MOTOR_KD = 1.25;}
     if(CALIBRATE_DIR != -1 && CALIBRATE_DIR != 1){CALIBRATE_DIR = 1;}
+    if(isnan(CALIBRATE_OFFSET) || CALIBRATE_OFFSET==-1){CALIBRATE_OFFSET = 0.0;}
+    if(isnan(CALIBRATE_SPEED) || CALIBRATE_SPEED==-1){CALIBRATE_SPEED = 0.25;}
     
     spi.SetElecOffset(E_OFFSET);                                                // Set position sensor offset
     spi.SetMechOffset(M_OFFSET);
@@ -644,7 +680,7 @@
     memcpy(&lut, &ENCODER_LUT, sizeof(lut));
     spi.WriteLUT(lut);                                                          // Set potision sensor nonlinearity lookup table
     init_controller_params(&controller);
-
+ 
     pc.baud(115200);                                                            // set serial baud rate
     wait(.01);
     pc.printf("\n\r\n\r HobbyKing Cheetah\n\r\n\r");
@@ -663,7 +699,9 @@
     printf(" PID controller parameters \n\r");
     printf(" KP: %.3f, KI: %.3f, KD: %.3f \n\r", controller.kp, controller.ki, controller.kd);
     printf(" Calibrate Direction: %d\n\r", CALIBRATE_DIR);
-
+    printf(" Calibrate Offset: %f\n\r", CALIBRATE_OFFSET);
+    printf(" Calibrate Speed: %f\n\r", CALIBRATE_SPEED);
+ 
     //printf(" %d\n\r", drv.read_register(DCR));
     //wait_us(100);
     //printf(" %d\n\r", drv.read_register(CSACR));
@@ -677,7 +715,7 @@
     
     // calibrate
     calibrate_state = 0;
-
+ 
     int counter = 0;
     while(1) {
         if(complete_changepara){
@@ -710,7 +748,7 @@
         printf("helloworld\n\r");
         wait(1);
         */
-
+ 
         /*
         CAN_DEBUG->write(1);
         wait(0.1);
@@ -729,6 +767,6 @@
             wait(.002);
         }
         */
-
+ 
     }
-}
+}
\ No newline at end of file