“ 好久没更新了,最近忙着换工作了。”
前面几期好像把硬件部分的搭建说完了,从这期开始讲讲软件吧,先说说直流电机的控制。这部分可以看作是整个系统运行起来的第一步吧,有了这部分内容,前面搭建起来的机器人硬件就可以运作起来了,你的小车就可以放地上跑起来了。
01
—
PWM
PWM(Pulse Width Modulation),即脉冲宽度调制,是利用微处理器的数字输出对模拟电路进行控制的一种技术,其控制简单灵活、动态响应好,广泛应用于工业测控、功率控制,电机控制、开关电源以及音频放大器等领域。
PWM通过使用高分辨率计数器调整输出信号的占空比,实现用数字信号控制模拟信号。PWM信号是数字信号,在任一时刻,电源只有通(1)或断(0)两种状态,电源是以重复脉冲序列加到模拟负载上的。
如图所示,一个PWM的周期内包括一段高电平和一段低电平,其中高电平时间即为脉宽时间,PWM的占空比即为脉宽时间与PWM周期的比值。实际应用中,通过改变占空比来实现控制。
下面以一个电压控制的例子解释PWM的控制实现方法。
如图所示,假设高电平为5V,低电平为0V,当设置PWM的占空比为50%,则实际输出电压值为5V*50%=2.5V,同理,当占空比设置为75%或20%时,则对应的输出电压值分别为3.75V和1V,从而实现了电压的调制输出。由此可见,只要我们设置不同的占空比,理论上就可以将输出电压调制为任意值。
02
—
代码实现
通过STM32单片机的定时器生成PWM信号。
STM32原理与应用就不讲了,可以自行去学习。 这里直接给出代码。笔者用了STM32CUBEMX进行开发,这个软件是ST自己的软件,相当于是内置了stm32的HAL库,相当于引脚配置这部分的代码不需要自己再手写了,省去了造轮子的时间,开发人员只需要把精力放在业务代码的实现上,大大提高了开发效率。当然如果读者习惯了用标准库函数开发,也可以自己决定使用哪种。
说一下CUBEMX的配置吧。这块具体的配置内容,包括引脚号啥的跟前面硬件的连接那部分是相关的,读者自行对照着看即可。
首先就是要选择单片机型号,即stm32f103c8t6。
双击以后就会自动生成工程。
设置时钟源为外部晶振。
设置时钟频率为72MHz
开启SW仿真调试。
设置定时器TIM1生成两路PWM信号。
设置电机驱动模块的两路电机输入引脚。注意设置为推挽输出。
这样的话,单片机就配置完了。然后设置一下代码生成规则。
此处MDK版本对照你电脑上安装的版本即可。
点击生成代码。
点击打开工程即可。然后就自动用KeilMDK软件打开了。
这是自动生成的引脚配置的代码。
再写一点设置PWM的代码。
#include "stm32f1xx_hal.h"
#include "pwm.h"
#include "tim.h"
void Set_pwm(signed short left, signed short right)
{
if(left >= 0)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_14,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_15,GPIO_PIN_SET);
__HAL_TIM_SetCompare(&htim1, TIM_CHANNEL_1, left);
}
else
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_14,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_15,GPIO_PIN_RESET);
__HAL_TIM_SetCompare(&htim1, TIM_CHANNEL_1, -left);
}
if(right >= 0)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_RESET);
__HAL_TIM_SetCompare(&htim1, TIM_CHANNEL_4, right);
}
else
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_SET);
__HAL_TIM_SetCompare(&htim1, TIM_CHANNEL_4, -right);
}
}
然后在主函数里开启PWM,再调用Set_pwm函数就可以了。
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 */
HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_4);
/* 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_TIM1_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
Set_pwm(1000,1000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
编译通过后下载进单片机就可以看到电机已经可以转起来了。读者也可以尝试改变Set_pwm函数的参数大小,可以发现电机转速会随着参数值的变化而变化。至此就实现了直流电机的PWM调速。