[其他ST产品] 使用PWM控制电机-STM32循迹小车系列教程(一)

[复制链接]
3129|11
 楼主| 烟雨蒙蒙520 发表于 2023-7-29 16:03 | 显示全部楼层 |阅读模式
本章节主要讲解直流减速电机控制原理,电机驱动电路,以及如何使用PWM控制直流减速电机

前言
1.软件准备:STM32CubeMx、Keil5_ MDK

2.硬件准备:STM32F103C8T6核心板、TB6612电机驱动模块/L298N电机驱动、18650锂电池3节/3S航模电池、杜邦线若干

直流减速电机
       图2-1为市场上常用的直流减速电机的图片,减速电机由直流电机加上减速齿轮构成。减速齿轮决定减速电机的减速比,减速比越大电机转速越慢,力矩越大。减速电机一般驱动电压有 12V 和 24V 的,驱动电压越大同样减速比减速电机对应的力矩也就越大,同时耗电电流也会增加。
2507664c4c7a294013.png


下图为某厂家 370减速电机的参数表,我们可以从表中看出与减速电机减速比和驱动电压相对应的力矩、电流等参数的相关关系。
5435364c4c7b49955f.png
4049964c4c7bb92a72.png
直流电机有两个引脚,当我们正向给电机正向通电时电机正转,当我们反向给电机通电时电机反转。如图 2-3 所示为,当电机的 1 脚施加正极,2 脚施加负极时电机正转;电机的 2 脚施加正极,1 脚施加负极电机反转。
5704064c4c7ca1949d.png


————————————————
版权声明:本文为CSDN博主「宝玺」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_49821504/article/details/130443350

 楼主| 烟雨蒙蒙520 发表于 2023-7-29 16:03 | 显示全部楼层
直流电机调速
       对于电机的调速我们需要通过脉冲宽度调制(Pulse width modulation,PWM)来实现,PWM 的占空比为高电平占整个调制周期的时间比例。
       如图 2-4 所示为脉冲宽度调制的的原理图示,比如高电平时间为 8ms,低电平时间为 2ms时,这是整个脉宽周期是为 10ms,占空比即为 80%。我们通过此波形来控制电机即可实现电机的速度控制,且占空比越高的话,高电平的比例越高,则电机速度就会越快,反之就越慢,一般PWM的频率应大于 1KHZ。当然单片机引脚产生的这个 PWM 波形肯定是不可能直接驱动电机的,中间需要使用驱动电路。
8666464c4c7db71061.png

    图 2-5 左为单向电机驱动电路,PWM 引脚为高电平时 N 沟道 MOS 管导通,如果把电机看成电阻的话,这是电机两端电压应该为 12V,PWM 引脚为低电平时 N 沟道 MOS管截止,电机两端电压应该为 0V。但实际电机并不能看成电阻。

        图 2-5 右的电路等效为右边的电路,我们可以把电机看成一个电感,我们知道电感有储能的作用,所以当 MOS管截止电感会释放能量,所以电机两端电压并不是 0V。
 楼主| 烟雨蒙蒙520 发表于 2023-7-29 16:04 | 显示全部楼层
同样当 MOS 管导通时电感会吸收能量,所以电机两端电压也并不是 12V。而是与 PWM 占空比相关,电机两端电压应该
6167164c4c7ff609fc.png
 楼主| 烟雨蒙蒙520 发表于 2023-7-29 16:04 | 显示全部楼层
        如果 PWM占空比为 80%,电机供电电压为 12V 的话,此时电机的实际电压应为 9.6V,所以调PWM 占空比调节电机转速也就是调节电机两端电压调节电机转速。但是PWM 脉冲周期需要小于电感储放能的时间。

3520864c4c80cd40e4.png
 楼主| 烟雨蒙蒙520 发表于 2023-7-29 16:04 | 显示全部楼层
电机驱动电路
        一般我们控制电机需要控制电机的正反转,一个 MOS 管并不能满足我们的需求,所以我们需要通过 H 桥电路来实现,H 桥需要 4 个 MOSFET,这样电路设计起来比较麻烦。市场上有帮我们搭建好的 H 桥电机驱动芯片,这里我们用到的驱动芯片为TB6612FNG,如下图所示,
TB6612FNG介绍  
        单片机引脚的电流一般只有几十个毫安,无法驱动电机,因此一般是通过单片机控制电机驱动芯片进而控制电机。TB6612是比较常用的电机驱动芯片之一。

9439364c4c823029d0.png
TB6612FNG可以同时控制两个电机,工作电流1.2A,最大电流3.2A。

AIN1/2、BIN1/2接单片机的GPIO口。PWMA/B接单片机的定时器口(配置为定时器PWM)。AO1/2、BO1/2接电机的正负极。

        PWMA、AIN1/2、AO1/2为一组驱动一个电机, PWMB、BIN1/2、BO1/2为一组驱动另一个电机。

        STBY为正常工作、待机状态控制引脚,一般接3.3V电即可。VM为电机驱动电压输入(<12V,可接3S锂电池),VCC为逻辑电平输入端(2.7V~5.5V)。
 楼主| 烟雨蒙蒙520 发表于 2023-7-29 16:05 | 显示全部楼层
用户可通过配置AIN1/2、BIN1/2的电平状态控制电机转向,如下图TB6612电机驱动真值表,

4974364c4c8367a094.png

       我们将VM和GND接入电源正极(6~12V,一般2-3节锂电池)和负极(GND需要与主控板共地),PWMA接入主控板上PA6端口,AIN1接入主控板的PB12端口,AIN2接入主控板的PB13端口,STBY接入3.3V,AO1和AO2接入电机的正负极。
 楼主| 烟雨蒙蒙520 发表于 2023-7-29 16:05 | 显示全部楼层
电机驱动程序实现
定时器配置和GPIO配置均通过STM32CUBEMX配置
1395064c4c852b6aac.png
 楼主| 烟雨蒙蒙520 发表于 2023-7-29 16:05 | 显示全部楼层
GPIO配置
  1. void MX_GPIO_Init(void)
  2. {

  3.   GPIO_InitTypeDef GPIO_InitStruct = {0};

  4.   /* GPIO Ports Clock Enable */
  5.   __HAL_RCC_GPIOD_CLK_ENABLE();
  6.   __HAL_RCC_GPIOA_CLK_ENABLE();
  7.   __HAL_RCC_GPIOB_CLK_ENABLE();

  8.   /*Configure GPIO pin Output Level */
  9.   HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_RESET);

  10.   /*Configure GPIO pins : PB12 PB13 PB14 PB15 */
  11.   GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
  12.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  13.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  14.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  15.   HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  16. }
 楼主| 烟雨蒙蒙520 发表于 2023-7-29 16:06 | 显示全部楼层
PWM配置
  1. void MX_TIM3_Init(void)
  2. {

  3.   /* USER CODE BEGIN TIM3_Init 0 */

  4.   /* USER CODE END TIM3_Init 0 */

  5.   TIM_MasterConfigTypeDef sMasterConfig = {0};
  6.   TIM_OC_InitTypeDef sConfigOC = {0};

  7.   /* USER CODE BEGIN TIM3_Init 1 */

  8.   /* USER CODE END TIM3_Init 1 */
  9.   htim3.Instance = TIM3;
  10.   htim3.Init.Prescaler = 72-1;
  11.   htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
  12.   htim3.Init.Period = 1000-1;
  13.   htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  14.   htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  15.   if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)
  16.   {
  17.     Error_Handler();
  18.   }
  19.   sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  20.   sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  21.   if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
  22.   {
  23.     Error_Handler();
  24.   }
  25.   sConfigOC.OCMode = TIM_OCMODE_PWM1;
  26.   sConfigOC.Pulse = 0;
  27.   sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  28.   sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  29.   if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  30.   {
  31.     Error_Handler();
  32.   }
  33.   if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
  34.   {
  35.     Error_Handler();
  36.   }
  37.   /* USER CODE BEGIN TIM3_Init 2 */

  38.   /* USER CODE END TIM3_Init 2 */
  39.   HAL_TIM_MspPostInit(&htim3);

  40. }
 楼主| 烟雨蒙蒙520 发表于 2023-7-29 16:06 | 显示全部楼层
电机控制代码
  1. /**************************************************************************
  2. 函 数 名:void motor_ctrl(int16_t left_speed,int16_t right_speed)
  3. 功    能:电机速度设定函数
  4. 入口参数:left_speed左电机速度 right_speed右电机速度
  5. **************************************************************************/
  6. void motor_ctrl(int16_t left_speed,int16_t right_speed)
  7. {
  8.         if(left_speed>=0) //左电机速度大于0时,电机正转
  9.         {
  10.                 HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_SET);
  11.                 HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13,GPIO_PIN_RESET);
  12.         }
  13.         else         //电机反转                                                                   
  14.         {               
  15.                 HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_RESET);
  16.                 HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13,GPIO_PIN_SET);
  17.   }
  18.        
  19.         if(right_speed>=0)  
  20.         {
  21.                 HAL_GPIO_WritePin(GPIOB,GPIO_PIN_14,GPIO_PIN_SET);
  22.                 HAL_GPIO_WritePin(GPIOB,GPIO_PIN_15,GPIO_PIN_RESET);
  23.         }
  24.         else                                                                            
  25.         {               
  26.                 HAL_GPIO_WritePin(GPIOB,GPIO_PIN_14,GPIO_PIN_RESET);
  27.                 HAL_GPIO_WritePin(GPIOB,GPIO_PIN_15,GPIO_PIN_SET);
  28.   }
  29.        
  30.         __HAL_TIM_SetCompare(&htim3, TIM_CHANNEL_1, abs(left_speed));//将速度占空比赋给电机
  31.         __HAL_TIM_SetCompare(&htim3, TIM_CHANNEL_2, abs(right_speed);
  32. }
 楼主| 烟雨蒙蒙520 发表于 2023-7-29 16:06 | 显示全部楼层
主函数
  1. /**
  2.   * [url=home.php?mod=space&uid=247401]@brief[/url]  The application entry point.
  3.   * @retval int
  4.   */
  5. int main(void)
  6. {
  7.   /* USER CODE BEGIN 1 */

  8.   /* USER CODE END 1 */

  9.   /* MCU Configuration--------------------------------------------------------*/

  10.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  11.   HAL_Init();

  12.   /* USER CODE BEGIN Init */

  13.   /* USER CODE END Init */

  14.   /* Configure the system clock */
  15.   SystemClock_Config();

  16.   /* USER CODE BEGIN SysInit */

  17.   /* USER CODE END SysInit */

  18.   /* Initialize all configured peripherals */
  19.   MX_GPIO_Init();
  20.   MX_TIM3_Init();
  21.   /* USER CODE BEGIN 2 */
  22.                 HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);//开启定时器PWM
  23.                 HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_2);
  24.   /* USER CODE END 2 */

  25.   /* Infinite loop */
  26.   /* USER CODE BEGIN WHILE */
  27.   while (1)
  28.   {
  29.                 motor_ctrl(500,-500);
  30.                 HAL_Delay(5000);
  31.                 motor_ctrl(-500,500);
  32.                 HAL_Delay(5000);
  33.     /* USER CODE END WHILE */

  34.     /* USER CODE BEGIN 3 */
  35.   }
  36.   /* USER CODE END 3 */
  37. }
 楼主| 烟雨蒙蒙520 发表于 2023-7-29 16:06 | 显示全部楼层
具体实现
可以观察到当速度正反改变,电机转动方向也会改变。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

41

主题

720

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部