你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32CubeIDE自平衡小车教程6.电机转速闭环控制

[复制链接]
STMCU小助手 发布时间:2022-3-15 22:00
开始之前我们需要了解的是完成闭环控制输出任务前提是必须要有printf输出功能和PWM输出功能。

1)其中printf功能是为了在最后阶段,监测实时的PWM值,检测是否实现闭环控制。

关于printf功能的实现可参考教程4的内容:

STM32CubeIDE自平衡小车教程4.配置串口并实现字符的输出

2)PWM输出功能是为了实现最后车轮能按照设定的转速转动。

关于PWM输出功能的实现可参考教程5的内容:

STM32CubeIDE自平衡小车教程5.直流电机转速开环控制

以下是实现电机转速闭环控制的步骤:
1.打开上节的工程文件,在工程文件中新加一个User文件夹,在文件夹目录下新建Src和Inc文件夹,并分别添加.c文件和.h文件并命名为motor_control.c和motor_control.h

KVT(36B]M16PXRR)C6XZ5XL.png

2.在motor_control.c文件中加入以下代码:
  1. #include "main.h"

  2. float SpeedKp = 10.0, SpeedKi = 1, SpeedKd = 0;

  3. int Motor1SpeedClosedControl(int Encoder,int Target)
  4. {
  5.         static float Error,ErrorPrev,ErrorLast,PWM;

  6.         Error = Target - Encoder;

  7.         PWM += SpeedKp*(Error - ErrorPrev) + SpeedKi*Error + SpeedKd*(Error - 2*ErrorPrev + ErrorLast);

  8.         ErrorLast = ErrorPrev;
  9.         ErrorPrev = Error;

  10.         if(PWM >= 100) PWM = 100;
  11.         if(PWM <= -100) PWM = -100;

  12.         return PWM;
  13. }

  14. void SetMotor1Direction(int Pwm)//设置电机方向
  15. {
  16. if(Pwm < 0)//反转
  17. {
  18. HAL_GPIO_WritePin(BIN1_GPIO_Port, BIN1_Pin, GPIO_PIN_RESET);
  19. HAL_GPIO_WritePin(BIN2_GPIO_Port, BIN2_Pin, GPIO_PIN_SET);
  20. Pwm = (-Pwm);//如果计算值是负值,先取负得正,因为PWM寄存器只能是正值
  21. __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_4, Pwm);
  22. }else
  23. {
  24. HAL_GPIO_WritePin(BIN1_GPIO_Port, BIN1_Pin, GPIO_PIN_SET);
  25. HAL_GPIO_WritePin(BIN2_GPIO_Port, BIN2_Pin, GPIO_PIN_RESET);
  26. __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_4, Pwm);
  27. }
  28. }

  29. int Motor2SpeedClosedControl(int Encoder,int Target)
  30. {
  31.         static float Error,ErrorPrev,ErrorLast,PWM;

  32.         Error = Target - Encoder;

  33.         PWM += SpeedKp*(Error - ErrorPrev) + SpeedKi*Error + SpeedKd*(Error - 2*ErrorPrev + ErrorLast);

  34.         ErrorLast = ErrorPrev;
  35.         ErrorPrev = Error;

  36.         if(PWM >= 100) PWM = 100;
  37.         if(PWM <= -100) PWM = -100;

  38.         return PWM;
  39. }

  40. void SetMotor2Direction(int Pwm)//设置电机方向
  41. {
  42.         if(Pwm < 0)//反转
  43.         {
  44.         HAL_GPIO_WritePin(AIN1_GPIO_Port, AIN1_Pin, GPIO_PIN_SET);
  45.         HAL_GPIO_WritePin(AIN2_GPIO_Port, AIN2_Pin, GPIO_PIN_RESET);
  46.         Pwm = (-Pwm);//如果计算值是负值,先取负得正,因为PWM寄存器只能是正值
  47.         __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, Pwm);
  48.         }
  49.         else
  50.         {
  51.         HAL_GPIO_WritePin(AIN1_GPIO_Port, AIN1_Pin, GPIO_PIN_RESET);
  52.         HAL_GPIO_WritePin(AIN2_GPIO_Port, AIN2_Pin, GPIO_PIN_SET);
  53.         __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, Pwm);
  54.         }
  55. }
复制代码

3.在motor_control.h文件中加入以下代码:
  1. int Motor1SpeedClosedControl;
  2. int Motor2SpeedClosedControl;
  3. void SetMotor1Direction(int Pwm);
  4. void SetMotor2Direction(int Pwm);
复制代码

4.在main.c文件中在上节代码的基础中添加如下代码:
  1.         HAL_TIM_Encoder_Start(&htim3,TIM_CHANNEL_ALL);
  2.         HAL_TIM_Encoder_Start(&htim4,TIM_CHANNEL_ALL);
复制代码

R{CTSRAY1347YBOGK]E_S$O.png

5.打开在Core文件夹下Src文件夹中的stm32f1xx_it.c文件,下拉找到void SysTick_Handler(void),并加入以下代码(要加在CODE BEGIN和CODE END中间):
  1. static unsigned char Timer5msCounter;
  2.         static int Motor1Speed;
  3.         static int Motor1PWM;
  4.         static int Motor2Speed;
  5.         static int Motor2PWM;

  6.         Timer5msCounter++;
  7.           if(Timer5msCounter >=5)//每5s一个周期
  8.           {
  9.                   Timer5msCounter = 0;
  10.                   Motor2Speed = GetTim4Encoder();
  11.                   Motor1Speed = GetTim3Encoder();

  12.                   printf("M1Speed = %d \n", Motor1Speed);
  13.                   printf("M2Speed = %d \n", Motor2Speed);

  14.                   Motor1PWM = Motor1SpeedClosedControl(Motor1Speed,-20);
  15.                   Motor2PWM = Motor2SpeedClosedControl(Motor2Speed,30);

  16.                   SetMotor1Direction(Motor1PWM);
  17.                   SetMotor2Direction(Motor2PWM);
  18.       }
复制代码

ZJ0A]YBZRXQOV1{BGO%N~WA.png

6.在工程文件目录下的Core文件夹下添加Inc和Src文件夹,并添加encoder.c文件和encoder.h文件。
在encoder.c文件下添加以下代码:
  1. #include "tim.h"//包含tim头文件
  2. #include "encoder.h"

  3. int iTim4Encoder;//存放从TIM4定时器读出来的编码器脉冲
  4. int iTim3Encoder;

  5. int GetTim4Encoder(void)//获取TIM4定时器读出来的编码器脉冲
  6. {
  7. iTim4Encoder = (short)(__HAL_TIM_GET_COUNTER(&htim4));//先读取脉冲数
  8. __HAL_TIM_SET_COUNTER(&htim4,0);//再计数器清零
  9. return iTim4Encoder;//返回脉冲数
  10. }

  11. int GetTim3Encoder(void)//获取TIM4定时器读出来的编码器脉冲
  12. {
  13. iTim3Encoder = (short)(__HAL_TIM_GET_COUNTER(&htim3));//先读取脉冲数
  14. __HAL_TIM_SET_COUNTER(&htim3,0);//再计数器清零
  15. return iTim3Encoder;//返回脉冲数
  16. }
复制代码

在encoder.h文件下添加以下代码:
  1. int GetTim4Encoder(void);//声明函数
  2. int GetTim3Encoder(void);
复制代码

7.点击编译并进行烧录,完成PID速度闭环控制任务。可在在stm32f1xx_it.c中更改小车M1和M2电机的脉冲速度,正数转向为正向,负数转向为反向,并在调试器中接收小车的脉冲速度。(需要打开小车电源开关)
例如此时设置M1电机脉冲速度为-20,M2电机脉冲速度为40。
7BSW6FV]GYDF@NA[)BQ4(6C.png

打开串口数据调试工具,可查看小车实时输出的PWM值:

OL4ES%3}4BT@M2VO{J{HBT0.png


收藏 评论0 发布时间:2022-3-15 22:00

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版