smo_observer.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. #include "foc/mc_config.h"
  2. #include "math/fast_math.h"
  3. #include "controller.h"
  4. #include "smo_observer.h"
  5. #define USE_ARCTAN 0
  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 = CONFIG_SENSORLESS_TS;
  15. smo.bandwith = pll_bandwith;
  16. smo.pll_kp = pll_bandwith * 2;
  17. smo.pll_ki = SQ(pll_bandwith);
  18. smo.pll_max_rad_pers = CONFIG_HW_MAX_MOTOR_RPM/30.0f * M_PI * mc_conf()->m.poles;
  19. smo.lpf_wc = lpf_wc;
  20. smo.lpf_ceof = (lpf_wc*smo.ts);
  21. smo.Ksmo = Ksmo;
  22. smo.Ksta = Ksta;
  23. smo.motor_r = mc_conf()->m.rs;
  24. smo.motor_ld = mc_conf()->m.ld;
  25. smo.motor_lq = mc_conf()->m.lq;
  26. smo.motor_poles = mc_conf()->m.poles;
  27. smo.dir_ccw = true;
  28. PLL_Reset(&smo.pll, 0);
  29. smo.pll.ts = smo.ts;
  30. smo.pll.kp = pll_bandwith * 2;
  31. smo.pll.ki = 0.25f * SQ(smo.pll.kp);
  32. }
  33. float smo_observer_update(float uAlpha, float uBeta, float iAlpha, float iBeta) {
  34. smo_observer(uAlpha, uBeta, iAlpha, iBeta);
  35. #ifdef USE_ARCTAN
  36. smo_arctan();
  37. #else
  38. smo_pll();
  39. #endif
  40. return pi_2_degree(smo.est_angle_out);
  41. }
  42. smo_observer_t *get_smo(void) {
  43. return &smo;
  44. }
  45. static __INLINE float line_func(float err, float max, float slide) {
  46. float err_abs = ABS(err);
  47. if (err_abs > max) {
  48. return (err>0)?slide:-slide;
  49. }else {
  50. return (err * slide)/max;
  51. }
  52. }
  53. static void smo_observer(float uAlpha, float uBeta, float iAlpha, float iBeta) {
  54. float est_ab = smo.est_rad_pers_filted * (smo.motor_ld - smo.motor_lq);
  55. /* est alpha back emf */
  56. float Ialpha_hat = smo.Ialpha_hat;
  57. float calc_alpha = (uAlpha - smo.Ialpha_hat*smo.motor_r - smo.est_eAlpha - est_ab * smo.IBeta_hat) / smo.motor_ld ;
  58. smo.Ialpha_hat += calc_alpha * smo.ts; //积分
  59. float err_iAlpha = smo.Ialpha_hat - iAlpha;
  60. smo.est_eAlpha = line_func(err_iAlpha, smo.Ksta, smo.Ksmo);//fclamp(err_iAlpha, -smo.Ksta, smo.Ksta) * smo.Ksmo;
  61. #ifdef USE_ARCTAN
  62. smo.est_eAlpha_Filted = do_lpf(smo.est_eAlpha_Filted, smo.est_eAlpha, smo.lpf_ceof);
  63. #else
  64. smo.est_eAlpha_Filted = smo.est_eAlpha;
  65. #endif
  66. /* est beta back emf */
  67. float calc_beta = (uBeta - smo.IBeta_hat*smo.motor_r - smo.est_eBeta + est_ab * Ialpha_hat) / smo.motor_ld;
  68. smo.IBeta_hat += calc_beta * smo.ts; //积分
  69. float err_iBeta = smo.IBeta_hat - iBeta;
  70. smo.est_eBeta = line_func(err_iBeta, smo.Ksta, smo.Ksmo);//fclamp(err_iBeta, -smo.Ksta, smo.Ksta) * smo.Ksmo;
  71. #ifdef USE_ARCTAN
  72. smo.est_eBeta_Filted = do_lpf(smo.est_eBeta_Filted, smo.est_eBeta, smo.lpf_ceof);
  73. #else
  74. smo.est_eBeta_Filted = smo.est_eBeta;
  75. #endif
  76. }
  77. #ifdef USE_ARCTAN
  78. static void smo_arctan(void) {
  79. float ealpha_in = -smo.est_eAlpha_Filted;
  80. float ebeta_in = smo.est_eBeta_Filted;
  81. float angle = fast_atan2(ealpha_in, ebeta_in); //通过反正切获取电角度
  82. UTILS_NAN_ZERO(angle);
  83. norm_angle_rad(angle);
  84. float prev_angle = smo.est_angle;
  85. float comp_angle = 0.0f;
  86. if (smo.dir_ccw) {
  87. if ((prev_angle > angle) && (prev_angle > M_PI && angle < M_PI)) {//wrapper
  88. comp_angle = 2 * M_PI;
  89. }
  90. }else {
  91. if ((prev_angle < angle) && (prev_angle < M_PI && angle > M_PI)) {//wrapper
  92. comp_angle = -2 * M_PI;
  93. }
  94. }
  95. smo.est_angle = angle;
  96. smo.est_rad_pers = PLL_run(&smo.pll, angle, comp_angle);
  97. if (smo.est_rad_pers > smo.pll_max_rad_pers) {
  98. smo.est_rad_pers = smo.pll_max_rad_pers;
  99. smo.pll.out = smo.est_rad_pers;
  100. }
  101. smo.est_rad_pers_filted = smo.est_rad_pers;
  102. /*低通滤波有相位滞后,需要补偿,同时电流和电压滞后一个控制周期,需要通过当前的电角速度对计算的角度进行补偿 */
  103. smo.est_angle_out = smo.est_angle + fast_atan2(smo.est_rad_pers_filted, smo.lpf_wc) + smo.est_rad_pers_filted * smo.ts;
  104. norm_angle_rad(smo.est_angle_out);
  105. smo.est_rpm = (30.0f * smo.est_rad_pers_filted/M_PI/smo.motor_poles);
  106. if (smo.est_rpm > CONFIG_HW_MAX_MOTOR_RPM) {
  107. smo.est_rpm = CONFIG_HW_MAX_MOTOR_RPM;
  108. }else if (smo.est_rpm < 0) {
  109. smo.est_rpm = 0;
  110. }
  111. }
  112. #else
  113. static void smo_pll(void) {
  114. float eab_sqr = NORM2_f(smo.est_eAlpha_Filted, smo.est_eBeta_Filted) + (1e-10f));
  115. float ealpha_in = -smo.est_eAlpha_Filted/eab_sqr;
  116. float ebeta_in = smo.est_eBeta_Filted/eab_sqr;
  117. float sin, cos;
  118. float angle_rad = pi_2_degree(smo.est_angle);
  119. arm_sin_cos_f32(angle_rad, &sin, &cos);
  120. float pi_err = cos * ealpha_in - sin * ebeta_in;
  121. float perr = pi_err * smo.pll_kp;
  122. if (smo.pll_integrator < smo.pll_max_rad_pers) {
  123. smo.pll_integrator += smo.ts * pi_err * smo.pll_ki; //更新pll的pi的积分xiang
  124. }
  125. smo.est_rad_pers = perr + smo.pll_integrator; //计算角速度
  126. smo.est_angle += smo.ts * smo.est_rad_pers; //角速度积分
  127. smo.est_rad_pers_filted = do_lpf(smo.est_rad_pers_filted, smo.est_rad_pers, smo.lpf_ceof); //对速度低通滤波
  128. norm_angle_rad(smo.est_angle);
  129. smo.est_rpm = (30.0f * smo.est_rad_pers_filted/M_PI/smo.motor_poles);
  130. if (smo.est_rpm > CONFIG_HW_MAX_MOTOR_RPM) {
  131. smo.est_rpm = CONFIG_HW_MAX_MOTOR_RPM;
  132. }else if (smo.est_rpm < 0) {
  133. smo.est_rpm = 0;
  134. }
  135. /* 电流和电压滞后一个控制周期,需要通过当前的电角速度对计算的角度进行补偿 */
  136. smo.est_angle_out = smo.est_angle + smo.est_rad_pers_filted * smo.ts;
  137. norm_angle_rad(smo.est_angle_out);
  138. }
  139. #endif
  140. float smo_observer_angle(void) {
  141. return pi_2_degree(smo.est_angle_out);
  142. }
  143. //机械角度 rpm
  144. float smo_observer_vel(void) {
  145. return smo.est_rpm;
  146. }