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 //printf("%f %f %f\r\n",controller->i_a, controller->i_b, controller->i_c); 00151 00152 float s = FastSin(theta); 00153 float c = FastCos(theta); 00154 dq0(controller->theta_elec, controller->i_a, controller->i_b, controller->i_c, &controller->i_d, &controller->i_q); //dq0 transform on currents 00155 //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 00156 //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); 00157 00158 controller->i_q_filt = 0.95f*controller->i_q_filt + 0.05f*controller->i_q; 00159 controller->i_d_filt = 0.95f*controller->i_d_filt + 0.05f*controller->i_d; 00160 //printf("%f, %f, %f, %f, %f\r\n",controller->i_a, controller->i_b, controller->i_c, controller->i_d_filt, controller->i_q_filt); 00161 00162 // Filter the current references to the desired closed-loop bandwidth 00163 controller->i_d_ref_filt = (1.0f-controller->alpha)*controller->i_d_ref_filt + controller->alpha*controller->i_d_ref; 00164 controller->i_q_ref_filt = (1.0f-controller->alpha)*controller->i_q_ref_filt + controller->alpha*controller->i_q_ref; 00165 00166 00167 /// Field Weakening /// 00168 00169 controller->fw_int += .001f*(0.5f*OVERMODULATION*controller->v_bus - controller->v_ref); 00170 controller->fw_int = fmaxf(fminf(controller->fw_int, 0.0f), -I_FW_MAX); 00171 controller->i_d_ref = controller->fw_int; 00172 //float i_cmd_mag_sq = controller->i_d_ref*controller->i_d_ref + controller->i_q_ref*controller->i_q_ref; 00173 limit_norm(&controller->i_d_ref, &controller->i_q_ref, I_MAX); 00174 00175 00176 00177 /// PI Controller /// 00178 float i_d_error = controller->i_d_ref - controller->i_d; 00179 float i_q_error = controller->i_q_ref - controller->i_q;// + cogging_current; 00180 00181 // Calculate feed-forward voltages // 00182 float v_d_ff = SQRT3*(1.0f*controller->i_d_ref*R_PHASE - controller->dtheta_elec*L_Q*controller->i_q); //feed-forward voltages 00183 float v_q_ff = SQRT3*(1.0f*controller->i_q_ref*R_PHASE + controller->dtheta_elec*(L_D*controller->i_d + 1.0f*WB)); 00184 00185 // Integrate Error // 00186 controller->d_int += controller->k_d*controller->ki_d*i_d_error; 00187 controller->q_int += controller->k_q*controller->ki_q*i_q_error; 00188 00189 controller->d_int = fmaxf(fminf(controller->d_int, OVERMODULATION*controller->v_bus), - OVERMODULATION*controller->v_bus); 00190 controller->q_int = fmaxf(fminf(controller->q_int, OVERMODULATION*controller->v_bus), - OVERMODULATION*controller->v_bus); 00191 00192 //limit_norm(&controller->d_int, &controller->q_int, OVERMODULATION*controller->v_bus); 00193 controller->v_d = controller->k_d*i_d_error + controller->d_int ;//+ v_d_ff; 00194 controller->v_q = controller->k_q*i_q_error + controller->q_int ;//+ v_q_ff; 00195 00196 controller->v_ref = sqrt(controller->v_d*controller->v_d + controller->v_q*controller->v_q); 00197 00198 limit_norm(&controller->v_d, &controller->v_q, OVERMODULATION*controller->v_bus); // Normalize voltage vector to lie within curcle of radius v_bus 00199 //float dtc_d = controller->v_d/controller->v_bus; 00200 //float dtc_q = controller->v_q/controller->v_bus; 00201 //linearize_dtc(&dtc_d); 00202 //linearize_dtc(&dtc_q); 00203 //controller->v_d = dtc_d*controller->v_bus; 00204 //controller->v_q = dtc_q*controller->v_bus; 00205 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 00206 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 00207 00208 if(PHASE_ORDER){ // Check which phase order to use, 00209 TIM1->CCR3 = (PWM_ARR)*(1.0f-controller->dtc_u); // Write duty cycles 00210 TIM1->CCR2 = (PWM_ARR)*(1.0f-controller->dtc_v); 00211 TIM1->CCR1 = (PWM_ARR)*(1.0f-controller->dtc_w); 00212 } 00213 else{ 00214 TIM1->CCR3 = (PWM_ARR)*(1.0f-controller->dtc_u); 00215 TIM1->CCR1 = (PWM_ARR)*(1.0f-controller->dtc_v); 00216 TIM1->CCR2 = (PWM_ARR)*(1.0f-controller->dtc_w); 00217 } 00218 00219 controller->theta_elec = theta; 00220 00221 } 00222 00223 00224 void torque_control(ControllerStruct *controller){ 00225 float torque_ref = controller->kp*(controller->p_des - controller->theta_mech) + controller->t_ff + controller->kd*(controller->v_des - controller->dtheta_mech); 00226 //float torque_ref = -.1*(controller->p_des - controller->theta_mech); 00227 controller->i_q_ref = torque_ref/KT_OUT; 00228 controller->i_d_ref = 0.0f; 00229 //printf("pos:%f vel:%f Kp:%f Kd:%f t_ff:%f\r\n",controller->p_des,controller->v_des,controller->kp,controller->kd,controller->t_ff); 00230 } 00231
Generated on Sun Jul 17 2022 04:45:41 by
1.7.2