smo_observer.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. #include "app/nv_storage.h"
  2. #include "math/fast_math.h"
  3. #include "PMSM_FOC_Core.h"
  4. #include "smo_observer.h"
  5. #define USE_ARCTAN 1
  6. static smo_observer_t smo;
  7. static void smo_observer(float uAlpha, float uBeta, float iAlpha, float iBeta);
  8. #ifdef USE_ARCTAN
  9. static void smo_arctan(void);
  10. #else
  11. static void smo_pll(void);
  12. #endif
  13. void smo_observer_init(float pll_bandwith, float lpf_wc, float Ksmo, float Ksta) {
  14. smo.ts = FOC_CTRL_US;
  15. smo.bandwith = pll_bandwith;
  16. smo.pll_kp = pll_bandwith * 2;
  17. smo.pll_ki = 0.25f * SQ(smo.pll_kp);
  18. smo.pll_max_rad_pers = CONFIG_MAX_MOT_RPM/30.0f * M_PI * nv_get_motor_params()->poles;
  19. smo.lpf_wc = lpf_wc;
  20. smo.lpf_ceof = (lpf_wc*2*M_PI/(float)FOC_PWM_FS);
  21. smo.Ksmo = Ksmo;
  22. smo.Ksta = Ksta;
  23. smo.motor_r = nv_get_motor_params()->r;
  24. smo.motor_ld = nv_get_motor_params()->ld;
  25. smo.motor_lq = nv_get_motor_params()->lq;
  26. smo.motor_poles = nv_get_motor_params()->poles;
  27. smo.dir_ccw = true;
  28. smo.ldq_diff_dm = (smo.motor_ld-smo.motor_lq)/smo.motor_lq*smo.motor_ld;
  29. smo.ld_inv = 1.0f / smo.motor_ld;
  30. smo.pll.DT = smo.ts;
  31. smo.pll.kp = pll_bandwith * 2;
  32. smo.pll.ki = 0.25f * SQ(smo.pll.kp);
  33. }
  34. float smo_observer_update(float uAlpha, float uBeta, float iAlpha, float iBeta) {
  35. smo_observer(uAlpha, uBeta, iAlpha, iBeta);
  36. #ifdef USE_ARCTAN
  37. smo_arctan();
  38. #else
  39. smo_pll();
  40. #endif
  41. return pi_2_degree(smo.est_angle_out);
  42. }
  43. smo_observer_t *get_smo(void) {
  44. return &smo;
  45. }
  46. static void smo_observer(float uAlpha, float uBeta, float iAlpha, float iBeta) {
  47. float est_ab = smo.ldq_diff_dm * smo.est_rad_pers;//(smo.motor_ld-smo.motor_lq)/smo.motor_lq * smo.est_rad_pers;
  48. /* est alpha back emf */
  49. float calc_alpha = (uAlpha - smo.Ialpha_hat*smo.motor_r - smo.est_eAlpha - est_ab * smo.IBeta_hat) * smo.ld_inv;
  50. smo.Ialpha_hat += calc_alpha * smo.ts; //积分
  51. float err_iAlpha = smo.Ialpha_hat - iAlpha;
  52. smo.est_eAlpha = fclamp(err_iAlpha, -smo.Ksta, smo.Ksta) * smo.Ksmo;
  53. smo.est_eAlpha_Filted = do_lpf(smo.est_eAlpha_Filted, smo.est_eAlpha, smo.lpf_ceof);
  54. /* est beta back emf */
  55. float calc_beta = (uBeta - smo.IBeta_hat*smo.motor_r - smo.est_eBeta + est_ab * smo.Ialpha_hat) * smo.ld_inv;
  56. smo.IBeta_hat += calc_beta * smo.ts; //积分
  57. float err_iBeta = smo.IBeta_hat - iBeta;
  58. smo.est_eBeta = fclamp(err_iBeta, -smo.Ksta, smo.Ksta) * smo.Ksmo;
  59. smo.est_eBeta_Filted = do_lpf(smo.est_eBeta_Filted, smo.est_eBeta, smo.lpf_ceof);
  60. }
  61. #define angle_clamp(a) {while (a >= M_PI*2) a-=M_PI*2;while (a < 0) a +=M_PI*2;};
  62. #ifdef USE_ARCTAN
  63. static void smo_arctan(void) {
  64. float ealpha_in = -smo.est_eAlpha_Filted;
  65. float ebeta_in = smo.est_eBeta_Filted;
  66. float angle = fast_atan_2(ealpha_in, ebeta_in); //通过反正切获取电角度
  67. angle_clamp(angle);
  68. float prev_angle = smo.est_angle;
  69. float comp_angle = 0.0f;
  70. if (smo.dir_ccw) {
  71. if (prev_angle > angle) {
  72. comp_angle = 2 * M_PI;
  73. }
  74. }else {
  75. if (prev_angle < angle) {
  76. comp_angle = -2 * M_PI;
  77. }
  78. }
  79. smo.est_angle = angle;
  80. smo.est_rad_pers = PLL_run(&smo.pll, angle, comp_angle);
  81. if (smo.est_rad_pers > smo.pll_max_rad_pers) {
  82. smo.est_rad_pers = smo.pll_max_rad_pers;
  83. smo.pll.out = smo.est_rad_pers;
  84. }
  85. smo.est_rad_pers_filted = smo.est_rad_pers;
  86. smo.est_angle_out = smo.est_angle + fast_atan_2(smo.est_rad_pers_filted, smo.lpf_wc*2*M_PI);
  87. angle_clamp(smo.est_angle_out);
  88. smo.est_rpm = (30.0f * smo.est_rad_pers_filted/M_PI/smo.motor_poles);
  89. if (smo.est_rpm > CONFIG_MAX_MOT_RPM) {
  90. smo.est_rpm = CONFIG_MAX_MOT_RPM;
  91. }else if (smo.est_rpm < 0) {
  92. smo.est_rpm = 0;
  93. }
  94. }
  95. #else
  96. static void smo_pll(void) {
  97. float eab_sqr = sqrtf(SQ(smo.est_eAlpha_Filted) + SQ(smo.est_eBeta_Filted) + (1e-10f));
  98. float ealpha_in = -smo.est_eAlpha_Filted/eab_sqr;
  99. float ebeta_in = smo.est_eBeta_Filted/eab_sqr;
  100. float sin, cos;
  101. float angle_rad = pi_2_degree(smo.est_angle);
  102. arm_sin_cos_f32(angle_rad, &sin, &cos);
  103. float pi_err = cos * ealpha_in - sin * ebeta_in;
  104. float perr = pi_err * smo.pll_kp;
  105. smo.est_rad_pers = perr + smo.pll_integrator; //计算角速度
  106. if (smo.pll_integrator < smo.pll_max_rad_pers) {
  107. smo.pll_integrator += smo.ts * pi_err * smo.pll_ki; //更新pll的pi的积分xiang
  108. }
  109. smo.est_rad_pers_filted = do_lpf(smo.est_rad_pers_filted, smo.est_rad_pers, smo.lpf_ceof); //对速度低通滤波
  110. smo.est_angle += smo.ts * smo.est_rad_pers; //角速度积分
  111. angle_clamp(smo.est_angle);
  112. smo.est_rpm = (30.0f * smo.est_rad_pers_filted/M_PI/smo.motor_poles);
  113. if (smo.est_rpm > CONFIG_MAX_MOT_RPM) {
  114. smo.est_rpm = CONFIG_MAX_MOT_RPM;
  115. }else if (smo.est_rpm < 0) {
  116. smo.est_rpm = 0;
  117. }
  118. /* 对低通进行角度补偿 */
  119. smo.est_angle_out = smo.est_angle + fast_atan_2(smo.est_rad_pers_filted, smo.lpf_wc*2*M_PI);
  120. //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);
  121. angle_clamp(smo.est_angle_out);
  122. }
  123. #endif
  124. float smo_observer_est_angle(void) {
  125. return pi_2_degree(smo.est_angle_out);
  126. }
  127. //机械角度 rpm
  128. float smo_observer_est_rpm(void) {
  129. return smo.est_rpm;
  130. }