一. PWM的定义

PWM ( Pulse Width Modulation ) 脉冲宽度调制技术,通过对一系列脉冲的宽度进行调制,来等效地获得所需要波形(含形状和幅值)。PWM能使电源的输出电压在工作条件变化时保持恒定,是利用微处理器的数字信号对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量通信到功率控制与变换的许多领域中。PWM这项技术的本质其实非常简单,“在不改变最大电压的情况下,通过改变最大电压出现的比率,来改变整体的平均电压”。PWM通常用于控制电机,舵机,加密信息传递,电压变化控制等等

二. PWM的基本概念

PWM的周期:是指信号从高电平到低电平再回到高电平的次数;
PWM的频率:是指一秒钟内的周期数;
PWM的占空比():是指一个脉冲周期内,高电平的时间与整个周期时间的比例;
PWM的脉宽:是指一个周期内高电平的时间。

三. PWM控制大疆M3508

这里以RoboMaster中常见的M3508直流无刷减速电机和C620无刷电机调速器为例。

  1. PWM信号给到C620,然后C620根据其占空比来控制M3508速度;
  2. M3508用PWM驱动时,需要先校验PWM,先给最大占空比,然后在3s内给最小占空比;
  3. M3508是缓启动,也就是说,速度需要从0开始递增,而不能直接让M3508满速;
  4. M3508能接收的频率为50Hz到500Hz,脉宽从1000us到2000us变化,推荐500Hz
  5. M3508分为两种模式:
    单向转动模式:
    Vmin=1000usV_{min}\ =\ 1000usVmin​ = 1000us
    Vmax=2000usV_{max}\ =\ 2000usVmax​ = 2000us
    双向转动模式:
    −Vmax=1000us-V_{max}\ =\ 1000us−Vmax​ = 1000us
    V0=1500usV_{0}\ =\ 1500usV0​ = 1500us
    Vmax=2000usV_{max}\ =\ 2000usVmax​ = 2000us

四. 控制代码

单向转动模式

/* USER CODE BEGIN Header */
/********************************************************************************* @file           : main.c* @brief          : Main program body******************************************************************************* @attention** <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.* All rights reserved.</center></h2>** This software component is licensed by ST under BSD 3-Clause license,* the "License"; You may not use this file except in compliance with the* License. You may obtain a copy of the License at:*                        opensource.org/licenses/BSD-3-Clause********************************************************************************/
/* USER CODE END Header *//* Includes ------------------------------------------------------------------*/
#include "main.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes *//* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*/
TIM_HandleTypeDef htim2;/* USER CODE BEGIN PV *//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_TIM2_Init(void);
/* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 *//* USER CODE END 0 *//*** @brief  The application entry point.* @retval int*/
int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_TIM2_Init();/* USER CODE BEGIN 2 */HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);__uint16_t flag=0;/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){while(flag < 2000){__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,flag++);HAL_Delay(3);}while(flag > 1000){__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,flag--);HAL_Delay(3);}/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}/*** @brief System Clock Configuration* @retval None*/
void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};/** Configure the main internal regulator output voltage */__HAL_RCC_PWR_CLK_ENABLE();__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);/** Initializes the CPU, AHB and APB busses clocks */RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLM = 6;RCC_OscInitStruct.PLL.PLLN = 168;RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;RCC_OscInitStruct.PLL.PLLQ = 4;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}/** Initializes the CPU, AHB and APB busses clocks */RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK){Error_Handler();}
}/*** @brief TIM2 Initialization Function* @param None* @retval None*/
static void MX_TIM2_Init(void)
{/* USER CODE BEGIN TIM2_Init 0 *//* USER CODE END TIM2_Init 0 */TIM_ClockConfigTypeDef sClockSourceConfig = {0};TIM_MasterConfigTypeDef sMasterConfig = {0};TIM_OC_InitTypeDef sConfigOC = {0};/* USER CODE BEGIN TIM2_Init 1 *//* USER CODE END TIM2_Init 1 */htim2.Instance = TIM2;htim2.Init.Prescaler = 83;htim2.Init.CounterMode = TIM_COUNTERMODE_UP;htim2.Init.Period = 1999;htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;if (HAL_TIM_Base_Init(&htim2) != HAL_OK){Error_Handler();}sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK){Error_Handler();}if (HAL_TIM_PWM_Init(&htim2) != HAL_OK){Error_Handler();}sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK){Error_Handler();}sConfigOC.OCMode = TIM_OCMODE_PWM1;sConfigOC.Pulse = 2000;sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK){Error_Handler();}/* USER CODE BEGIN TIM2_Init 2 *//* USER CODE END TIM2_Init 2 */HAL_TIM_MspPostInit(&htim2);}/*** @brief GPIO Initialization Function* @param None* @retval None*/
static void MX_GPIO_Init(void)
{/* GPIO Ports Clock Enable */__HAL_RCC_GPIOH_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();}/* USER CODE BEGIN 4 *//* USER CODE END 4 *//*** @brief  This function is executed in case of error occurrence.* @retval None*/
void Error_Handler(void)
{/* USER CODE BEGIN Error_Handler_Debug *//* User can add his own implementation to report the HAL error return state *//* USER CODE END Error_Handler_Debug */
}#ifdef  USE_FULL_ASSERT
/*** @brief  Reports the name of the source file and the source line number*         where the assert_param error has occurred.* @param  file: pointer to the source file name* @param  line: assert_param error line source number* @retval None*/
void assert_failed(uint8_t *file, uint32_t line)
{ /* USER CODE BEGIN 6 *//* User can add his own implementation to report the file name and line number,tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT *//************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

双向转动模式

/* USER CODE BEGIN Header */
/********************************************************************************* @file           : main.c* @brief          : Main program body******************************************************************************* @attention** <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.* All rights reserved.</center></h2>** This software component is licensed by ST under BSD 3-Clause license,* the "License"; You may not use this file except in compliance with the* License. You may obtain a copy of the License at:*                        opensource.org/licenses/BSD-3-Clause********************************************************************************/
/* USER CODE END Header *//* Includes ------------------------------------------------------------------*/
#include "main.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes *//* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*/
TIM_HandleTypeDef htim2;/* USER CODE BEGIN PV *//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_TIM2_Init(void);
/* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 *//* USER CODE END 0 *//*** @brief  The application entry point.* @retval int*/
int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_TIM2_Init();/* USER CODE BEGIN 2 */HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,0);HAL_Delay(2000);uint16_t flag=1500;/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){while(flag < 2000){__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,flag++);HAL_Delay(3);}while(flag > 1000){__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,flag--);HAL_Delay(3);}/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}/*** @brief System Clock Configuration* @retval None*/
void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};/** Configure the main internal regulator output voltage */__HAL_RCC_PWR_CLK_ENABLE();__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);/** Initializes the CPU, AHB and APB busses clocks */RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLM = 6;RCC_OscInitStruct.PLL.PLLN = 168;RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;RCC_OscInitStruct.PLL.PLLQ = 4;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}/** Initializes the CPU, AHB and APB busses clocks */RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK){Error_Handler();}
}/*** @brief TIM2 Initialization Function* @param None* @retval None*/
static void MX_TIM2_Init(void)
{/* USER CODE BEGIN TIM2_Init 0 *//* USER CODE END TIM2_Init 0 */TIM_MasterConfigTypeDef sMasterConfig = {0};TIM_OC_InitTypeDef sConfigOC = {0};/* USER CODE BEGIN TIM2_Init 1 *//* USER CODE END TIM2_Init 1 */htim2.Instance = TIM2;htim2.Init.Prescaler = 83;htim2.Init.CounterMode = TIM_COUNTERMODE_UP;htim2.Init.Period = 1999;htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;if (HAL_TIM_PWM_Init(&htim2) != HAL_OK){Error_Handler();}sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK){Error_Handler();}sConfigOC.OCMode = TIM_OCMODE_PWM1;sConfigOC.Pulse = 2000;sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK){Error_Handler();}/* USER CODE BEGIN TIM2_Init 2 *//* USER CODE END TIM2_Init 2 */HAL_TIM_MspPostInit(&htim2);}/*** @brief GPIO Initialization Function* @param None* @retval None*/
static void MX_GPIO_Init(void)
{/* GPIO Ports Clock Enable */__HAL_RCC_GPIOH_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();}/* USER CODE BEGIN 4 *//* USER CODE END 4 *//*** @brief  This function is executed in case of error occurrence.* @retval None*/
void Error_Handler(void)
{/* USER CODE BEGIN Error_Handler_Debug *//* User can add his own implementation to report the HAL error return state *//* USER CODE END Error_Handler_Debug */
}#ifdef  USE_FULL_ASSERT
/*** @brief  Reports the name of the source file and the source line number*         where the assert_param error has occurred.* @param  file: pointer to the source file name* @param  line: assert_param error line source number* @retval None*/
void assert_failed(uint8_t *file, uint32_t line)
{ /* USER CODE BEGIN 6 *//* User can add his own implementation to report the file name and line number,tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT *//************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

参考

https://github.com/AlchemicRonin/-STM32-RoboMaster-

大疆M3508电机使用PWM控制转速相关推荐

  1. 大疆A型板使用经验分享(七)——大疆M3508电机和PID控制

    一. 大疆M3508电机 大疆M3508电机可以从RM官网下载很多相关资料,这里不做过多赘述.关于电机配套电调使用的时候,重点是如下两张图: 第一张图是电调接收报文的格式,即如果要发送数据给1号到4号 ...

  2. CAN通信紊乱解决办法 关于大疆6020电机与2006电机同时挂在CAN2上通信紊乱的解决办法

    大疆C板例程改动 CAN通信紊乱解决办法 关于大疆6020电机与2006电机同时挂在CAN2上通信紊乱的解决办法 C板例程的standard_robot里六个电机都是挂在CAN1总线上,由于6020电 ...

  3. 基于大疆RM3508电机的串级PID(角度环+速度环)

    1.前言 最近参加ROBOCON,我负责编写传球机器人,由于传球机构需要一个电机转固定角度来带动球,所以便用大疆3508电机通过串级PID来实现,不得不说3508电机还是真的强,先看一下效果吧. 视频 ...

  4. 大疆M2006电机测试文档

    一.项目 MilkTeaBrother是使用麦克纳姆移动方式的室内服务小车,动力系统为RoboMaster M2006,文中提到的相关文件可以在下方获取. 点击此处了解MilkTeaBrother相关 ...

  5. 多车调度问题(大疆Robot Master)——ROS键盘控制失灵,小车无法收敛定位,路径规划出错

    问题1 ROS键盘控制小车失灵 具体就是:用键盘左右转小车,速度贼快,而且方向不正确,检查发现是控制模块失灵,有可能是内部测量元件(陀螺仪等)烧了,换了个控制模块解决. 问题2 小车无法收敛定位 具体 ...

  6. ESP32:蓝牙BLE控制M3508电机

    ESP32:蓝牙BLE控制M3508电机 先给各位朋友拜个年,祝大家新春快乐,事事顺利,身体健康啊! 还是熟悉的3508,内容概述: ESP32主控 蓝牙BLE通信 使用实时系统(FreeRTOS) ...

  7. 大疆遥控控制M3508电机二(基于HAL库)

    接上一篇文章,话不多说直接开始 一.打开我们创建的工程文件,先就建立一个文件夹用来存放我们写的子文件(不建立也行),然后建立pid.h,pid.c存入我们建立的文件夹中,并把它的源文件和头文件添加进去 ...

  8. 使用Arduino ESP32 通过PWM波控制大疆GM6020以及3508无刷电机(更新)

    使用Arduino控制大疆GM6020无刷电机: 话不多说直接上代码 #include <Servo.h> Servo myservo; //创建一个舵机控制对象// Arduino自带的 ...

  9. 大疆开发板A型基于HAL库驱动M3508直流无刷电机及PID控制

    1.首先,我们先了解一下大疆开发板A型的资料,官方有提供 官网:RoboMaster 机甲大师赛 芯片型号STM32F427IIH6 2.了解M3508直流无刷电机的资料,官网有提供  3.于是我找到 ...

最新文章

  1. go http 处理w.write 错误_Go语言中的异常和错误处理简介
  2. java输出打印到文件_log4j简单使用java项目--后台打印以及输出到文件
  3. 计划策略-11-毛需求计划
  4. 小猪佩奇python_python画个小猪佩奇
  5. 【转载保存】网页提取正文算法汇总
  6. 漫谈LiteOS之开发板-串口(基于GD32450i-EVAL)
  7. python图书馆预约系统_python实现图书馆研习室自动预约功能
  8. Eclipse使用问题
  9. python语法学习第十一天--迭代器
  10. F - Substrings(一些函数的运用)
  11. 关于报错:There is already ‘什么Controller‘ bean method的解决方法
  12. 苹果手机需要清理垃圾吗?
  13. hr标签和注释的总结
  14. php7语法 mysql_php7语法
  15. Linux常用指令(幻影快递Linux小组)
  16. 如何解除word文档保护的方法
  17. 时序预测 | MATLAB实现LSTM长短期记忆神经网络时间序列预测
  18. 最小化安装 Rocky Linux(CentOS的传承,同创始人发起)
  19. XV6 Lab7:Locks
  20. centos rpm安装mysql时依赖检测失败:mysql57-community-release 与 mysql80-community-release-el8-3.noarch 冲突

热门文章

  1. 神舟战神k650d系列触控板关闭开启方法
  2. 一组免费的简约风格表情图标 – Simple Smileys
  3. arcgis for android(一)配置Android Sutdio环境
  4. Matlab/Admas联合仿真提示 输入位移曲线 输出速度曲线为0的解决方法
  5. mac在终端查看本地ip
  6. 三星c9pro语言,三星C9Pro评测 为什么被认为专门为中国用户量身打造的一款产品...
  7. moveit! 与 gazebo 仿真中的问题:Unable to identify any set of controllers that can actuate the specified...
  8. 外贸独立站运营注意事项
  9. WIN10下安装visual studio 2013 语言包失败
  10. 大二python+ffpmeg处理视频实验