ladrc_observer.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. #include "ladrc_observer.h"
  2. #include "foc/mc_config.h"
  3. #include "math/fast_math.h"
  4. #include "libs/logger.h"
  5. static ladrc_observer observer;
  6. #define angle_clamp(a) {while (a >= M_PI*2) a-=M_PI*2;while (a < 0) a +=M_PI*2;};
  7. static __inline float ladrc_observer_band(float vel) {
  8. float ration = vel / observer.vel_min;
  9. float Wo = observer.Wo;
  10. if (ration > 7.0f) { //限制最高带宽,实际调试
  11. ration = 7.0f;
  12. }else if (ration < 0.1f) {
  13. ration = 0.1f;
  14. }
  15. Wo = ration * Wo;
  16. observer.B1 = 2 * Wo;
  17. observer.B2 = SQ(Wo);
  18. return Wo;
  19. }
  20. void ladrc_observer_init(float Wo, float vel_min, float lpf_cut_off) {
  21. observer.Wo = Wo;
  22. observer.vel_min = vel_min;
  23. observer.ts = CONFIG_SENSORLESS_TS;
  24. observer.lpf_ceof = lpf_cut_off * observer.ts;
  25. observer.ld = mc_conf()->m.ld;
  26. observer.lq = mc_conf()->m.lq;
  27. observer.r = mc_conf()->m.rs;
  28. observer.poles = mc_conf()->m.poles;
  29. observer.max_eVel = CONFIG_HW_MAX_MOTOR_RPM/30.0f * M_PI * mc_conf()->m.poles;
  30. observer.max_z1 = CONFIG_HW_MAX_PHASE_CURR * 10.0f;
  31. observer.max_z2 = CONFIG_MAX_ACTIVE_EMF / observer.ld;
  32. observer.Vel_El = 0;
  33. observer.Vel_El_filter = 0;
  34. observer.angle_atan = 0;
  35. observer.angle_out = 0;
  36. observer.alpha.z1 = 0;
  37. observer.alpha.z2 = 0;
  38. observer.beta.z1 = 0;
  39. observer.beta.z2 = 0;
  40. observer.Ealpha = 0;
  41. observer.Ebeta = 0;
  42. observer.angle_idx = 0;
  43. observer.angle_sum = 0;
  44. for (int i = 0; i < ANGLE_BUF_NUM; i++) {
  45. observer.angle_array[i] = 0;
  46. }
  47. ladrc_observer_band(0);
  48. }
  49. float ladrc_observer_update(float va, float vb, float ia, float ib) {
  50. float induct = observer.Vel_El * (observer.ld - observer.lq) / observer.ld;
  51. /* update Wc for current est vel */
  52. float Wo = ladrc_observer_band(observer.Vel_El_filter);
  53. /* est alpha emf */
  54. float F0 = -observer.r/observer.ld * ia;
  55. float e = observer.alpha.z1 - ia;
  56. float alpha_z1 = observer.alpha.z1;
  57. observer.alpha.z2 += (-e * observer.B2) * observer.ts;
  58. observer.alpha.z2 = fclamp(observer.alpha.z2, -observer.max_z2, observer.max_z2);
  59. observer.alpha.z1 += (observer.alpha.z2 + F0 + va/observer.ld - e * observer.B1 - induct * observer.beta.z1) * observer.ts;
  60. observer.alpha.z1 = fclamp(observer.alpha.z1, -observer.max_z1, observer.max_z1);
  61. observer.Ealpha = observer.alpha.z2 * (-observer.ld);
  62. /* est beta emf */
  63. F0 = -observer.r/observer.ld * ib;
  64. e = observer.beta.z1 - ib;
  65. observer.beta.z2 += (-e * observer.B2) * observer.ts;
  66. observer.beta.z2 = fclamp(observer.beta.z2, -observer.max_z2, observer.max_z2);
  67. observer.beta.z1 += (observer.beta.z2 + F0 + vb/observer.ld - e * observer.B1 + induct * alpha_z1) * observer.ts;
  68. observer.beta.z1 = fclamp(observer.beta.z1, -observer.max_z1, observer.max_z1);
  69. observer.Ebeta = observer.beta.z2 * (-observer.ld);
  70. float angle = fast_atan_2(-observer.Ealpha, observer.Ebeta);
  71. UTILS_NAN_ZERO(angle);
  72. angle_clamp(angle);
  73. /* 速度计算 */
  74. float delta_angle = angle - observer.angle_atan;
  75. float delta_angle_abs = ABS(delta_angle);
  76. if (delta_angle_abs >= M_PI) {
  77. delta_angle = 2 * M_PI - delta_angle_abs;
  78. }
  79. observer.angle_atan = angle;
  80. observer.angle_sum += delta_angle;
  81. observer.angle_sum -= observer.angle_array[observer.angle_idx];
  82. observer.angle_array[observer.angle_idx] = delta_angle;
  83. if (++observer.angle_idx == ANGLE_BUF_NUM) {
  84. observer.angle_idx = 0;
  85. }
  86. float vel = observer.angle_sum / (ANGLE_BUF_NUM * observer.ts);
  87. if (vel > observer.max_eVel) {
  88. vel = observer.max_eVel;
  89. }else if (vel < -observer.max_eVel) {
  90. vel = -observer.max_eVel;
  91. }
  92. LowPass_Filter(observer.Vel_El, vel, observer.lpf_ceof);
  93. /* 补偿ladrc相位延时,LADRC等效截止频率为Wo/2pi的两个低通滤波器串联 */
  94. angle = fast_atan_2(observer.Vel_El, Wo) * 2.0f;
  95. /* 电压滞后一个控制周期,需要通过当前的电角速度对计算的角度进行补偿 */
  96. observer.angle_out = observer.angle_atan + (angle + 0/*observer.Vel_El * observer.ts*/);
  97. angle_clamp(observer.angle_out);
  98. LowPass_Filter(observer.Vel_El_filter, observer.Vel_El, 0.01f); //需要再加一级低通滤波,给计算Wo和输出使用
  99. return pi_2_degree(observer.angle_out);
  100. }
  101. float ladrc_observer_angle(void) {
  102. return pi_2_degree(observer.angle_out);
  103. }
  104. float ladrc_observer_vel(void) {
  105. return (observer.Vel_El_filter * (30.0f / M_PI) / observer.poles);
  106. }
  107. ladrc_observer *ladrc_observer_get(void) {
  108. return &observer;
  109. }