首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

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

  • 23-09-22 01:23
  • 2497
  • 12496
blog.csdn.net

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

文章目录

  • 1 概述
  • 2 底层代码生成
    • 2.1 电位器输入配置
    • 2.2 TIM3定时器配置
  • 3 接口及配置代码
    • 3.1 ADC转换接口函数
    • 3.2 TIM3计数接口函数
  • 4 应用层模型及代码生成
    • 4.1 PWM请求计算模块
    • 4.2 转速计算模块
    • 4.3 代码生成及调用
  • 5 打印运行信息
  • 6 总结

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;
}	
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

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

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

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

HAL_TIM_Base_Start_IT(&htim3);
  • 1

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
",ADC1AverageValue);
		printf("PWMRequest:%d
",PWMRequest);
		printf("MotorSpeedHall:%d
",MotorSpeedHall);
		printf("=======================================
");
		HAL_Delay(1000);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

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

6 总结

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

>>返回个人博客总目录

注:本文转载自blog.csdn.net的chhttty的文章"https://blog.csdn.net/u013288925/article/details/119382294"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2024 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top