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