#include "IQmathLib.h" #include "alg_pll.h" #include "params_pll.h" #include "params_norma.h" //#define NORMA_ACP 3000 //#define FREQ_PWM_VIPR 1975 //#define SIZE_PLL_AVG 50 //_iq w_in_avg[SIZE_PLL_AVG]; //_iq w_out_avg[SIZE_PLL_AVG]; #define DETECT_PLL_D (2000.0/NORMA_ACP) // ampl #define DETECT_PLL_Q (500.0/NORMA_ACP) // zero _iq iqDetect_PLL_d=_IQ(DETECT_PLL_D); _iq iqDetect_PLL_q=_IQ(DETECT_PLL_Q); #define MAX_COUNT_ERR_PLL 5000 //20 #ifdef USE_SMOOTH_FOR_CALC_WC SMOOTH mysmooth=SMOOTH_DEFAULTS; #endif // /////////////////////////////////////////// //PLL_REC pll2 = PLL_REC_DEFAULT; /////////////////////////////////////////// ABC_TO_ALPHABETA abc_to_alphabeta_u_input = ABC_TO_ALPHABETA_DEFAULTS; ALPHABETA_TO_DQ alphabeta_to_dq_u_input = ALPHABETA_TO_DQ_DEFAULTS; PIDREG3 pidUdq = PIDREG3_DEFAULTS; //int count_wait_pll=0; int count_err_pll = 0; //int c_start=0; //int c_stop=0; #define MAX_TIME_WAIT_PLL 5000 //_iq iqUab=0, iqUbc=0, iqUca=0; //_iq koef_Um_filter = _IQ(0.000125/0.09); //_iq koef_AddIq_minus_1_filter = _IQ(0.00034/0.009);//9576244354248046875 #pragma CODE_SECTION(minus_plus_2_pi,".fast_run"); _iq minus_plus_2_pi(_iq a) { while (a>=CONST_IQ_2PI) a -= CONST_IQ_2PI; while (a<=-CONST_IQ_2PI) a += CONST_IQ_2PI; return a; } #pragma CODE_SECTION(minus_plus_2_pi_v2,".fast_run"); _iq minus_plus_2_pi_v2(_iq a) { while (a>=CONST_IQ_2PI) a -= CONST_IQ_2PI; while (a<0) a += CONST_IQ_2PI; return a; } #pragma CODE_SECTION(AB_BC_CA_To_ABC,".fast_run"); void AB_BC_CA_To_ABC(_iq U_AB, _iq U_BC, _iq U_CA, _iq *Ua, _iq *Ub, _iq *Uc) { // static _iq c2 = _IQ(2.0); // static _iq c13_sqrt = _IQ(1.7320508075688772935274463415059 / 3.0); *Ua = U_AB; *Ub = U_BC; *Uc = U_CA; /* *Ua = _IQmpy(c13_sqrt, (_IQmpy(c2,U_AB)+U_BC));// 2*U_AB/3+U_BC/3; *Ub = _IQmpy(c13_sqrt, (_IQmpy(c2,U_BC)+U_CA));// 2*U_BC/3+U_CA/3; *Uc = _IQmpy(c13_sqrt, (_IQmpy(c2,U_CA)+U_AB));// 2*U_CA/3+U_AB/3; */ } ///////////////////////////////////////////////// #pragma CODE_SECTION(PLLController,".fast_run"); ///////////////////////////////////////////////// void PLLController(PLL_REC *v) { static unsigned int count_wait_pll=0; static _iq prev_Tetta_z=0; _iq Tetta_z_t=0; static int prev_flag_find_pll = 0; static int flag_reset_Tetta_p = 0; // static _iq prev_Tetta_v2 = 0; v->vars.Uab = v->input.Input_U_AB - v->vars.iqZeroUAB; v->vars.Ubc = v->input.Input_U_BC - v->vars.iqZeroUBC; v->vars.Uca = v->input.Input_U_CA - v->vars.iqZeroUCA; v->vars.sum_zeroU_AB_BC_CA = v->vars.Uab + v->vars.Ubc + v->vars.Uca; if (v->setup.rotation_u_cba) { AB_BC_CA_To_ABC(v->vars.Uab, v->vars.Uca, v->vars.Ubc, &v->vars.Ua, &v->vars.Ub, &v->vars.Uc); } else { AB_BC_CA_To_ABC(v->vars.Uab,v->vars.Ubc,v->vars.Uca, &v->vars.Ua, &v->vars.Ub, &v->vars.Uc); } #ifdef ROTATION_U_CBA #else #endif v->vars.sum_zeroU_A_B_C = v->vars.Ua + v->vars.Ub + v->vars.Uc; abc_to_alphabeta_u_input.Ua = v->vars.Ua; abc_to_alphabeta_u_input.Ub = v->vars.Ub; abc_to_alphabeta_u_input.Uc = v->vars.Uc; abc_to_alphabeta_u_input.calc(&abc_to_alphabeta_u_input); v->vars.Ualpha = abc_to_alphabeta_u_input.Ualpha; v->vars.Ubeta = abc_to_alphabeta_u_input.Ubeta; alphabeta_to_dq_u_input.Ualpha = v->vars.Ualpha; alphabeta_to_dq_u_input.Ubeta = v->vars.Ubeta; alphabeta_to_dq_u_input.Tetta = v->vars.Tetta; alphabeta_to_dq_u_input.calc(&alphabeta_to_dq_u_input); v->vars.pll_Ud = alphabeta_to_dq_u_input.Ud; v->vars.pll_Uq = alphabeta_to_dq_u_input.Uq; // pidUdq.Fdb = v->pll_Ud;//.pll_Uq; //err = Ref - Fdb // pidUdq.Ref = 0; pidUdq.Ref = v->vars.pll_Uq; //err = Ref - Fdb pidUdq.Fdb = 0; pidUdq.calc(&pidUdq); v->vars.wc = pidUdq.Out; if (prev_flag_find_pll==0) { flag_reset_Tetta_p = 0; } if (v->output.flag_find_pll) { #ifdef USE_SMOOTH_FOR_CALC_WC mysmooth.input = _IQtoIQ23(v->vars.wc); mysmooth.add(&mysmooth); mysmooth.calc(&mysmooth); v->vars.w_shtrih = _IQ23toIQ(mysmooth.av); #else v->vars.w_shtrih = v->vars.wc; #endif } else { v->vars.w_shtrih = v->vars.wc; } v->vars.Tetta += v->vars.wc; v->vars.Tetta = minus_plus_2_pi(v->vars.Tetta); // +- 2PI if (v->output.flag_find_pll) { v->vars.dwc = v->vars.wc - v->vars.w_shtrih; v->vars.Tetta_p += v->vars.dwc; v->vars.Tetta_p = minus_plus_2_pi(v->vars.Tetta_p); // +- 2PI v->vars.dTetta = v->vars.Tetta - v->vars.Tetta_p;// + iq_05Pi; v->vars.dTetta = minus_plus_2_pi(v->vars.dTetta); // +- 2PI v->vars.Tetta_z = v->vars.dTetta; // if (v->Tetta_z>=iq_05Pi && prev_Tetta_zTetta_p = 0; Tetta_z_t = minus_plus_2_pi_v2(v->vars.Tetta_z); if ( (Tetta_z_t>=0) && (Tetta_z_t(CONST_IQ_2PI-CONST_IQ_PI05)) ) ) { if (flag_reset_Tetta_p==0) { v->vars.Tetta_p = 0; // flag_reset_Tetta_p = 1; } } prev_Tetta_z = Tetta_z_t; #ifdef USE_FILTER_TETTA //use filter teta v->vars.Tetta_v2 = v->vars.Tetta_z;//v->Tetta; #else //use mgnoven teta v->vars.Tetta_v2 = v->vars.Tetta; #endif v->vars.delta_Tetta_c = v->vars.Tetta_z - v->vars.Tetta; // prev_Tetta_v2 = v->Tetta_v2; } else { v->vars.Tetta_v2 = v->vars.Tetta; flag_reset_Tetta_p = 0; } // PLL OK? //count_wait_pll=0 //new alg find pll if (v->vars.w_shtrih >= v->vars.find_min_w_strih && v->vars.w_shtrih <= v->vars.find_max_w_strih) { if (v->vars.count_wait_pll_w_shtrih < v->vars.max_time_wait_pll_w_strih) v->vars.count_wait_pll_w_shtrih++; } else { if (v->vars.count_wait_pll_w_shtrih>0) v->vars.count_wait_pll_w_shtrih--; } if (v->vars.count_wait_pll_w_shtrih == v->vars.max_time_wait_pll_w_strih) v->output.flag_find_pll = 1; if (v->vars.count_wait_pll_w_shtrih == 0) v->output.flag_find_pll = 0; //end new alg find pll if ( (_IQabs(v->vars.pll_Uq)<=_IQabs(iqDetect_PLL_q)) // zero && (_IQabs(v->vars.pll_Ud)>=_IQabs(iqDetect_PLL_d) ) //ampl ) { count_err_pll=0; if (count_wait_plloutput.flag_find_pll = 1; } else { if (count_err_pll>=MAX_COUNT_ERR_PLL) { // fail find pll count_wait_pll=0; v->output.flag_find_pll = 0; if (v->output.flag_find_pll==1) { v->vars.pll_Uq = 0; v->vars.pll_Ud = 0; } } else { count_err_pll++; if ((v->output.flag_find_pll==0) && (count_wait_pll>0)) count_wait_pll--; } } // end PLL Ok? v->vars.pi_teta_u_out = pidUdq.Out; v->vars.pi_teta_u_i = pidUdq.Ui; v->vars.pi_teta_u_p = pidUdq.Up; prev_flag_find_pll = v->output.flag_find_pll; } ////////////////////////////////////////////////// ////////////////////////////////////////////////// ////////////////////////////////////////////////// ///////////////////////////////////////////////// //#pragma CODE_SECTION(pll_get_freq,".fast_run"); ///////////////////////////////////////////////// void pll_get_freq_float(PLL_REC *v) { if (v->output.flag_find_pll) { v->output.int_freq_net = _IQtoF( v->vars.w_shtrih) * v->setup.freq_run_pll / PI * 50.00; // freq*100 } else { v->output.int_freq_net = 0; } } ////////////////////////////////////////////////// ////////////////////////////////////////////////// void pll_get_freq_iq(PLL_REC *v) { if (v->output.flag_find_pll) { v->output.iq_freq_net = v->vars.w_shtrih;//_IQtoF( v->vars.w_shtrih) * v->setup.freq_run_pll / PI * 50.00; // freq*100 } else { v->output.iq_freq_net = 0; } } ////////////////////////////////////////////////// //#pragma CODE_SECTION(detect_phase_count,".fast_run"); void detect_phase_count(PLL_REC *v) { static _iq prev_Ua = 0; static int prev_flag_find_pll=0; // abc_to_dq.Ua if ((v->output.flag_find_pll != prev_flag_find_pll) && (v->output.flag_find_pll == 1)) { prev_Ua = v->vars.Ua; v->vars.enable_detect_phase_count = 1; v->vars.error_phase_count = 0; } if (v->output.flag_find_pll==0) v->vars.enable_detect_phase_count = 0; if (v->output.flag_find_pll) { if (v->vars.enable_detect_phase_count) { if ( (prev_Ua<0) && (v->vars.Ua>=0) ) { if (v->vars.Uc > v->vars.Ub) v->vars.enable_detect_phase_count = 0; if (v->vars.Ub > v->vars.Uc) { v->vars.enable_detect_phase_count = 0; v->vars.error_phase_count = 1; } } } } prev_flag_find_pll = v->output.flag_find_pll; prev_Ua = v->vars.Ua; } ///////////////////////////////////////////////// //////////////////////////////////////////////// #pragma CODE_SECTION(Find_zero_Uabc,".fast_run"); void Find_zero_Uabc(PLL_REC *v) { static int c_a=0; // static int c_b=0; // static int c_c=0; static _iq sum_a=0; static _iq sum_b=0; static _iq sum_c=0; _iq22 sum_t,c_t; _iq22 sum_div; // AB_BC_CA_To_ABC(analog.iqUin_AB-iqZeroUABC, analog.iqUin_BC-iqZeroUABC, analog.iqUin_CA-iqZeroUABC); sum_a += v->input.Input_U_AB; // analog.iqUin_AB; sum_b += v->input.Input_U_BC; // analog.iqUin_BC; sum_c += v->input.Input_U_CA; // analog.iqUin_CA; c_a++; if (c_a >= v->vars.count_sum_find_zero_uabc) { sum_div = v->vars.sum_div_find_zero_uabc; sum_t = _IQtoIQ22(sum_a); c_t = _IQ22div(sum_t,sum_div); v->vars.iqZeroUAB = _IQ22toIQ(c_t); sum_t = _IQtoIQ22(sum_b); c_t = _IQ22div(sum_t,sum_div); v->vars.iqZeroUBC = _IQ22toIQ(c_t); sum_t = _IQtoIQ22(sum_c); c_t = _IQ22div(sum_t,sum_div); v->vars.iqZeroUCA = _IQ22toIQ(c_t); sum_a = 0; sum_b = 0; sum_c = 0; c_a = 0; } } void pll_init(PLL_REC *v) { v->output.status = STATUS_PLL_NOT_INITED; abc_to_alphabeta_u_input.Ua = 0; abc_to_alphabeta_u_input.Ub = 0; abc_to_alphabeta_u_input.Uc = 0; abc_to_alphabeta_u_input.Ualpha = 0; abc_to_alphabeta_u_input.Ubeta = 0; alphabeta_to_dq_u_input.Tetta = 0; alphabeta_to_dq_u_input.Ualpha = 0; alphabeta_to_dq_u_input.Ubeta = 0; alphabeta_to_dq_u_input.Ud = 0; alphabeta_to_dq_u_input.Uq = 0; v->vars.count_wait_pll_w_shtrih = 0; v->vars.pll_Ud = 0; v->vars.pll_Uq = 0; v->vars.Tetta = 0; v->vars.Tetta_p = 0; v->vars.Ua = 0; v->vars.Ub = 0; v->vars.Uc = 0; v->vars.Ualpha = 0; v->vars.Ubeta = 0; // count_wait_pll = 0; count_err_pll = 0; v->output.flag_find_pll = 0; pidUdq.Kp = _IQ(v->setup.pid_kp_pll); pidUdq.Ki = _IQ(v->setup.pid_ki_pll); pidUdq.Kc = _IQ(PID_KC_PLL); pidUdq.Kd = _IQ(0.0); pidUdq.OutMax = _IQ(K_PLL_MAX); pidUdq.OutMin = _IQ(K_PLL_MIN); pidUdq.Err = 0; pidUdq.Out = 0; pidUdq.OutPreSat = 0; pidUdq.SatErr = 0; if (v->setup.freq_run_pll == 0) v->setup.freq_run_pll = DEFAULT_FREQ_RUN_PLL; pidUdq.Ui = _IQ(2.0*PI*DEFAULT_FREQ_NET/(v->setup.freq_run_pll)); // iqDetect_PLL_d = iqDetect_PLL_d; // iqDetect_PLL_q = iqDetect_PLL_q; #ifdef USE_SMOOTH_FOR_CALC_WC mysmooth.init(&mysmooth); #endif v->vars.count_sum_find_zero_uabc = v->setup.freq_run_pll/DEFAULT_FREQ_NET; //79*2 //1975/50*2 v->vars.sum_div_find_zero_uabc = _IQ22(v->vars.count_sum_find_zero_uabc); v->vars.find_max_w_strih = _IQ(FIND_MAX_W_STRIH*2.0*PI*DEFAULT_FREQ_NET/(v->setup.freq_run_pll)); v->vars.find_min_w_strih = _IQ(FIND_MIN_W_STRIH*2.0*PI*DEFAULT_FREQ_NET/(v->setup.freq_run_pll)); v->vars.max_time_wait_pll_w_strih = (v->vars.count_sum_find_zero_uabc * MAX_PERIOD_WAIT_PLL_W_SHTRIH); v->output.status = STATUS_PLL_INITED; } #pragma CODE_SECTION(read_error_find_pll,".fast_run2"); int read_error_find_pll(PLL_REC *v) { // static int enable_detect_pll_err=0; // static int prev_flag_find_pll=0; static int err_pll=0; err_pll = 0; /* if ((v->output.flag_find_pll!=prev_flag_find_pll) && (v->output.flag_find_pll==1)) { enable_detect_pll_err = 1; } prev_flag_find_pll = v->output.flag_find_pll; if (v->input.enable_find_pll==0) enable_detect_pll_err = 0; if ((enable_detect_pll_err) && (v->output.flag_find_pll==0) && (v->input.enable_find_pll==1)) { err_pll = 1; } */ return err_pll; } #pragma CODE_SECTION(pll_calc,".fast_run"); void pll_calc(PLL_REC *v) { if (v->output.status >= STATUS_PLL_INITED) { Find_zero_Uabc(v); PLLController(v); // detect_phase_count(v); v->output.status = STATUS_PLL_OK; } }