当前位置:   article > 正文

[STM32+HAL]DengFOC移植之闭环位置控制

[STM32+HAL]DengFOC移植之闭环位置控制

一、源码来源

DengFOC官方文档

二、HAL库配置

1、开启硬件IIC低速模式

低速更稳定

2、PWM波开启

三、keil填写代码

1、AS5600读取编码器数值
  1. #include "AS5600.h"
  2. #include "math.h"
  3. float angle_prev=0;
  4. int full_rotations=0; // full rotation tracking;
  5. float angle_d; //GetAngle_Without_Track()的返回值
  6. float angle_cd; //GetAngle()的返回值
  7. //IIC读多字节
  8. void AS5600_Read_Reg(uint16_t reg, uint8_t* buf, uint8_t len)
  9. {
  10. HAL_I2C_Mem_Read(&hi2c1, AS5600_ADDRESS, reg, I2C_MEMADD_SIZE_8BIT, buf, len, 100);
  11. }
  12. //得到弧度制的角度,范围在0-6.28
  13. float GetAngle_Without_Track(void)
  14. {
  15. int16_t in_angle;
  16. uint8_t temp[DATA_SIZE]={0};
  17. AS5600_Read_Reg( Angle_Hight_Register_Addr, temp, DATA_SIZE);
  18. in_angle = ((int16_t)temp[0] <<8) | (temp[1]);
  19. angle_d = (float)in_angle * (2.0f*PI) / 4096;
  20. //angle_d为弧度制,范围在0-6.28
  21. return angle_d;
  22. }
  23. //得到弧度制的带圈数角度
  24. float GetAngle(void)
  25. {
  26. float val = angle_d;
  27. float d_angle = val - angle_prev;
  28. //计算旋转的总圈数
  29. //通过判断角度变化是否大于80%的一圈(0.8f*6.28318530718f)来判断是否发生了溢出,如果发生了,则将full_rotations增加1(如果d_angle小于0)或减少1(如果d_angle大于0)。
  30. if(fabs(d_angle) > (0.8f*2.0f*PI) ) full_rotations += ( d_angle > 0 ) ? -1 : 1;
  31. angle_prev = val;
  32. angle_cd = full_rotations * (2.0f*PI) + angle_prev;
  33. return angle_cd;
  34. }
  35. void Track(void)
  36. {
  37. GetAngle_Without_Track();
  38. GetAngle();
  39. }

2、闭环FOC控制
  1. #include "AS5600.h"
  2. #include "FOC1.h"
  3. #include <math.h>
  4. #define PWMA TIM1 -> CCR1
  5. #define PWMB TIM1 -> CCR2
  6. #define PWMC TIM1 -> CCR3
  7. #define CNT TIM1 -> ARR-1
  8. float voltage_limit=12.6;
  9. float voltage_power_supply=12.6;
  10. float shaft_angle=0,open_loop_timestamp=0;
  11. float zero_electric_angle=0,Ualpha,Ubeta=0,Ua=0,Ub=0,Uc=0,dc_a=0,dc_b=0,dc_c=0;
  12. int PP=7,DIR=-1;
  13. float _electricalAngle(void){
  14. return _normalizeAngle((float)(DIR * PP) * GetAngle_Without_Track()-zero_electric_angle);
  15. }
  16. // 归一化角度到 [0,2PI]
  17. float _normalizeAngle(float angle){
  18. float a = fmod(angle, 2*PI); //取余运算可以用于归一化,列出特殊值例子算便知
  19. return a >= 0 ? a : (a + 2*PI);
  20. }
  21. // 设置PWM到控制器输出
  22. void setPwm(float Ua, float Ub, float Uc) {
  23. // 限制上限
  24. Ua = _constrain(Ua, 0.0f, voltage_limit);
  25. Ub = _constrain(Ub, 0.0f, voltage_limit);
  26. Uc = _constrain(Uc, 0.0f, voltage_limit);
  27. // 计算占空比
  28. // 限制占空比从0到1
  29. dc_a = _constrain(Ua / voltage_power_supply, 0.0f , 1.0f );
  30. dc_b = _constrain(Ub / voltage_power_supply, 0.0f , 1.0f );
  31. dc_c = _constrain(Uc / voltage_power_supply, 0.0f , 1.0f );
  32. //写入PWM到PWM 0 1 2 通道
  33. PWMA = dc_a*5599;
  34. PWMB = dc_b*5599;
  35. PWMC = dc_c*5599;
  36. }
  37. void setPhaseVoltage(float Uq,float Ud, float angle_el) {
  38. angle_el = _normalizeAngle(angle_el);
  39. // 帕克逆变换
  40. Ualpha = -Uq*sin(angle_el);
  41. Ubeta = Uq*cos(angle_el);
  42. // 克拉克逆变换
  43. Ua = Ualpha + voltage_power_supply/2;
  44. Ub = (sqrt(3)*Ubeta-Ualpha)/2 + voltage_power_supply/2;
  45. Uc = (-Ualpha-sqrt(3)*Ubeta)/2 + voltage_power_supply/2;
  46. setPwm(Ua,Ub,Uc);
  47. }
  48. //初始化FOC,校准零点
  49. void FOC_Init(void)
  50. {
  51. setPhaseVoltage(3, 0,_3PI_2);
  52. HAL_Delay(1000);
  53. zero_electric_angle=_electricalAngle();
  54. setPhaseVoltage(0, 0,_3PI_2);
  55. }

3、main.c
  1. /* USER CODE BEGIN PV */
  2. extern float voltage_limit;
  3. extern float voltage_power_supply;
  4. extern float shaft_angle,open_loop_timestamp;
  5. extern float zero_electric_angle,Ualpha,Ubeta,Ua,Ub,Uc,dc_a,dc_b,dc_c;
  6. extern int PP,DIR;
  7. float motor_target = 4;
  8. /* USER CODE END PV */
  9. /* USER CODE BEGIN 2 */
  10. printf("Hello World\r\n");
  11. HAL_Delay(500);
  12. HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);
  13. HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_2);
  14. HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_3);
  15. FOC_Init();
  16. HAL_TIM_Base_Start_IT(&htim2);
  17. /* USER CODE END 2 */
  18. /* Infinite loop */
  19. /* USER CODE BEGIN WHILE */
  20. while (1)
  21. {
  22. float Sensor_Angle=GetAngle();
  23. float Kp=0.133;
  24. setPhaseVoltage(_constrain(Kp*(motor_target-DIR*Sensor_Angle)*180/PI,-6,6),0,_electricalAngle());
  25. /* USER CODE END WHILE */
  26. /* USER CODE BEGIN 3 */
  27. }
  28. /* USER CODE END 3 */

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/405288
推荐阅读
相关标签
  

闽ICP备14008679号