/************************************ Extended Kalman Filter Kalman Observer Z. Peroutka Rev. 15.3.2008 EKF pocitan s daty ve formatu Q15, zatimco regulace pracuje v Q13 -> resenim je vynasobit referencni hodnoty v EKF 4-mi (tim je automaticky zajisten prechod mezi formaty Q13 a Q15). Realizovano konstantou K_PREVOD_FORM. 15.3.2008 Kontrola kodu + zamena datovych typu q15->int a q30->long. *************************************/ #include #include "fixed.h" //#include "parametry_motoru.h" // aktivovat v DSP #include "reference.h" #include "matrix.h" #include "ekf.h" #define K_PREVOD_FORM 4 // 2^(15-Qm) /* Declaration of global functions */ void init_ekf(double Tv, double *param); void ekf(double *x_estimation, double Umd, double beta, double Ucnd, double Ucd, double isxd, double isyd); /* Declaration of local functions */ static void prediction(int *ux); static void correction(void); static void update_psi(void); // global variables double ladeni_EKF[10]; /* Constants - definovat jako konstanty ?? ?kde je vyhodnejsi aby v pameti byli?*/ static int H[8]={0x7FFF,0,0,0,0,0x7FFF,0,0}; /* matrix [2,4] */ static int Ht[8]={0x7FFF,0,0,0x7FFF,0,0,0,0};/* matrix [4,2] */ //static int Q[4][4]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /* matrix [4,4] */ //static int R[2][2]={0,0,0,0}; /* matrix [2,2] */ static int Q[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /* matrix [4,4] */ static int R[4]={0,0,0,0}; /* matrix [2,2] */ /* Initial conditions and variables */ static int x_est[4]={0,0,0,0}; static int x_pred[4]={0,0,0,0}; static int P_pred[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /* matrix [4,4] */ //static int P_est[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /* matrix [4,4] */ static int P_est[16]={0x7FFF,0,0,0,0,0x7FFF,0,0,0,0,0x7FFF,0,0,0,0,0x7FFF}; /* matrix [4,4] */ static int Y_mes[2]={0,0}; static int ukalm[2]={0,0}; static int Kalm[8]; /* matrix [5,2] */ static int PSI[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /* matrix [4,4] */ /* Temporary variables */ static int temp15a[16]; // constants of PMSM mathematical model static int cA, cB, cC, cG, cH; // cD, cE, cF, cI ... nepouzivane ////////////////////////////////////////////////////////////////////////////////////////////////////// void init_ekf(double Tv, double *param) { // parametry simulace - v DSP vyhodit (nahrazeno "parametry_motoru.h") double Rs, Ls, Fmag, kp, p; // param=[Rs, Ls, Fmag, Bf, p, kp, J = 0.04?]; Rs=*param; Ls=*(param+1); Fmag=*(param+2); p=*(param+4); kp=*(param+5); /// KONEC inicializace pro PC - az sem vyhodit v DSP /// // Tuning of matrix Q /* Q[0][0]=prevod(.05,15); // 1e-2 Q[1][1]=Q[0][0]; Q[2][2]=prevod(1e-3,15); // 10e-5 Q[3][3]=prevod(1e-3,15); // model(ureg) ... 4e-3 // Tuning of matrix R R[0][0]=prevod(0.05,15); // model(ureg) ... 0.1 R[1][1]=R[0][0]; /**/ // Tuning of matrix Q Q[0]=prevod(.01,15); // 0.05 Q[5]=Q[0]; Q[10]=prevod(0.0001,15); // 1e-3 Q[15]=prevod(0.0001,15); // 1e-3 // Tuning of matrix R R[0]=prevod(0.05,15); // 0.05 R[3]=R[0]; /**/ /* Tuning of matrix P_est - initial values */ /* P_est[0][0]=prevod(0.999,15); P_est[1][1]=prevod(0.999,15); P_est[2][2]=prevod(0.999,15); P_est[3][3]=prevod(0.999,15); P_est[4][4]=prevod(0.999,15); /**/ // Motor model parameters cA=prevod(1-Tv*Rs/Ls,15); cB=prevod(Tv*Wref*Fmag/Iref/Ls,15); cC=prevod(Tv/Ls/Iref*Uref,15); // cD=prevod(1-Tv*Bf/J,15); // cE=prevod(kp*p*p*Tv*Fmag*Iref/J/Wref,15); // cF=prevod(p*Tv*Mref/J/Wref,15); cG=prevod(Tv*Wref*K_PREVOD_FORM/Thetaref,15); cH=prevod(Tv*Wref*Fmag/Iref/Ls*Thetaref,15); // cI=prevod(kp*p*p*Tv*Fmag*Iref/J/Wref*Thetaref); /* Init matrix PSI with permanently constant terms */ PSI[0]=cA; PSI[5]=PSI[0]; PSI[10]=0x7FFF; PSI[14]=cG; PSI[15]=0x7FFF; } static void update_psi(void) { int t_sin,t_cos,tmp; // implementace v PC t_sin=prevod(sin(Thetaref*x_est[3]/32768.),15); t_cos=prevod(cos(Thetaref*x_est[3]/32768.),15); // implementace v DSP // t_sin=qsin(x_est[3]); // t_cos=qcos(x_est[3]); PSI[2]=((long)cB*t_sin)>>15; tmp=((long)cH*x_est[2])>>15; PSI[3]=((long)tmp*t_cos)>>15; PSI[6]=-((long)cB*t_cos)>>15; PSI[7]=((long)tmp*t_sin)>>15; } void prediction(int *ux) { int t_sin,t_cos, tmp; // implementace v PC t_sin=prevod(sin(Thetaref*x_est[3]/32768.),15); t_cos=prevod(cos(Thetaref*x_est[3]/32768.),15); // implementace v DSP // t_sin=qsin(x_est[3]); // t_cos=qcos(x_est[3]); tmp=((long)cB*x_est[2])>>15; x_pred[0]=((long)cA*x_est[0]+(long)tmp*t_sin+(long)cC*ux[0])>>15; x_pred[1]=((long)cA*x_est[1]-(long)tmp*t_cos+(long)cC*ux[1])>>15; x_pred[2]=x_est[2]; x_pred[3]=(((long)x_est[3]<<15)+(long)cG*x_est[2])>>15; update_psi(); mmult(PSI,P_est,temp15a,3,3,3); // mtrans(PSI,temp15b,5,5); mmultt(temp15a,PSI,P_pred,3,3,3); maddD(P_pred,Q,3,3); } void correction(void) { int Y_error[2]; long temp30a[4]; /* matrix [2,2] - temporary matrix for inversion */ /* Kalman gain calculation */ // mmult(P_pred,Ht,temp15a,5,5,2); /* mmultt(P_pred,H,temp15a,4,4,1); mmult(H,temp15a,temp15b,1,4,1); these lines are replaced by choice_P */ choice_P(P_pred,temp15a,3); maddD(temp15a,R,1,1); minv2(temp15a,temp30a); /* mmultt(P_pred,H,temp15a,4,4,1); /* remove this line if choice_P is not used */ // mmultDr15(P_pred,Ht,temp15a,4,4,1,1); mmultDr(P_pred,temp15a,3,3,1,1); mmult1530(temp15a,temp30a,Kalm,3,1,1); /* estimate the state system */ // mmult(H,x_pred,temp15a,1,4,0); choice_x(x_pred, temp15a); msub(Y_mes,temp15a,Y_error,1,0); mmult(Kalm,Y_error,temp15a,3,1,0); madd(x_pred,temp15a,x_est,3,0); /* matrix of covariances - version without MMULTDL() */ /* mmult(Kalm,H,temp15a,4,1,4); mmult(temp15a,P_pred,P_est,4,4,4); msub(P_pred,P_est,P_est,4,4); /* END */ /* Version with MMULTDL() */ mmultDl(P_pred,temp15a,1,3,3,1); /* if result matrix has more terms than DIAG matrix,it is necessary to enable erase sequence in definition of function MMULTDL() that is currently disabled. */ mmult(Kalm,temp15a,P_est,3,1,3); msub(P_pred,P_est,P_est,3,3); /* END */ } void ekf(double *x_estimation, double Umd, double beta, double Ucnd, double Ucd, double isxd, double isyd) { int Umk, ua, ub; /// prechod ze simulace do fixed-pointu - vyradit v DSP /////////// int Um, Ucn, Uc, isx, isy, t_cos; Um=prevod(Umd/Uref,Qm); Ucn=prevod(Ucnd/Uref,Qm); Uc=prevod(Ucd/Uref,Qm); isx=prevod(isxd/Iref,Qm); isy=prevod(isyd/Iref,Qm); /// KONEC emulace FIXED-POINTu - az sem vyradit v DSP //////////// // prepocet napeti pro EKF dle skutecneho napeti v ss obvodu Umk=((long)Um*Uc)/Ucn; // vypocet fazovych napeti stridace ua=((long)Umk*prevod(cos(beta),15))>>15; ub=((long)Umk*prevod(cos(beta-2./3.*M_PI),15))>>15; // uc=((long)Umk*prevod(cos(beta+2./3.*M_PI),15))>>15; // vypocet napeti v systemu (x,y) ukalm[0]=ua; ukalm[1]=(((long)ua+ub<<1)*18917)>>15; // usy=(ua+2*ub)/sqrt(3) // zadani mereni Y_mes[0]=isx; Y_mes[1]=isy; ////// vlastni rutina EKF ///////////////////////// prediction(ukalm); correction(); // navrat estimovanych hodnot regulatoru *x_estimation=zprevod(x_est[2],Qm)*Wref; // x_est[3]=(short int)x_est[3]; *(x_estimation+1)=zprevod((short int)x_est[3],15)*Thetaref; }