完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
1个回答
|
|
本文记录博主学习BLDC控制软件的过程。
1 概述 本文是博主第一次做BLDC控制实验,内容只是写代码让BLDC转起来,而暂时不考虑其他复杂的需求。 控制的方法是比较简单的六步换相法。利用电机内部的霍尔传感器,通过参考电机厂家给出的二二导通换相表,生成方波来控制电机。第一次实验为了简化需求,只考虑开环、定速、正转的情况: 开环:不考虑速度反馈,直接给PWM让电机转起来; 定速:不考虑速度调节,换相的时候给的PWM都是相同的值; 正转:只参考换相表中正转的部分,不考虑反转; 所以,实验目标为,通过按下开发板上的Key1按键使BLDC低速运转,按下Key2按键使BLDC停止运转。 本实验需要BLDC六步换相的理论作为知识储备。 2 软件架构及工具链 2.1 软件架构 博主根据自己的工作习惯和经验,制订出实验的软件架构如下: 其中,各个板块的含义如下: ASW:应用层软件,包含电机控制策略和算法; BSW:底层软件,包含驱动Stm32的寄存器配置; Interface:接口层软件,为底层和应用层之间的接口函数; UI:调试开发板所用的代码; 2.2 工具链 对于架构中不同的板块,博主也根据经验选择合适的工具链进行开发。 Matlab/Simulink:基于模型开发的利器,非常适用于应用层软件开发。首先在Simulink中创建控制策略的模型,再用Embedded Coder组件生成C代码; CubeMX:ST公司开发的用于配置STM32的工具,通过配置时钟和外设引脚,可以生成标准的HAL库,可用于BSW代码的生成; MDK:STM32的编译环境,用于编译、调试软件并下载到控制器中,Interface的手写代码也在其中完成; 串口调试助手:用于监测程序运行过程中的一些变量值; 3 底层代码生成 本章节会结合原理图,研究配置CubeMX生成底层代码。 3.1 时钟配置 博主用的开发板是STM32F405RGT6,在CubeMX中将时钟源设置为外部晶振。 时钟数配置如下图。 由于后续的低频任务会运行在系统定时器中断里,所以这里需要留意一下系统定时器的频率为168MHz,也就是1秒钟计数168000000次。 3.2 按键输入配置 在本实验中,开发板上的按键是用于告诉单片机启动或停止电机的请求。开发板上焊接了5个按键模块,如下图。本实验只需要用SW1和SW2两个。 以SW1为例,它的左端接地,右端连接到单片机的PC13引脚,如下图。 所以在CubeMX中配置PC13引脚的模式为输入模式,并配置为上拉。 这样的配置表示,PC13引脚接收到低电平时,按键SW1被按下,接收到高电平时,按键SW1没有被按下。SW2的按键引脚配置类似。 3.3 串口通信配置 串口通信可以将单片机运行过程中的全局变量发送到PC上,然后通过串口调试助手读取信息,是一种验证问题的常规方式。 从原理图可以看出,PB10和PB11引脚是串口3发送和接收的引脚。 首先将串口模式设置为Asynchronous,也就是异步通信。 然后是一些参数设置,包括波特率、字长度等。这里的设置将和PC上的串口调试助手相对应。 最后是NVIC中断优先级设置,这里暂时设置为如下图。 3.4 霍尔信号外部中断配置 六步换相法控制BLDC需要根据霍尔传感器信号输入来判断导通哪些MOS管,因此需要配置3个引脚来分别接收A相,B相,C相三个霍尔信号。 从原理图中可以看出,PB6,PB7,PB8这三个引脚分别对应着A相,B相,C相,所以接下来需要在CubeMX中配置这三个引脚。以PB6为例,在CubeMX中如下。 首先,GPIO_EXTI表示用于GPIO的外部中断。GPIO mode配置成了上升或下降沿触发的外部中断,也就是说,当电机转动导致了霍尔信号变化的时候,会触发外部中断。这一点很重要,因为在该中断回调函数里,会执行换相逻辑。 3.5 MOS管导通开关配置 STM32通过控制引脚输出PWM或GPIO电平,来导通MOS管,从而实现了BLDC的换相控制。由于采用了H PWM-L ON的控制方式,上桥由PWM驱动,下桥由高低电平驱动。 以A相为例,原理图如下。左边的TIM1_CH是PWM,TIM1_CHN是高低电平。 然后顺藤摸瓜找到对应的引脚,TIM1_CH对应PA8,TIM1_CHN对应PB13。 接着就可以在CubeMX分别配置PWM输出和GPIO输出。 这里博主将上桥PWM配置为Up向上计数,重装载值为12000。也就是说后面进行输出比较的时候,范围是0~12000。 下桥的GPIO配置为推挽输出,初始为低电平。 以上配置完成后,就可以生成Keil工程了。 4 接口及配置代码 本章节会在Keil中手写一些代码,作为两方面用处。一方面是为应用层软件配置好输入输出接口函数,另一方面是调用Hal库函数对底层进一步配置。 4.1 系统定时器重装载值 在main文件的初始化代码段加上如下函数: HAL_SYSTICK_Config(168000U); 该函数用于配置系统定时器重装载值为168000。结合前文将系统时钟配置为168MHz,重装载值配置为168000就意味着通过系统定时器产生1ms中断。在中断函数SysTick_Handler中将执行低频任务。 4.2 按键输入接口函数 在main文件中配置如下按键输入接口函数,调用该函数可以返回按键状态(1或0)。 // Get Key State uint8_t Get_Key1State(void) { return((uint8_t)(!HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_13))); } uint8_t Get_Key2State(void) { return((uint8_t)(!HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_0))); } 博主习惯于将输入的接口函数以Get_开头,其实相当于封装了一层统一的命名,并简化传参。这里的Get函数中调用了Hal库的读取GPIO pin脚的函数,并对返回值取反,使得返回1代表按键按下,0代表按键没有按下。 4.3 重定向printf函数 在main文件中重新定义fputc 函数: int fputc(int ch, FILE *f) { HAL_UART_Transmit(&huart3, (uint8_t *)&ch, 1, 0xFFFF); return (ch); } 通过这种方式,就可以用printf函数将全局变量打印到PC上。本文的实验比较简单,没有做UI上位机,就用串口调试助手查看电机运行的实时数据了。 4.4 霍尔信号状态函数 在main文件中配置霍尔信号状态接收函数,调用该函数可以返回霍尔传感器状态(1或0)。 // Get Hall State uint8_t Get_HallAState(void) { return HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6); } uint8_t Get_HallBState(void) { return HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7); } uint8_t Get_HallCState(void) { return HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_8); } 应用层调用霍尔信号状态函数可以获取当前的A,B,C三相的霍尔传感器状态,然后查阅换相表得到导通的MOS管。 4.5 MOS管导通控制函数 在main文件中配置MOS管导通控制函数,调用该函数可以设置MOS管的开关或者PWM。 // Mos void Set_T1PWM(uint32_t PWMValue) { __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,PWMValue); } void Set_T3PWM(uint32_t PWMValue) { __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_2,PWMValue); } void Set_T5PWM(uint32_t PWMValue) { __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,PWMValue); } void Set_T2Status(uint8_t State) { HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13,(GPIO_PinState)State); } void Set_T4Status(uint8_t State) { HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14,(GPIO_PinState)State); } void Set_T6Status(uint8_t State) { HAL_GPIO_WritePin(GPIOB, GPIO_PIN_15,(GPIO_PinState)State); } 其中,T1,T3,T5是上桥,在CubeMX配置为定时器PWM,因此传入的是输出比较值;T2,T4,T6是下桥,配置为GPIO输出,因此传入0或1的状态,来控制导通与断开。这里传入的PWMValue是0~12000,因为CubeMX中配置重装载值为12000。 4.6 电机启停函数 在main文件中配置电机启停函数,调用该函数可以启动或停止定时器通道,从而达到启停电机的效果。 // Set_StartStopMotor void Set_StartStopMotor(uint8_t State) { if(State == 0) //Stop Motor { HAL_TIM_PWM_Stop(&htim1,TIM_CHANNEL_1); HAL_TIM_PWM_Stop(&htim1,TIM_CHANNEL_2); HAL_TIM_PWM_Stop(&htim1,TIM_CHANNEL_3); } else { HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_2); HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_3); } } Set函数会根据传入的State参数来判断调用Stop或是Start的Hal库函数。 5 应用层模型及代码生成 本实验的电机控制应用层软件采用Simulink建模并生成代码。 5.1 基于模型设计(MBD)方案 Matlab/Simulink软件的灵活性很强,可以定制化生成各式各样的代码。博主按照自己的建模习惯,制定了本小节的MBD方案,但不是Matlab/Simulink的唯一用法。 首先,将所有控制策略做在一个模型文件和数据字典中,命名为MotorControl,如下图所示。 数据字典中定义了枚举量、Signal对象等,并根据需要设定Storage Class和头文件。 模型的顶层调用了两个function-call子系统,分别对应系统定时器中断中运行的低频任务,和霍尔传感器外部中断中运行的换相任务。在代码生成的时候会生成SystickTask和HallExitTask两个函数。 下面博主会叙述自己设计的BLDC控制策略,如有不当之处,希望能够交流探讨。 5.2 低频任务子系统 本实验中的低频任务只做两件事,电机状态机建模、启动停止控制。输入为按键状态、霍尔传感器状态,输出为电机状态。 1)首先是按键输入监测,调用了Get_Key1State()接口函数,并通过延时两个周期判断产生了上升沿。 这部分做了两个延时,也就是,第一个周期Key1State为0,然后连续两个周期为1的情况时,视为一次启动电机的请求(StartMotorReq置为1)。 2)电机状态机,Stateflow中共有4个状态:Init,Start,Run,Stop。 电机状态机的输入为启动或停止电机的请求。默认进入Init初始化状态,如果产生了启动电机请求(StartMotorReq)则跳转到Start状态。如果在Start状态停留了10个周期(StartCount == 10),则进入Run状态。当产生了停止电机请求(StopMotorReq),无论当前为Start状态还是Run状态都会跳入Stop状态。 进入Start或是Stop状态的时候,会产生一个事件(Event)用于触发外面的子系统。 每个状态进入时,都会输出MotorState,作为状态机外面的逻辑判断的依据。 3)电机启动的时候还未进入霍尔传感器引起的中断,在该状态中也需要进行启动时的换相函数。首先通过Get_HallXState函数获取三个霍尔传感器的状态,再通过移位进行组装合成。 A相左移2位,B相左移1位,C相不移位。例如A,B,C三相分别是1,0,1时, HallState = (A 《《 2) + (B 《《 1) + C = 4 + 0 + 1 = 5 后面的模型会通过HallState 输入到查表模块(1D Lookup Table)中来判断哪些MOS管需要导通。然后通过调用Set函数导通Mos管。 PWMValue的值在数据字典中定义为2000。这是因为本实验做开环定速旋转,设的过高会引起启动时的抖动。 5.3 霍尔中断子系统 霍尔中断子系统中的模型中没有电机状态机的部分,其余的和5.2 低频任务子系统相似,也是根据霍尔传感器的状态判断导通MOS管。但是有一点区别在于该子系统需要输出HallExtiFlag,也就是霍尔激活标志位。 5.4 代码生成及调用 将模型MotorControl.slx配置好Embedded Coder后,Ctrl + B生成代码。 顶层的两个子系统分别生成了HallExtiTask.c和SystickTask.c两个c文件,并且其中包含了同名的函数。这两个函数就是上文两个子系统对应的代码。 MotorControl.c中生成了一个初始化函数MotorControl_initialize(),用于将模型中定义的全局变量初始化为0。 将所有的C文件和头文件拷贝到Keil工程中,然后在三个地方分别调用。 1)在main函数中调用初始化函数MotorControl_initialize(); 2)在系统定时器中断函数中调用SystickTask(); 3)在霍尔传感器中断回调函数中调用HallExtiTask(); 另外,调用函数需要加上对应的头文件,否则编译无法通过。 最后在Keil中编译软件,并通过ST-Link下载到单片机中。尝试按下按键1和按键2,验证是否可以启动和停止。 6 总结 博主第一次做电机控制实验,感觉还是很有意思的。后面会按照本文的方法论去继续研究BLDC的控制。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1683 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1582 浏览 1 评论
1013 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
703 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1627 浏览 2 评论
1892浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
675浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
538浏览 3评论
557浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
526浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-4 01:41 , Processed in 1.142318 second(s), Total 51, Slave 43 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号