modified 0511

Dependencies:   mbed-dev FastPWM3

Revision:
61:29371056a3de
Parent:
60:f009e39e913e
Child:
62:d43fcdd2d48b
--- a/main.cpp	Tue Mar 01 12:29:08 2022 +0000
+++ b/main.cpp	Wed Mar 02 10:01:40 2022 +0000
@@ -9,8 +9,10 @@
 #define MOTOR_MODE 2
 #define SETUP_MODE 4
 #define ENCODER_MODE 5
+#define HALL_CALIBRATE 6 //hall sensor calibration
+#define HALL_OFFSET 7
 
-#define VERSION_NUM 4
+#define VERSION_NUM 5
 
 
 //float __float_reg[64];                                                          // Floats stored in flash
@@ -33,6 +35,9 @@
 #include "PreferenceWriter.h"
 #include "CAN_com.h"
 #include "DRV.h"
+#include "math.h"
+
+using namespace FastMath;
 
 //DigitalOut *CAN_DEBUG = new DigitalOut(PB_15); 
 //DigitalOut *GPIO_PID_DEBUG = new DigitalOut(PC_6); 
@@ -68,7 +73,19 @@
 bool complete_changepara = false;
 bool set_zero = 0;
 
+/*Hall sensor calibration*/
 volatile int hall_input = 1;
+volatile int hall_preinput = 1;
+volatile float cal_pcmd = 0;
+volatile float calibrate_speed = 0.25; // rad/s
+volatile float hall_presentpos = 0; //calibrate之前encoder的位置
+volatile float hall_in_pos = 0;  //讀到1->0的位置(磁鐵進入hall sensor範圍)
+volatile float hall_out_pos = 0; //讀到0->1的位置(磁鐵出hall sensor範圍)
+volatile float hall_mid_pos = 0;
+volatile int calibrate_dir = -1; 
+volatile float calibrate_offset = 0; //rad
+volatile int calibrate_count = 0;
+volatile int calibrate_finish = 0;
 
 void onMsgReceived() {
     //static int can_state = 0;
@@ -99,6 +116,23 @@
             ChangeParameter(rxMsg);
             complete_changepara = true;
         }
+        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");
+            calibrate_finish = 0;
+            //step1:讀目前位置
+            /*----- convert theta_mech to 0~359.9999deg -----*/
+            hall_presentpos = controller.theta_mech;
+            float _f_cal_round;
+            modf(hall_presentpos/(2*PI),&_f_cal_round);
+            hall_presentpos = hall_presentpos - _f_cal_round*2*PI;
+            if(hall_presentpos < 0)
+                hall_presentpos = hall_presentpos + 2*PI;
+            
+            printf("hall_presentpos: %f\n\r", hall_presentpos);
+            cal_pcmd = hall_presentpos;
+            state = HALL_CALIBRATE; 
+            state_change = 1;    
+        }
         else if(state == MOTOR_MODE){
             unpack_cmd(rxMsg, &controller);
         }
@@ -222,7 +256,7 @@
 /// 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();
+        hall_input = HALL_IO->read(); // read hall sensor
         //GPIO_PID_DEBUG->write(1);
 
         ///Sample current always ///
@@ -295,12 +329,88 @@
                     enter_setup_state();
                 }
                 break;
+            case HALL_CALIBRATE:
+                if(state_change){
+                    //step2:馬達激磁
+                    enter_torque_mode();
+                    count = 0;
+                }
+                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 = controller.theta_mech;
+                                    calibrate_finish = 1;
+                                    state = REST_MODE;
+                                    state_change = 1;
+                                    spi.ZeroPosition();
+                                    controller.p_des = 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_finish = 1;
+                                    spi.ZeroPosition();
+                                    controller.p_des = 0;
+                                    state = REST_MODE;
+                                    state_change = 1;
+                                    //歸零
+                                    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.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
+    TIM1->SR = 0x0;                                                               // reset the status register
+    hall_preinput = hall_input;
   //GPIO_PID_DEBUG->write(0);
 }
 
@@ -541,7 +651,6 @@
     
     state_change = 1;
 
-
     int counter = 0;
     while(1) {
         if(complete_changepara){
@@ -553,10 +662,17 @@
             state = REST_MODE;
             state_change = 1;
         }
-        //printf("p_des: %f\n\r", controller.p_des);
+
         
-        //printf("Hall_input(PC6): %d\n\r", HALL_IN->read());
-        //wait(1);
+//        printf("Hall_input(PC6): %d\n\r", hall_input);
+//        printf("Hall_preinput(PC6): %d\n\r", hall_preinput);
+//        printf("calibrate count: %d\n\r",calibrate_count);
+//        printf("cal_pcmd: %.4f\n\r",cal_pcmd);
+//        printf("pos_in: %f\n\r",hall_in_pos);
+//        printf("pos_out: %f\n\r",hall_out_pos);
+//        printf("theta_mech: %f\n\r",controller.theta_mech);
+//        printf("state: %d\n\r",state);
+//        wait(1);
         
         /*
         CAN_DEBUG->write(1);