BLDC控制实验:方波、霍尔、开环、调速、正转

本文记录博主学习BLDC控制软件的过程。

1 概述

本文是博主进一步学习BLDC控制的实验。在上一篇博客《BLDC控制实验:方波、霍尔、开环、定速、正转》的基础上,加入了调速的功能,包括以下两方面:

  • 通过旋转电位器,调整BLDC转速大小;
  • 通过霍尔传感器和定时器计数算出BLDC当前转速大小;

在上一篇博客中已经实现的换相和按键输入等功能,本文不再赘述。方法和工具链和上一篇类似,也是底层、接口、应用层的顺序进行实现。

2 底层代码生成

《BLDC控制实验:方波、霍尔、开环、定速、正转》中关于时钟树、GPIO、PWM等配置的基础上,进一步配置CubeMX生成底层代码。

2.1 电位器输入配置

开发板上焊接了可调电位器和10k的电阻,组成了一个可调分压电路。该电路可以作为调速用的速度请求输入信号。
在这里插入图片描述
右边的电阻也是10k,SPEEDREF引脚接在了两个电阻之间。容易算出SPEEDREF引脚的电压理论上变化范围是3.3/2 V~ 3.3V。
在这里插入图片描述
SPEEDREF连接在STM32芯片上的PB0引脚上,因此在CubeMX中配置PB0引脚的ADC采样。
在这里插入图片描述
如图所示,配置ADC1为独立单通道采集。其中分辨率(Resolution)设为12位,并设为连续转换模式。

这样的话,就可以生成一些函数来获取PB0引脚的AD转换值。

2.2 TIM3定时器配置

霍尔传感器可以反馈位置状态,如果要将其计算为速度,则还需要一个时间变量。TIM3定时器配置就是为了利用芯片的资源,获取时间信息。

由于TIM1定时器已经配置为了PWM,所以采用TIM3中断来获取时间,TIM3在CubeMX中配置如下。
在这里插入图片描述
在这里插入图片描述
预分频设为41,向上计数,重装载值为99,并且开启了中断。因此TIM3中断周期计算方法如下。
TIM3所挂的时钟是APB1,时钟树中配置为42MHz。预分频为41表示TIM3的频率为42 / (41+1) = 1MHz,即1us计数一次。重装载值为99表示计数0~99后进入一次中断,即100个1us会中断一次,即0.1ms中断一次,然后在中断服务函数中可以写上相应的程序。

3 接口及配置代码

3.1 ADC转换接口函数

在main文件中配置如下ADC转换接口函数,调用该函数可以返回PB0的ADC转换值。

//ADC
uint16_t Get_ADC1Value(void)  
{  	 
	uint16_t adc_value;
	HAL_ADC_Start(&hadc1);//启动ADC单次转换
    HAL_ADC_PollForConversion(&hadc1, 50);//等待ADC转换完成
	adc_value = HAL_ADC_GetValue(&hadc1);//读取ADC转换数据
	return adc_value;
}	

Get_ADC1Value函数中调用了HAL库的函数,完成一次ADC转换。由于在CubeMX中将分辨率配置为12位,因此ADC返回的数值应该是0 - 4096,对应了0 - 3.3v。由于电路图中还有个电阻分去了一半的电压,因此ADC返回数值的范围进一步缩减为2048 - 4096,且实际过程中会有一定偏差。

3.2 TIM3计数接口函数

在main文件中配置如下TIM3计数接口函数以及TIM3中断回调函数,调用接口函数可以返回TIM3计数100us的次数。

//TIM3
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if (htim->Instance == htim3.Instance)
	{
		Count100us++;
	}
}

uint32_t Get_TIM3Count(void)
{
	return Count100us;
}

其中,HAL_TIM_PeriodElapsedCallback是TIM定时器中断服务函数中调用的回调函数。在该函数中判断如果是tim3中断,就把全局变量Count100us加1。因此Count100us就代表了在使能TIM中断后计数了多少了100us。

下面的Get_TIM3Count接口函数就是用来返回Count100us这个全局变量的值,可以由模型调用该函数。

另外要记得在主函数中使能中断:

HAL_TIM_Base_Start_IT(&htim3);

4 应用层模型及代码生成

4.1 PWM请求计算模块

本文还是做开环控制,相对于之前的实验只是将固定的PWM=2000改为由电位器输入改变PWM的数值。因此需要通过电位器的ADC转换值,算出对应的PWM。

1)首先需要对采集的ADC数值进行均值计算,减少跳变的影响,模型如下。
在这里插入图片描述
调用接口函数Get_ADC1Value得到当前的ADC值,用Unit Delay模块与前两个周期的值相加并除以3,算出3个周期内的ADC1均值。

2)由ADC1均值算出请求的PWM数值。在这里插入图片描述
上文提到,ADC1返回的数值是0 - 4096,被分压电阻分走了一半,范围就变成了 2048 - 4096。所以模型中就先减去了2048,再将0 - 2048映射到0 - 12000的PWM。最后用Saturation模块把范围限值成2000 - 10000。

3)换相模块中输入的PWM请求。
在这里插入图片描述
修改两个子系统中换相相关的模块,把原来固定的PWM常数改成前两步基于电位器AD转换数值算出来的PWM请求值。

4.2 转速计算模块

转速计算模块在Hall中断子系统中进行,原理就是当霍尔中断了一定的次数后,算一下每次中断所用的时间,从而换算成电机的rmp单位(转每分钟)。

如下图状态机所示,输入为电机当前状态和TIM3中断计数值,输出为转速。
在这里插入图片描述
在状态机内部,分别设定3个状态:Reset,Calc和Wait。
在这里插入图片描述
1)当MotorState为Run以外的状态时,会从Wait或Calc跳转会Reset状态,然后霍尔中断计数(HallCount)和速度(MotorSpeedHall)都会置为0;

2)当MotorState为Run状态时,从Reset跳转到Wait,同时调用Get函数获取TIM3中断计数值作为起始计数值(StartTIM3Count);接着每次霍尔中断,都会将霍尔中断计数(HallCount)加1,直到HallCount == 120时,跳转到Calc状态。

3)在Calc状态中会获取TIM3中止计数值(StopTIM3Count),它和起始值相减就得到了120次霍尔中断所用的时间(单位是0.1ms);又因为电机转一周是12次霍尔中断(2对极),以及时间换算关系,就可以算出电机转速;计算完毕后立即跳回到Wait状态再进行一轮等待和计算;

4.3 代码生成及调用

将上面的模型生成代码后,代码文件数量都不变,直接拷贝到KEIL工程的路径下,并且也不用再修改原来的函数就可以编译了。

5 打印运行信息

在Main函数中加上一部分串口打印函数,可以看到电机运行时的ADC均值,PWM请求值、速度信息。

/* USER CODE BEGIN WHILE */
  while (1)
  {
		printf("ADC1AverageValue:%d\r\n",ADC1AverageValue);
		printf("PWMRequest:%d\r\n",PWMRequest);
		printf("MotorSpeedHall:%d\r\n",MotorSpeedHall);
		printf("=======================================\r\n");
		HAL_Delay(1000);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */

程序下载到板子中,按下启动按钮,旋转电位器可以输出如下串口信息。
在这里插入图片描述
随着ADC1AverageValue增大,PWMRequest和MotorSpeedHall也相应地增大。

6 总结

这次BLDC控制实验实现了调速功能。但是由于是博主自己玩,也没有十分注意模型和代码地规范性和通用性,但愿很久之后自己也能看得懂了吧。

>>返回个人博客总目录

  • 3
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值