Modified Motor Driver Firmware to include Flash + Thermal

Dependencies:   FastPWM3 mbed-dev-STM-lean

Files at this revision

API Documentation at this revision

Comitter:
benkatz
Date:
Sun Mar 03 02:51:51 2019 +0000
Parent:
47:e1196a851f76
Child:
49:83d83040ea51
Commit message:
Working on the new hardware

Changed in this revision

Config/current_controller_config.h Show annotated file Show diff for this revision Revisions of this file
Config/hw_config.h Show annotated file Show diff for this revision Revisions of this file
Config/motor_config.h Show annotated file Show diff for this revision Revisions of this file
FOC/foc.cpp Show annotated file Show diff for this revision Revisions of this file
FOC/foc.h Show annotated file Show diff for this revision Revisions of this file
PositionSensor/PositionSensor.cpp Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
math_ops.h Show annotated file Show diff for this revision Revisions of this file
structs.h Show annotated file Show diff for this revision Revisions of this file
--- a/Config/current_controller_config.h	Wed Dec 05 04:07:46 2018 +0000
+++ b/Config/current_controller_config.h	Sun Mar 03 02:51:51 2019 +0000
@@ -7,14 +7,15 @@
 #define K_SCALE 0.0001f             // K_loop/Loop BW (Hz) 0.0042
 #define KI_D 0.0255f                // PI zero, in radians per sample
 #define KI_Q 0.0255f                // PI zero, in radians per sample
-#define V_BUS 35.0f                 // Volts
-#define OVERMODULATION 1.15f         // 1.0 = no overmodulation
+#define V_BUS 24.0f                 // Volts
+#define OVERMODULATION 1.15f        // 1.0 = no overmodulation
 
 #define D_INT_LIM V_BUS/(K_D*KI_D)  // Amps*samples
 #define Q_INT_LIM V_BUS/(K_Q*KI_Q)  // Amps*samples
 
-#define I_MAX 40.0f
-#define I_MAX_FW 0.0f
+#define I_MAX 40.0f                 // Max Current
+#define I_MAX_FW 0.0f               // Max field weakening current
+#define I_MAX_CONT 15.0f            // Max continuous current, for thermal limiting
 
 //Observer//
 #define DT 0.000025f
--- a/Config/hw_config.h	Wed Dec 05 04:07:46 2018 +0000
+++ b/Config/hw_config.h	Sun Mar 03 02:51:51 2019 +0000
@@ -7,11 +7,12 @@
 #define ENABLE_PIN PA_11        // Enable gate drive pin
 #define LED         PC_5        // LED Pin
 #define I_SCALE 0.02014160156f  // Amps per A/D Count
-#define V_SCALE 0.00886f        // Bus volts per A/D Count
+#define V_SCALE 0.012890625f     // Bus volts per A/D Count
 #define DTC_MAX 0.94f          // Max phase duty cycle
 #define DTC_MIN 0.0f          // Min phase duty cycle
 #define PWM_ARR 0x8CA           /// timer autoreload value
 
+static float inverter_tab[16] = {2.5f, 2.4f, 2.3f, 2.2f, 2.1f, 2.0f, 1.9f, 1.8f, 1.7f, 1.6f, 1.59f, 1.58f, 1.57f, 1.56f, 1.55f, 1.5f};
 
 
 #endif
--- a/Config/motor_config.h	Wed Dec 05 04:07:46 2018 +0000
+++ b/Config/motor_config.h	Sun Mar 03 02:51:51 2019 +0000
@@ -1,14 +1,16 @@
 #ifndef MOTOR_CONFIG_H
 #define MOTOR_CONFIG_H
 
-#define R_PHASE 0.02f          //Ohms
+#define R_PHASE 0.13f           //Ohms
 #define L_D 0.00002f            //Henries
 #define L_Q 0.00002f            //Henries
 #define KT .08f                 //N-m per peak phase amp, = WB*NPP*3/2
 #define NPP 21                  //Number of pole pairs
 #define GR 1.0f                 //Gear ratio
 #define KT_OUT 0.45f            //KT*GR
-#define WB 0.0024f               //Flux linkage, Webers.  
+#define WB 0.0025f              //Flux linkage, Webers.  
+#define R_TH 1.25f              //Kelvin per watt
+#define INV_M_TH 0.03125f       //Kelvin per joule
 
 
 
--- a/FOC/foc.cpp	Wed Dec 05 04:07:46 2018 +0000
+++ b/FOC/foc.cpp	Sun Mar 03 02:51:51 2019 +0000
@@ -33,7 +33,7 @@
     /// Space Vector Modulation ///
     /// u,v,w amplitude = v_bus for full modulation depth ///
     
-    float v_offset = (fminf3(u, v, w) + fmaxf3(u, v, w))/2.0f;
+    float v_offset = (fminf3(u, v, w) + fmaxf3(u, v, w))*0.5f;
     
     *dtc_u = fminf(fmaxf(((u -v_offset)/v_bus + .5f), DTC_MIN), DTC_MAX);
     *dtc_v = fminf(fmaxf(((v -v_offset)/v_bus + .5f), DTC_MIN), DTC_MAX);
@@ -49,7 +49,19 @@
     
     }
 
-
+void linearize_dtc(float *dtc){
+    /// linearizes the output of the inverter, which is not linear for small duty cycles ///
+    float sgn = 1.0f-(2.0f*(dtc<0));
+    if(abs(*dtc) >= .01f){
+        *dtc = *dtc*.986f+.014f*sgn;
+        }
+    else{
+        *dtc = 2.5f*(*dtc);
+        }
+    
+    }
+    
+    
 void zero_current(int *offset_1, int *offset_2){                                // Measure zero-offset of the current sensors
     int adc1_offset = 0;
     int adc2_offset = 0;
@@ -92,6 +104,11 @@
 
     }
     
+void reset_observer(ObserverStruct *observer){
+    observer->temperature = 25.0f;
+    observer->resistance = .1f;
+    }
+    
 void limit_current_ref (ControllerStruct *controller){
     float i_q_max_limit = (0.5774f*controller->v_bus - controller->dtheta_elec*WB)/R_PHASE;
     float i_q_min_limit = (-0.5774f*controller->v_bus - controller->dtheta_elec*WB)/R_PHASE;
@@ -99,7 +116,24 @@
     }
 
 
-void commutate(ControllerStruct *controller, GPIOStruct *gpio, float theta){
+void commutate(ControllerStruct *controller, ObserverStruct *observer, GPIOStruct *gpio, float theta){
+        
+        /// Update observer estimates ///
+        // Resistance observer //
+        // Temperature Observer //
+        float t_rise = (float)observer->temperature - 25.0f;
+        float q_th_in = (1.0f + .00393f*t_rise)*(controller->i_d*controller->i_d*R_PHASE*1.5f + controller->i_q*controller->i_q*R_PHASE*1.5f);
+        float q_th_out = t_rise*R_TH;
+        observer->temperature += INV_M_TH*DT*(q_th_in-q_th_out);
+        
+        //observer->resistance = (controller->v_q - 2.0f*controller->dtheta_elec*(WB + L_D*controller->i_d))/controller->i_q;
+        observer->resistance = controller->v_q/controller->i_q;
+        if(isnan(observer->resistance)){observer->resistance = R_PHASE;}
+        observer->temperature2 = (double)(25.0f + ((observer->resistance*6.0606f)-1.0f)*275.5f);
+        double e = observer->temperature - observer->temperature2;
+        observer->temperature -= .001*e;
+        //printf("%.3f\n\r", e);
+        
 
        /// Commutation Loop ///
        controller->loop_count ++;   
@@ -124,32 +158,27 @@
         
         
         // Filter the current references to the desired closed-loopbandwidth
-        // Allows calculation of desired di/dt for inductance, etc
-        controller->did_dt = controller->i_d_ref_filt;
-        controller->diq_dt = controller->i_q_ref_filt;
         controller->i_d_ref_filt = (1.0f-controller->alpha)*controller->i_d_ref_filt + controller->alpha*controller->i_d_ref;
         controller->i_q_ref_filt = (1.0f-controller->alpha)*controller->i_q_ref_filt + controller->alpha*controller->i_q_ref;
-        controller->did_dt = (controller->i_d_ref_filt - controller->did_dt)/DT;
-        controller->diq_dt = (controller->i_q_ref_filt - controller->diq_dt)/DT;
+
+       
+       /// Field Weakening ///
+       
+       controller->fw_int += .001f*(0.5f*OVERMODULATION*controller->v_bus - controller->v_ref);
+       controller->fw_int = fmaxf(fminf(controller->fw_int, 0.0f), -I_MAX_FW);
+       controller->i_d_ref = controller->fw_int;
+       //float i_cmd_mag_sq = controller->i_d_ref*controller->i_d_ref + controller->i_q_ref*controller->i_q_ref;
+       limit_norm(&controller->i_d_ref, &controller->i_q_ref, I_MAX);
        
        
-       /// Field Weakening ///
-       /*
-       controller->fw_int += .001*(0.5f*OVERMODULATION*controller->v_bus - controller->v_ref);
-       controller->fw_int = fmaxf(fminf(controller->fw_int, 0.0f), -I_MAX_FW);
-       controller->i_d_ref = controller->fw_int;
-       float i_cmd_mag_sq = controller->i_d_ref*controller->i_d_ref + controller->i_q_ref*controller->i_q_ref;
-       limit_norm(&controller->i_d_ref, &controller->i_q_ref, I_MAX);
-       
-       */
        
        /// PI Controller ///
        float i_d_error = controller->i_d_ref - controller->i_d;
        float i_q_error = controller->i_q_ref - controller->i_q;//  + cogging_current;
        
        // Calculate feed-forward voltages //
-       float v_d_ff = 2.0f*(1.0f*controller->i_d_ref*R_PHASE  - controller->dtheta_elec*L_Q*controller->i_q);   //feed-forward voltages
-       float v_q_ff =  2.0f*(1.0f*controller->i_q_ref*R_PHASE +  controller->dtheta_elec*(L_D*controller->i_d + 1.0f*WB));
+       float v_d_ff = SQRT3*(1.0f*controller->i_d_ref*R_PHASE  - controller->dtheta_elec*L_Q*controller->i_q);   //feed-forward voltages
+       float v_q_ff =  SQRT3*(1.0f*controller->i_q_ref*R_PHASE +  controller->dtheta_elec*(L_D*controller->i_d + 1.0f*WB));
        
        // Integrate Error //
        controller->d_int += controller->k_d*controller->ki_d*i_d_error;   
@@ -165,6 +194,12 @@
        controller->v_ref = sqrt(controller->v_d*controller->v_d + controller->v_q*controller->v_q);
        
        limit_norm(&controller->v_d, &controller->v_q, OVERMODULATION*controller->v_bus);       // Normalize voltage vector to lie within curcle of radius v_bus
+       float dtc_d = controller->v_d/controller->v_bus;
+       float dtc_q = controller->v_q/controller->v_bus;
+       linearize_dtc(&dtc_d);
+       linearize_dtc(&dtc_q);
+       controller->v_d = dtc_d*controller->v_bus;
+       controller->v_q = dtc_q*controller->v_bus;
        abc(controller->theta_elec + 0.0f*DT*controller->dtheta_elec, controller->v_d, controller->v_q, &controller->v_u, &controller->v_v, &controller->v_w); //inverse dq0 transform on voltages
        svm(controller->v_bus, controller->v_u, controller->v_v, controller->v_w, &controller->dtc_u, &controller->dtc_v, &controller->dtc_w); //space vector modulation
 
@@ -179,7 +214,7 @@
             TIM1->CCR2 =  (PWM_ARR)*(1.0f-controller->dtc_w);
         }
 
-       controller->theta_elec = theta;                                          //For some reason putting this at the front breaks thins
+       controller->theta_elec = theta;                                          
        
     }
     
--- a/FOC/foc.h	Wed Dec 05 04:07:46 2018 +0000
+++ b/FOC/foc.h	Sun Mar 03 02:51:51 2019 +0000
@@ -17,8 +17,10 @@
 void svm(float v_bus, float u, float v, float w, float *dtc_u, float *dtc_v, float *dtc_w);
 void zero_current(int *offset_1, int *offset_2);
 void reset_foc(ControllerStruct *controller);
+void reset_observer(ObserverStruct *observer);
 void init_controller_params(ControllerStruct *controller);
-void commutate(ControllerStruct *controller, GPIOStruct *gpio, float theta);
+void commutate(ControllerStruct *controller, ObserverStruct *observer, GPIOStruct *gpio, float theta);
 void torque_control(ControllerStruct *controller);
 void limit_current_ref (ControllerStruct *controller);
+void linearize_dtc(float *dtc);
 #endif
--- a/PositionSensor/PositionSensor.cpp	Wed Dec 05 04:07:46 2018 +0000
+++ b/PositionSensor/PositionSensor.cpp	Sun Mar 03 02:51:51 2019 +0000
@@ -30,7 +30,7 @@
     //raw = spi->write(readAngleCmd);
     //raw &= 0x3FFF;   
     raw = spi->write(0);
-    raw = raw>>1;                                                             //Extract last 14 bits
+    raw = raw>>2;                                                             //Extract last 14 bits
     GPIOA->ODR |= (1 << 15);
     int off_1 = offset_lut[raw>>7];
     int off_2 = offset_lut[((raw>>7)+1)%128];
--- a/main.cpp	Wed Dec 05 04:07:46 2018 +0000
+++ b/main.cpp	Sun Mar 03 02:51:51 2019 +0000
@@ -37,6 +37,7 @@
 
 GPIOStruct gpio;
 ControllerStruct controller;
+ObserverStruct observer;
 COMStruct com;
 Serial pc(PA_2, PA_3);
 
@@ -154,8 +155,8 @@
     }
     
 void print_encoder(void){
-    //printf(" Mechanical Angle:  %f    Electrical Angle:  %f    Raw:  %d\n\r", spi.GetMechPosition(), spi.GetElecPosition(), spi.GetRawPosition());
-    printf("%d\n\r", spi.GetRawPosition());
+    printf(" Mechanical Angle:  %f    Electrical Angle:  %f    Raw:  %d\n\r", spi.GetMechPosition(), spi.GetElecPosition(), spi.GetRawPosition());
+    //printf("%d\n\r", spi.GetRawPosition());
     wait(.001);
     }
 
@@ -177,7 +178,7 @@
         controller.theta_mech = (1.0f/GR)*spi.GetMechPosition();
         controller.dtheta_mech = (1.0f/GR)*spi.GetMechVelocity();  
         controller.dtheta_elec = spi.GetElecVelocity();
-        controller.v_bus = V_BUS;//b0.95f*controller.v_bus + 0.05f*((float)controller.adc3_raw)*V_SCALE;
+        controller.v_bus = 0.95f*controller.v_bus + 0.05f*((float)controller.adc3_raw)*V_SCALE;
         ///
         
         /// Check state machine state, and run the appropriate function ///
@@ -224,16 +225,24 @@
                 
                 //controller.i_q_ref = 2.0f;
                 //controller.i_d_ref = -30.0f;
-                //controller.kd = .1;
+                //controller.kp = 1;
+                //controller.kd = .1f;
                 //controller.v_des = 25;
-                torque_control(&controller);
-                //controller.i_q_ref = 2.0f;
-                //controller.i_d_ref = -20.0f;
-                commutate(&controller, &gpio, controller.theta_elec);           // Run current loop
+                //torque_control(&controller);
+                controller.i_q_ref = 40.0f;
+                //
+                //controller.i_q_ref += .00025f;
+                //if(count>80000)
+                //{
+                //    controller.i_q_ref = 0.0f;
+                //    count = 0;
+                //    }    
+                //controller.i_d_ref = -10.0f;
+                commutate(&controller, &observer, &gpio, controller.theta_elec);           // Run current loop
                 //TIM1->CCR3 = (PWM_ARR)*(0.5f);                        // Write duty cycles
                 //TIM1->CCR2 = (PWM_ARR)*(0.5f);
                 //TIM1->CCR1 = (PWM_ARR)*(0.5f);
-                controller.timeout += 1;
+                controller.timeout++;
 
                 //pc.putc(iq);
                 //pc.putc(id);
@@ -244,15 +253,21 @@
                 count++;
                 
                 /*
-                if(count == 400){
+                if(count == 10000){
                      //printf("%d  %d  %.4f  %.4f  %.4f\n\r", controller.adc1_raw, controller.adc2_raw, controller.i_a, controller.i_b, controller.i_c);
-                     printf("%.2f\n\r", 1000.0f*controller.h1_iq_afc_int1);
+                     //printf("%.2f\n\r", 1000.0f*controller.h1_iq_afc_int1);
                      //pc.putc(id);
                      //pc.putc(iq);
                      //pc.putc(ang);
                      //pc.putc('\n');
                      //pc.putc('\r');
                      //printf("%.1f\n", controller.k_q*controller.ki_q*controller.q_int);
+                     if(controller.i_d_ref< 10.0f)
+                     {
+                        controller.i_d_ref += .05f;
+                    }
+                    else{controller.i_d_ref = 0;}
+                    
                      count = 0;
                      }
                      */
@@ -415,6 +430,7 @@
     gpio.enable->write(0);
     */
     reset_foc(&controller);                                                     // Reset current controller
+    reset_observer(&observer);                                                 // Reset observer
     TIM1->CR1 ^= TIM_CR1_UDIS;
     //TIM1->CR1 |= TIM_CR1_UDIS; //enable interrupt
     
@@ -429,9 +445,15 @@
     rxMsg.len = 8;
     can.attach(&onMsgReceived);                                     // attach 'CAN receive-complete' interrupt handler    
     
+    // If preferences haven't been user configured yet, set defaults 
     prefs.load();                                                               // Read flash
     if(isnan(E_OFFSET)){E_OFFSET = 0.0f;}
     if(isnan(M_OFFSET)){M_OFFSET = 0.0f;}
+    if(isnan(I_BW) || I_BW==-1){I_BW = 1000;}
+    if(isnan(TORQUE_LIMIT) || TORQUE_LIMIT ==-1){TORQUE_LIMIT=18;}
+    if(isnan(CAN_ID) || CAN_ID==-1){CAN_ID = 1;}
+    if(isnan(CAN_MASTER) || CAN_MASTER==-1){CAN_MASTER = 0;}
+    if(isnan(CAN_TIMEOUT) || CAN_TIMEOUT==-1){CAN_TIMEOUT = 0;}
     spi.SetElecOffset(E_OFFSET);                                                // Set position sensor offset
     spi.SetMechOffset(M_OFFSET);
     int lut[128] = {0};
@@ -463,16 +485,27 @@
     pc.attach(&serial_interrupt);                                               // attach serial interrupt
     
     state_change = 1;
-    
+    /*
+    for(int i = 0; i< 1000; i++){
+        float dtc_in = .001f*(float)i;
+        printf("%f  ", dtc_in);
+        linearize_dtc(&dtc_in);
+        printf("%f\n\r", dtc_in);
+        wait(.001);
+        }
+    */
 
     int counter = 0;
     while(1) {
         drv.print_faults();
-       wait(.1);
+       wait(.001);
+       //printf("%.4f\n\r", controller.v_bus);
         if(state == MOTOR_MODE)
         {
-            //printf("%.3f\n\r", controller.dtheta_mech);
-            //wait(.001);
+            //printf("%.3f  %.3f  %.3f\n\r", (float)observer.temperature, (float)observer.temperature2, observer.resistance);
+            //printf("%.3f  %.3f  %.3f\n\r", controller.v_q/controller.v_bus, controller.i_q, observer.resistance);
+            printf("%.3f\n\r", controller.dtheta_mech);
+            wait(.001);
         }
 
     }
--- a/math_ops.h	Wed Dec 05 04:07:46 2018 +0000
+++ b/math_ops.h	Sun Mar 03 02:51:51 2019 +0000
@@ -2,6 +2,7 @@
 #define MATH_OPS_H
 
 #define PI 3.14159265359f
+#define SQRT3 1.73205080757f
 
 #include "math.h"
 
--- a/structs.h	Wed Dec 05 04:07:46 2018 +0000
+++ b/structs.h	Sun Mar 03 02:51:51 2019 +0000
@@ -29,7 +29,6 @@
     float d_int, q_int;                                     // Current error integrals
     int adc1_offset, adc2_offset;                           // ADC offsets
     float i_d_ref, i_q_ref, i_d_ref_filt, i_q_ref_filt;     // Current references
-    float did_dt, diq_dt;                                   // Current reference derivatives
     int loop_count;                                         // Degubbing counter
     int timeout;                                            // Watchdog counter
     int mode;
@@ -40,13 +39,8 @@
     } ControllerStruct;
 
 typedef struct{
-    float h;
-    float k;
-    float phi;
-    float cos_integral;
-    float sin_integral;
-    float afc_out;
-    } AFCStruct;
-
-    
+    double temperature;                                              // Estimated temperature
+    double temperature2;
+    float resistance;
+    }   ObserverStruct;
 #endif