Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
foc.cpp
00001 00002 #include "foc.h" 00003 using namespace FastMath; 00004 00005 00006 void abc( float theta, float d, float q, float *a, float *b, float *c){ 00007 /// Inverse DQ0 Transform /// 00008 ///Phase current amplitude = lengh of dq vector/// 00009 ///i.e. iq = 1, id = 0, peak phase current of 1/// 00010 float cf = FastCos(theta); 00011 float sf = FastSin(theta); 00012 00013 *a = cf*d - sf*q; // Faster Inverse DQ0 transform 00014 *b = (0.86602540378f*sf-.5f*cf)*d - (-0.86602540378f*cf-.5f*sf)*q; 00015 *c = (-0.86602540378f*sf-.5f*cf)*d - (0.86602540378f*cf-.5f*sf)*q; 00016 } 00017 00018 00019 void dq0(float theta, float a, float b, float c, float *d, float *q){ 00020 /// DQ0 Transform /// 00021 ///Phase current amplitude = lengh of dq vector/// 00022 ///i.e. iq = 1, id = 0, peak phase current of 1/// 00023 00024 float cf = FastCos(theta); 00025 float sf = FastSin(theta); 00026 00027 *d = 0.6666667f*(cf*a + (0.86602540378f*sf-.5f*cf)*b + (-0.86602540378f*sf-.5f*cf)*c); ///Faster DQ0 Transform 00028 *q = 0.6666667f*(-sf*a - (-0.86602540378f*cf-.5f*sf)*b - (0.86602540378f*cf-.5f*sf)*c); 00029 00030 } 00031 00032 void svm(float v_bus, float u, float v, float w, float *dtc_u, float *dtc_v, float *dtc_w){ 00033 /// Space Vector Modulation /// 00034 /// u,v,w amplitude = v_bus for full modulation depth /// 00035 00036 float v_offset = (fminf3(u, v, w) + fmaxf3(u, v, w))*0.5f; 00037 00038 *dtc_u = fminf(fmaxf(((u -v_offset)/v_bus + .5f), DTC_MIN), DTC_MAX); 00039 *dtc_v = fminf(fmaxf(((v -v_offset)/v_bus + .5f), DTC_MIN), DTC_MAX); 00040 *dtc_w = fminf(fmaxf(((w -v_offset)/v_bus + .5f), DTC_MIN), DTC_MAX); 00041 00042 /* 00043 sinusoidal pwm 00044 *dtc_u = fminf(fmaxf((u/v_bus + .5f), DTC_MIN), DTC_MAX); 00045 *dtc_v = fminf(fmaxf((v/v_bus + .5f), DTC_MIN), DTC_MAX); 00046 *dtc_w = fminf(fmaxf((w/v_bus + .5f), DTC_MIN), DTC_MAX); 00047 */ 00048 00049 00050 } 00051 00052 void linearize_dtc(float *dtc){ 00053 /// linearizes the output of the inverter, which is not linear for small duty cycles /// 00054 float sgn = 1.0f-(2.0f*(dtc<0)); 00055 if(abs(*dtc) >= .01f){ 00056 *dtc = *dtc*.986f+.014f*sgn; 00057 } 00058 else{ 00059 *dtc = 2.5f*(*dtc); 00060 } 00061 00062 } 00063 00064 00065 void zero_current(int *offset_1, int *offset_2){ // Measure zero-offset of the current sensors 00066 int adc1_offset = 0; 00067 int adc2_offset = 0; 00068 int n = 1024; 00069 for (int i = 0; i<n; i++){ // Average n samples of the ADC 00070 TIM1->CCR3 = (PWM_ARR>>1)*(1.0f); // Write duty cycles 00071 TIM1->CCR2 = (PWM_ARR>>1)*(1.0f); 00072 TIM1->CCR1 = (PWM_ARR>>1)*(1.0f); 00073 ADC1->CR2 |= 0x40000000; // Begin sample and conversion 00074 wait(.001); 00075 adc2_offset += ADC2->DR; 00076 adc1_offset += ADC1->DR; 00077 } 00078 *offset_1 = adc1_offset/n; 00079 *offset_2 = adc2_offset/n; 00080 } 00081 00082 void init_controller_params(ControllerStruct *controller){ 00083 controller->ki_d = KI_D; 00084 controller->ki_q = KI_Q; 00085 controller->k_d = K_SCALE*I_BW; 00086 controller->k_q = K_SCALE*I_BW; 00087 controller->alpha = 1.0f - 1.0f/(1.0f - DT*I_BW*2.0f*PI); 00088 00089 } 00090 00091 void reset_foc(ControllerStruct *controller){ 00092 TIM1->CCR3 = (PWM_ARR>>1)*(0.5f); 00093 TIM1->CCR1 = (PWM_ARR>>1)*(0.5f); 00094 TIM1->CCR2 = (PWM_ARR>>1)*(0.5f); 00095 controller->i_d_ref = 0; 00096 controller->i_q_ref = 0; 00097 controller->i_d = 0; 00098 controller->i_q = 0; 00099 controller->i_q_filt = 0; 00100 controller->q_int = 0; 00101 controller->d_int = 0; 00102 controller->v_q = 0; 00103 controller->v_d = 0; 00104 00105 } 00106 00107 void reset_observer(ObserverStruct *observer){ 00108 observer->temperature = 25.0f; 00109 observer->resistance = .1f; 00110 } 00111 00112 void limit_current_ref (ControllerStruct *controller){ 00113 float i_q_max_limit = (0.5774f*controller->v_bus - controller->dtheta_elec*WB)/R_PHASE; 00114 float i_q_min_limit = (-0.5774f*controller->v_bus - controller->dtheta_elec*WB)/R_PHASE; 00115 controller->i_q_ref = fmaxf(fminf(i_q_max_limit, controller->i_q_ref), i_q_min_limit); 00116 } 00117 00118 00119 void commutate(ControllerStruct *controller, ObserverStruct *observer, GPIOStruct *gpio, float theta){ 00120 00121 /// Update observer estimates /// 00122 // Resistance observer // 00123 // Temperature Observer // 00124 float t_rise = (float)observer->temperature - 25.0f; 00125 float q_th_in = (1.0f + .00393f*t_rise)*(controller->i_d*controller->i_d*R_PHASE*SQRT3 + controller->i_q*controller->i_q*R_PHASE*SQRT3); 00126 float q_th_out = t_rise*R_TH; 00127 observer->temperature += INV_M_TH*DT*(q_th_in-q_th_out); 00128 00129 observer->resistance = (controller->v_q - SQRT3*controller->dtheta_elec*(WB))/controller->i_q; 00130 //observer->resistance = controller->v_q/controller->i_q; 00131 if(isnan(observer->resistance)){observer->resistance = R_PHASE;} 00132 observer->temperature2 = (double)(25.0f + ((observer->resistance*6.0606f)-1.0f)*275.5f); 00133 double e = observer->temperature - observer->temperature2; 00134 observer->temperature -= .001*e; 00135 //printf("%.3f\n\r", e); 00136 00137 00138 /// Commutation Loop /// 00139 controller->loop_count ++; 00140 if(PHASE_ORDER){ // Check current sensor ordering 00141 controller->i_b = I_SCALE*(float)(controller->adc2_raw - controller->adc2_offset); // Calculate phase currents from ADC readings 00142 controller->i_c = I_SCALE*(float)(controller->adc1_raw - controller->adc1_offset); 00143 } 00144 else{ 00145 controller->i_b = I_SCALE*(float)(controller->adc1_raw - controller->adc1_offset); 00146 controller->i_c = I_SCALE*(float)(controller->adc2_raw - controller->adc2_offset); 00147 } 00148 controller->i_a = -controller->i_b - controller->i_c; 00149 00150 float s = FastSin(theta); 00151 float c = FastCos(theta); 00152 dq0(controller->theta_elec, controller->i_a, controller->i_b, controller->i_c, &controller->i_d, &controller->i_q); //dq0 transform on currents 00153 //controller->i_d = 0.6666667f*(c*controller->i_a + (0.86602540378f*s-.5f*c)*controller->i_b + (-0.86602540378f*s-.5f*c)*controller->i_c); ///Faster DQ0 Transform 00154 //controller->i_q = 0.6666667f*(-s*controller->i_a - (-0.86602540378f*c-.5f*s)*controller->i_b - (0.86602540378f*c-.5f*s)*controller->i_c); 00155 00156 controller->i_q_filt = 0.95f*controller->i_q_filt + 0.05f*controller->i_q; 00157 controller->i_d_filt = 0.95f*controller->i_d_filt + 0.05f*controller->i_d; 00158 00159 00160 // Filter the current references to the desired closed-loop bandwidth 00161 controller->i_d_ref_filt = (1.0f-controller->alpha)*controller->i_d_ref_filt + controller->alpha*controller->i_d_ref; 00162 controller->i_q_ref_filt = (1.0f-controller->alpha)*controller->i_q_ref_filt + controller->alpha*controller->i_q_ref; 00163 00164 00165 /// Field Weakening /// 00166 00167 controller->fw_int += .001f*(0.5f*OVERMODULATION*controller->v_bus - controller->v_ref); 00168 controller->fw_int = fmaxf(fminf(controller->fw_int, 0.0f), -I_FW_MAX); 00169 controller->i_d_ref = controller->fw_int; 00170 //float i_cmd_mag_sq = controller->i_d_ref*controller->i_d_ref + controller->i_q_ref*controller->i_q_ref; 00171 limit_norm(&controller->i_d_ref, &controller->i_q_ref, I_MAX); 00172 00173 00174 00175 /// PI Controller /// 00176 float i_d_error = controller->i_d_ref - controller->i_d; 00177 float i_q_error = controller->i_q_ref - controller->i_q;// + cogging_current; 00178 00179 // Calculate feed-forward voltages // 00180 float v_d_ff = SQRT3*(1.0f*controller->i_d_ref*R_PHASE - controller->dtheta_elec*L_Q*controller->i_q); //feed-forward voltages 00181 float v_q_ff = SQRT3*(1.0f*controller->i_q_ref*R_PHASE + controller->dtheta_elec*(L_D*controller->i_d + 1.0f*WB)); 00182 00183 // Integrate Error // 00184 controller->d_int += controller->k_d*controller->ki_d*i_d_error; 00185 controller->q_int += controller->k_q*controller->ki_q*i_q_error; 00186 00187 controller->d_int = fmaxf(fminf(controller->d_int, OVERMODULATION*controller->v_bus), - OVERMODULATION*controller->v_bus); 00188 controller->q_int = fmaxf(fminf(controller->q_int, OVERMODULATION*controller->v_bus), - OVERMODULATION*controller->v_bus); 00189 00190 //limit_norm(&controller->d_int, &controller->q_int, OVERMODULATION*controller->v_bus); 00191 controller->v_d = controller->k_d*i_d_error + controller->d_int ;//+ v_d_ff; 00192 controller->v_q = controller->k_q*i_q_error + controller->q_int ;//+ v_q_ff; 00193 00194 controller->v_ref = sqrt(controller->v_d*controller->v_d + controller->v_q*controller->v_q); 00195 00196 limit_norm(&controller->v_d, &controller->v_q, OVERMODULATION*controller->v_bus); // Normalize voltage vector to lie within curcle of radius v_bus 00197 float dtc_d = controller->v_d/controller->v_bus; 00198 float dtc_q = controller->v_q/controller->v_bus; 00199 linearize_dtc(&dtc_d); 00200 linearize_dtc(&dtc_q); 00201 controller->v_d = dtc_d*controller->v_bus; 00202 controller->v_q = dtc_q*controller->v_bus; 00203 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 00204 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 00205 00206 if(PHASE_ORDER){ // Check which phase order to use, 00207 TIM1->CCR3 = (PWM_ARR)*(1.0f-controller->dtc_u); // Write duty cycles 00208 TIM1->CCR2 = (PWM_ARR)*(1.0f-controller->dtc_v); 00209 TIM1->CCR1 = (PWM_ARR)*(1.0f-controller->dtc_w); 00210 } 00211 else{ 00212 TIM1->CCR3 = (PWM_ARR)*(1.0f-controller->dtc_u); 00213 TIM1->CCR1 = (PWM_ARR)*(1.0f-controller->dtc_v); 00214 TIM1->CCR2 = (PWM_ARR)*(1.0f-controller->dtc_w); 00215 } 00216 00217 controller->theta_elec = theta; 00218 00219 } 00220 00221 00222 void torque_control(ControllerStruct *controller){ 00223 float torque_ref = controller->kp*(controller->p_des - controller->theta_mech) + controller->t_ff + controller->kd*(controller->v_des - controller->dtheta_mech); 00224 //float torque_ref = -.1*(controller->p_des - controller->theta_mech); 00225 controller->i_q_ref = torque_ref/KT_OUT; 00226 controller->i_d_ref = 0.0f; 00227 } 00228
Generated on Thu Jun 15 2023 06:56:49 by
1.7.2