当前位置:   article > 正文

视觉巡线小车——STM32+OpenMV(一)_巡线小车stm32

巡线小车stm32

目录

前言 

一、CubeMX配置

1、系统及时钟配置

2、配置GPIO

3、定时器配置

4、生成MDK工程

二、Keil编辑代码

1.初始化代码

2.电机控制代码

3、电机测速代码

4、控制示例

总结



前言 

利用STM32CubeMX新建减速电机驱动工程,并且通过减速电机自带的霍尔编码器采集速度。

重点:

        1、配置定时器生成PWM——控制TB6612输出;

        2、配置定时器产生10ms中断——电机控制周期;

        3、配置定时器为正交编码模式——采集电机转速;

       4、配置GPIO——控制电机方向

系列文章请查看:视觉巡线小车——STM32+OpenMV系列文章


一、CubeMX配置

1、系统及时钟配置

系统配置

2、配置GPIO

3、定时器配置

配置定时器TIM1生成PWM:

        PSC = 0;

        ARR = 7199;

由于系统时钟为72M,所以PWM频率为:10kHz。

占空比为:D=Pulse/ARR * 100%。

配置定时器TIM2产生10ms中断:

        PSC = 72-1;

        ARR = 10000-1;

 同时 需要开启定时器中断,中断优先级自己设置。

配置定时器TIM3、TIM4为正交编码模式:

定时器TIM3和TIM4操作一样,如果有需要可以自行开启定时器更新中断。

4、生成MDK工程

 其中工程名字和路径都不能有中文,必须用标准C的标识符命名。

二、Keil编辑代码

1.初始化代码

通过CubeMX配置生成的工程还需要加入一些初始化代码:

  1. HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL);
  2. HAL_TIM_Encoder_Start(&htim4, TIM_CHANNEL_ALL);
  3. HAL_TIM_Base_Start_IT(&htim2);
  4. HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);
  5. HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_4);
  6. __HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_1,0);
  7. __HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_4,0);

2.电机控制代码

这里主要采用TB6612来驱动减速电机:

motor.h文件代码如下

  1. #ifndef _MOTOR_H_
  2. #define _MOTOR_H_
  3. #include "stm32f1xx_hal.h"
  4. #include "tim.h"
  5. /*******直流减速电机机械参数*********/
  6. #define ENCODE_X 500 //编码器线数
  7. #define JIANSUBI 30 //减速比
  8. #define BEIPIN 4 //倍频
  9. #define SAMPLE_TIME 0.01 //采样时间10ms
  10. #define C (ENCODE_X*JIANSUBI*BEIPIN*SAMPLE_TIME)
  11. #define PI 3.1415
  12. #define R 6.5 //车轮直径cm
  13. #define BIN2(n) HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13 , (GPIO_PinState)n)
  14. #define BIN1(n) HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12 , (GPIO_PinState)n)
  15. #define AIN2(n) HAL_GPIO_WritePin(GPIOB,GPIO_PIN_15 , (GPIO_PinState)n)
  16. #define AIN1(n) HAL_GPIO_WritePin(GPIOB,GPIO_PIN_14 , (GPIO_PinState)n)
  17. typedef struct
  18. {
  19. float speed;
  20. int S;
  21. int Target_Speed;
  22. int out;
  23. }MOTOR_t;
  24. extern MOTOR_t motorA,motorB;
  25. #define LIMIT(x,min,max) (x)=(((x)<=(min))?(min):(((x)>=(max))?(max):(x))) //限幅定义
  26. int abs(int p);
  27. void Load(int motorA,int motorB);
  28. #endif

 其中电机以及轮子的参数自己修改。

motor.c文件代码如下

  1. #include "motor.h"
  2. MOTOR_t motorA = {0},motorB = {0};
  3. int abs(int p)
  4. {
  5. int q;
  6. q=p>0?p:(-p);
  7. return q;
  8. }
  9. void Load(int motorA,int motorB)
  10. {
  11. LIMIT(motorA,-7199,7199);
  12. LIMIT(motorB,-7199,7199);
  13. if(motorA>0)
  14. AIN1(1),AIN2(0);//正转
  15. else
  16. AIN1(0),AIN2(1);//正转
  17. __HAL_TIM_SetCompare(&htim1, TIM_CHANNEL_1, abs(motorA));
  18. if(motorB>0)
  19. BIN1(1),BIN2(0);
  20. else
  21. BIN1(0),BIN2(1);
  22. __HAL_TIM_SetCompare(&htim1, TIM_CHANNEL_4, abs(motorB));
  23. }

3、电机测速代码

  1. //根据电机头文件中的参数,可得计算出的速度的单位为:cm/s
  2. float get_speed_motorA()
  3. {
  4. short Encoder_TIM = 0;
  5. float Speed = 0.0;
  6. Encoder_TIM = (short)__HAL_TIM_GetCounter(&htim3); //获取编码器定时器中的计数值
  7. __HAL_TIM_SetCounter(&htim3, 0);
  8. if(htim3.Instance->CR1 & 0X10) //判断计数器的计数方向,逻辑1则是减计数
  9. {
  10. Encoder_TIM = -65536 + Encoder_TIM;
  11. }
  12. // Encoder_TIM = Encoder_TIM+Encoder3_Overflow_Count*65536;
  13. Speed = (float)Encoder_TIM / (C) * PI * R;
  14. return Speed;
  15. }
  16. float get_speed_motorB()
  17. {
  18. short Encoder_TIM = 0;
  19. float Speed = 0.0;
  20. Encoder_TIM = (short)__HAL_TIM_GetCounter(&htim4); //获取编码器定时器中的计数值
  21. __HAL_TIM_SetCounter(&htim4, 0);
  22. if(htim4.Instance->CR1 & 0X10) //判断计数器的计数方向,逻辑1则是减计数
  23. {
  24. Encoder_TIM = -65536 + Encoder_TIM;
  25. }
  26. // Encoder_TIM = Encoder_TIM+Encoder3_Overflow_Count*65536;
  27. Speed = -(float)Encoder_TIM / (C) * PI * R;
  28. return Speed;
  29. }

在定时器中断里, 每10毫秒对定时器TIM3和TIM4的计数值进行处理,得到电机速度,方便后续进行速度闭环控制。

4、控制示例

  1. int main(void)
  2. {
  3. /* USER CODE BEGIN 1 */
  4. /* USER CODE END 1 */
  5. /* MCU Configuration--------------------------------------------------------*/
  6. /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  7. HAL_Init();
  8. /* USER CODE BEGIN Init */
  9. /* USER CODE END Init */
  10. /* Configure the system clock */
  11. SystemClock_Config();
  12. /* USER CODE BEGIN SysInit */
  13. /* USER CODE END SysInit */
  14. /* Initialize all configured peripherals */
  15. MX_GPIO_Init();
  16. MX_TIM1_Init();
  17. MX_TIM2_Init();
  18. MX_TIM3_Init();
  19. MX_TIM4_Init();
  20. /* USER CODE BEGIN 2 */
  21. HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL);
  22. HAL_TIM_Encoder_Start(&htim4, TIM_CHANNEL_ALL);
  23. HAL_TIM_Base_Start_IT(&htim2);
  24. HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);
  25. HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_4);
  26. __HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_1,0);
  27. __HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_4,0);
  28. /* USER CODE END 2 */
  29. /* Infinite loop */
  30. /* USER CODE BEGIN WHILE */
  31. while (1)
  32. {
  33. /* USER CODE END WHILE */
  34. /* USER CODE BEGIN 3 */
  35. motorA.out = 7200*0.2;//以最大输出的百分之二十进行测试
  36. motorB.out = -7200*0.2;//以最大输出的百分之二十进行测试
  37. }
  38. /* USER CODE END 3 */
  39. }
  40. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
  41. {
  42. /*******电机控制周期,每10ms对电机控制一次*********/
  43. if(htim->Instance == TIM2 )
  44. {
  45. motorA.speed = get_speed_motorA();
  46. motorB.speed = get_speed_motorB();
  47. motorA.S += motorA.speed;//简单的路程计算
  48. motorB.S += motorB.speed;
  49. Load(motorA.out, motorB.out);
  50. }
  51. }

总结

通过本文,就可以对减速电机进行简单的控制,以及速度的采集了。

同时可以自行加入OLED等显示屏,显示所采集的速度,也可以通过配置串口进行打印观察。

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号