|
@@ -3,16 +3,20 @@
|
|
|
#include "PMSM_FOC_Core.h"
|
|
#include "PMSM_FOC_Core.h"
|
|
|
#include "smo_observer.h"
|
|
#include "smo_observer.h"
|
|
|
|
|
|
|
|
|
|
+#define USE_ARCTAN 1
|
|
|
static smo_observer_t smo;
|
|
static smo_observer_t smo;
|
|
|
-
|
|
|
|
|
static void smo_observer(float uAlpha, float uBeta, float iAlpha, float iBeta);
|
|
static void smo_observer(float uAlpha, float uBeta, float iAlpha, float iBeta);
|
|
|
|
|
+#ifdef USE_ARCTAN
|
|
|
|
|
+static void smo_arctan(void);
|
|
|
|
|
+#else
|
|
|
static void smo_pll(void);
|
|
static void smo_pll(void);
|
|
|
|
|
+#endif
|
|
|
void smo_observer_init(float pll_bandwith, float lpf_wc, float Ksmo, float Ksta) {
|
|
void smo_observer_init(float pll_bandwith, float lpf_wc, float Ksmo, float Ksta) {
|
|
|
- smo.ts = 1.0f/(float)FOC_PWM_FS;
|
|
|
|
|
|
|
+ smo.ts = FOC_CTRL_US;
|
|
|
smo.bandwith = pll_bandwith;
|
|
smo.bandwith = pll_bandwith;
|
|
|
- smo.pll_kp = pll_bandwith * 2 * M_PI * 2;
|
|
|
|
|
|
|
+ smo.pll_kp = pll_bandwith * 2;
|
|
|
smo.pll_ki = 0.25f * SQ(smo.pll_kp);
|
|
smo.pll_ki = 0.25f * SQ(smo.pll_kp);
|
|
|
- smo.pll_max_rad_pers = CONFIG_MAX_MOT_RPM/30.0f * M_PI;
|
|
|
|
|
|
|
+ smo.pll_max_rad_pers = CONFIG_MAX_MOT_RPM/30.0f * M_PI * nv_get_motor_params()->poles;
|
|
|
smo.lpf_wc = lpf_wc;
|
|
smo.lpf_wc = lpf_wc;
|
|
|
smo.lpf_ceof = (lpf_wc*2*M_PI/(float)FOC_PWM_FS);
|
|
smo.lpf_ceof = (lpf_wc*2*M_PI/(float)FOC_PWM_FS);
|
|
|
smo.Ksmo = Ksmo;
|
|
smo.Ksmo = Ksmo;
|
|
@@ -21,15 +25,22 @@ void smo_observer_init(float pll_bandwith, float lpf_wc, float Ksmo, float Ksta)
|
|
|
smo.motor_ld = nv_get_motor_params()->ld;
|
|
smo.motor_ld = nv_get_motor_params()->ld;
|
|
|
smo.motor_lq = nv_get_motor_params()->lq;
|
|
smo.motor_lq = nv_get_motor_params()->lq;
|
|
|
smo.motor_poles = nv_get_motor_params()->poles;
|
|
smo.motor_poles = nv_get_motor_params()->poles;
|
|
|
-
|
|
|
|
|
|
|
+ smo.dir_ccw = true;
|
|
|
smo.ldq_diff_dm = (smo.motor_ld-smo.motor_lq)/smo.motor_lq*smo.motor_ld;
|
|
smo.ldq_diff_dm = (smo.motor_ld-smo.motor_lq)/smo.motor_lq*smo.motor_ld;
|
|
|
smo.ld_inv = 1.0f / smo.motor_ld;
|
|
smo.ld_inv = 1.0f / smo.motor_ld;
|
|
|
|
|
+
|
|
|
|
|
+ smo.pll.DT = smo.ts;
|
|
|
|
|
+ smo.pll.kp = pll_bandwith * 2;
|
|
|
|
|
+ smo.pll.ki = 0.25f * SQ(smo.pll.kp);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
float smo_observer_update(float uAlpha, float uBeta, float iAlpha, float iBeta) {
|
|
float smo_observer_update(float uAlpha, float uBeta, float iAlpha, float iBeta) {
|
|
|
-
|
|
|
|
|
smo_observer(uAlpha, uBeta, iAlpha, iBeta);
|
|
smo_observer(uAlpha, uBeta, iAlpha, iBeta);
|
|
|
|
|
+#ifdef USE_ARCTAN
|
|
|
|
|
+ smo_arctan();
|
|
|
|
|
+#else
|
|
|
smo_pll();
|
|
smo_pll();
|
|
|
|
|
+#endif
|
|
|
return pi_2_degree(smo.est_angle_out);
|
|
return pi_2_degree(smo.est_angle_out);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -60,8 +71,41 @@ static void smo_observer(float uAlpha, float uBeta, float iAlpha, float iBeta) {
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
#define angle_clamp(a) {while (a >= M_PI*2) a-=M_PI*2;while (a < 0) a +=M_PI*2;};
|
|
#define angle_clamp(a) {while (a >= M_PI*2) a-=M_PI*2;while (a < 0) a +=M_PI*2;};
|
|
|
|
|
+#ifdef USE_ARCTAN
|
|
|
|
|
+static void smo_arctan(void) {
|
|
|
|
|
+ float ealpha_in = -smo.est_eAlpha_Filted;
|
|
|
|
|
+ float ebeta_in = smo.est_eBeta_Filted;
|
|
|
|
|
|
|
|
-#define ANGLE_COMP_RPM_CEOF (2.44E-4F)
|
|
|
|
|
|
|
+ float angle = fast_atan_2(ealpha_in, ebeta_in); //通过反正切获取电角度
|
|
|
|
|
+ angle_clamp(angle);
|
|
|
|
|
+ float prev_angle = smo.est_angle;
|
|
|
|
|
+ float comp_angle = 0.0f;
|
|
|
|
|
+ if (smo.dir_ccw) {
|
|
|
|
|
+ if (prev_angle > angle) {
|
|
|
|
|
+ comp_angle = 2 * M_PI;
|
|
|
|
|
+ }
|
|
|
|
|
+ }else {
|
|
|
|
|
+ if (prev_angle < angle) {
|
|
|
|
|
+ comp_angle = -2 * M_PI;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ smo.est_angle = angle;
|
|
|
|
|
+ smo.est_rad_pers = PLL_run(&smo.pll, angle, comp_angle);
|
|
|
|
|
+ if (smo.est_rad_pers > smo.pll_max_rad_pers) {
|
|
|
|
|
+ smo.est_rad_pers = smo.pll_max_rad_pers;
|
|
|
|
|
+ smo.pll.out = smo.est_rad_pers;
|
|
|
|
|
+ }
|
|
|
|
|
+ smo.est_rad_pers_filted = smo.est_rad_pers;
|
|
|
|
|
+ smo.est_angle_out = smo.est_angle + fast_atan_2(smo.est_rad_pers_filted, smo.lpf_wc*2*M_PI);
|
|
|
|
|
+ angle_clamp(smo.est_angle_out);
|
|
|
|
|
+ smo.est_rpm = (30.0f * smo.est_rad_pers_filted/M_PI/smo.motor_poles);
|
|
|
|
|
+ if (smo.est_rpm > CONFIG_MAX_MOT_RPM) {
|
|
|
|
|
+ smo.est_rpm = CONFIG_MAX_MOT_RPM;
|
|
|
|
|
+ }else if (smo.est_rpm < 0) {
|
|
|
|
|
+ smo.est_rpm = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+#else
|
|
|
static void smo_pll(void) {
|
|
static void smo_pll(void) {
|
|
|
float eab_sqr = sqrtf(SQ(smo.est_eAlpha_Filted) + SQ(smo.est_eBeta_Filted) + (1e-10f));
|
|
float eab_sqr = sqrtf(SQ(smo.est_eAlpha_Filted) + SQ(smo.est_eBeta_Filted) + (1e-10f));
|
|
|
float ealpha_in = -smo.est_eAlpha_Filted/eab_sqr;
|
|
float ealpha_in = -smo.est_eAlpha_Filted/eab_sqr;
|
|
@@ -86,12 +130,11 @@ static void smo_pll(void) {
|
|
|
smo.est_rpm = 0;
|
|
smo.est_rpm = 0;
|
|
|
}
|
|
}
|
|
|
/* 对低通进行角度补偿 */
|
|
/* 对低通进行角度补偿 */
|
|
|
- smo.est_angle_out = smo.est_angle;// + fast_arctan2(smo.est_rad_pers_filted, smo.lpf_wc*2*M_PI);
|
|
|
|
|
- /* 通过速度对角度再次补偿, ANGLE_COMP_RPM_CEOF 这个值通过校准获取 */
|
|
|
|
|
- smo.est_angle_out += smo.est_rpm * ANGLE_COMP_RPM_CEOF;
|
|
|
|
|
|
|
+ smo.est_angle_out = smo.est_angle + fast_atan_2(smo.est_rad_pers_filted, smo.lpf_wc*2*M_PI);
|
|
|
|
|
+ //smo.est_angle_out = fast_atan_2(ealpha_in, ebeta_in) + fast_atan_2(smo.est_rad_pers_filted, smo.lpf_wc*2*M_PI);
|
|
|
angle_clamp(smo.est_angle_out);
|
|
angle_clamp(smo.est_angle_out);
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
float smo_observer_est_angle(void) {
|
|
float smo_observer_est_angle(void) {
|
|
|
return pi_2_degree(smo.est_angle_out);
|
|
return pi_2_degree(smo.est_angle_out);
|