foc_task.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. #include "hal/hal.h"
  2. #include "hal/pwm.h"
  3. #include "libs/task.h"
  4. #include "foc_task.h"
  5. #include "foc.h"
  6. #include "phase_current.h"
  7. #include "park_clark.h"
  8. #include "hall_sensor.h"
  9. #include "svpwm.h"
  10. #if 1
  11. static void __inline foc_update_theta(motor_foc_t *foc) {
  12. float angle = 0.0f;
  13. if (foc->override.is_theta) {
  14. angle = foc->override.theta;
  15. }else {
  16. angle = hall_sensor_get_theta();
  17. }
  18. foc->motor_s.angle = angle;
  19. foc->motor_s.theta = degree_2_pi(foc->motor_s.angle);
  20. }
  21. #else
  22. static void __inline foc_update_theta(motor_foc_t *foc) {
  23. static float angle = 0.0f;
  24. static bool first_s = false;
  25. if (!first_s) {
  26. first_s = true;
  27. angle = hall_sensor_get_theta();
  28. }else {
  29. angle += 0.5f;
  30. }
  31. fast_norm_angle(&angle);
  32. foc->motor_s.angle = angle;
  33. foc->motor_s.theta = degree_2_pi(angle);
  34. }
  35. #endif
  36. /* 输出dq电压给反park,最后给svpwm */
  37. static void __inline Foc_Dq_PI_Contrl(motor_foc_t *foc, dq_t *sampled, dq_t *ref_out) {
  38. if (foc->mode == FOC_MODE_PI_DQ || foc->mode == FOC_MODE_PI_FULL) {
  39. ref_out->d = pi_control(&foc->PI_id, foc->dq_ref.d - sampled->d);
  40. ref_out->q = pi_control(&foc->PI_iq, foc->dq_ref.q - sampled->q);
  41. }else {
  42. ref_out->d = foc->dq_ref.d;
  43. ref_out->q = foc->dq_ref.q;
  44. }
  45. if (foc->override.is_vdq) {
  46. ref_out->d = foc->override.vdq.d;
  47. ref_out->q = foc->override.vdq.q;
  48. }
  49. }
  50. static void __inline DeadTime_Compensation(current_samp_t *c_sample, phase_time_t *time) {
  51. #if 0
  52. /* Dead time compensation */
  53. if ( c_sample->Ia > 0)
  54. {
  55. time->A += TDead;
  56. }
  57. else
  58. {
  59. time->A -= TDead;
  60. }
  61. if ( c_sample->Ib > 0 )
  62. {
  63. time->B += TDead;
  64. }
  65. else
  66. {
  67. time->B -= TDead;
  68. }
  69. if ( c_sample->Ic > 0 )
  70. {
  71. time->C += TDead;
  72. }
  73. else
  74. {
  75. time->C -= TDead;
  76. }
  77. #endif
  78. }
  79. static void __inline Debug_Log(motor_foc_t *foc){
  80. #if 0
  81. static int count;
  82. if (count++ % 10 == 0) {
  83. //printf("$%d %d %d %d %d;",(int)(foc->current_samp.Ia * 1000.0f), (int)(foc->current_samp.Ib * 1000.0f),
  84. // (int)(foc->current_samp.Ic * 1000.0f), (int)foc->sector * 100, (int)foc->motor_s.angle);
  85. printf("$%d;", (int)hall_sensor_get_speed());
  86. }
  87. #endif
  88. }
  89. static void __inline Debug_dq(dq_t *dq){
  90. #if 0
  91. static int count;
  92. if (count++ % 10 == 0) {
  93. printf("$%d %d;",(int)(dq->d * 1000.0f), (int)(dq->q * 1000.0f));
  94. }
  95. #endif
  96. }
  97. #if defined (CCMRAM)
  98. #if defined (__ICCARM__)
  99. #pragma location = ".ccmram"
  100. #elif defined (__CC_ARM)
  101. __attribute__( ( section ( ".ccmram" ) ) )
  102. #endif
  103. #endif
  104. /* FOC 主控制逻辑 */
  105. void FOC_Fast_Task(motor_foc_t *foc){
  106. current_samp_t *c_sample = &foc->current_samp;
  107. alpha_beta_t sample_ab, pwm_ab;
  108. dq_t sample_dq, v_dq;
  109. phase_time_t phase_time;
  110. u32 sample_point;
  111. /* 更新电角度 */
  112. foc_update_theta(foc);
  113. /* 采集3相电流 */
  114. phase_current_sample(c_sample);
  115. /* ABC坐标转alpha-beta坐标 */
  116. Clark(c_sample->Ia, c_sample->Ib, c_sample->Ic, &sample_ab);
  117. /* alpha-beta坐标转旋转坐标系D-Q */
  118. Park(&sample_ab, foc->motor_s.theta, &sample_dq);
  119. /* 处理D,Q电流环,速度环低频运行,不在此处处理*/
  120. Foc_Dq_PI_Contrl(foc, &sample_dq, &v_dq);
  121. /* d-q坐标转 alpha-beta坐标,输入给pwm */
  122. Rev_Park(&v_dq, foc->motor_s.theta, &pwm_ab);
  123. /* 生成 pwm,模拟正弦波,此处vbus需要动态采集 */
  124. SVPWM_7(&pwm_ab, foc->vbus, FOC_PWM_Half_Period, &phase_time, &foc->sector);
  125. /* 通过扇区和pwm duty 选择合适的3相电流采样点 */
  126. sample_point = get_phase_sample_point(c_sample, &phase_time, foc->sector);
  127. /* 死区补偿 */
  128. DeadTime_Compensation(c_sample, &phase_time);
  129. /* 更新duty和采样点到硬件TIM1中 */
  130. PWM_UpdateDuty(phase_time.A, phase_time.B, phase_time.C, sample_point);
  131. Debug_Log(foc);
  132. Debug_dq(&sample_dq);
  133. }
  134. //输出dq电流,给电流环
  135. static void __inline Foc_Speed_PI_Control(motor_foc_t *foc) {
  136. if (foc->mode == FOC_MODE_PI_SPEED || foc->mode == FOC_MODE_PI_FULL){
  137. float speed_ref = ramp_get_target(&foc->speed_ramp);
  138. float vq_out = pi_control(&foc->PI_speed, speed_ref - foc->motor_s.rpm);
  139. foc->dq_ref.q = vq_out;
  140. }
  141. }
  142. void FOC_Normal_Task(motor_foc_t *foc) {
  143. switch (foc->state) {
  144. case START:
  145. PWM_TurnOnLowSides();
  146. FOC_STM_NextState(CURRENT_CALIBRATE);
  147. break;
  148. case CURRENT_CALIBRATE:
  149. foc_current_calibrate();
  150. FOC_STM_NextState(READY_TO_RUN);
  151. break;
  152. case READY_TO_RUN:
  153. foc_pwm_start(true);
  154. FOC_STM_NextState(RAMPING_START);
  155. ramp_exc(&foc->start_ramp);
  156. foc_overide_vdq(true);
  157. break;
  158. case RAMPING_START:
  159. foc_overide_set_vdq(0.0f, ramp_get_target(&foc->start_ramp));
  160. if (ramp_complete(&foc->start_ramp)) {
  161. FOC_STM_NextState(RUNNING);
  162. }
  163. break;
  164. case RUNNING:
  165. Foc_Speed_PI_Control(foc);
  166. break;
  167. case ANY_STOP:
  168. ramp_clear(&foc->start_ramp);
  169. foc_clear();
  170. FOC_STM_NextState(IDLE);
  171. break;
  172. default:
  173. break;
  174. }
  175. }