1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 【FOC无刷电机控制】六步换向 FOC STM32cubemx从零开始搭建BLDC六步换相代码 FOC代

【FOC无刷电机控制】六步换向 FOC STM32cubemx从零开始搭建BLDC六步换相代码 FOC代

时间:2020-01-06 17:01:00

相关推荐

【FOC无刷电机控制】六步换向 FOC STM32cubemx从零开始搭建BLDC六步换相代码 FOC代

目录

O、前言1 个人经验2 软硬件介绍 一、六步换相1 新建cubemx工程2 工程基础配置(1)RCC时钟配置(2)SYS 调试接口(3)工程设置,生成MDK工程 3 串口(1)cubemx配置(2)printf重映射(3)测试 4 霍尔传感器(1)Cubemx配置(2)初始化启动(3)测试定时中断(4)测试霍尔中断 4 开环控制(1)普通PWM cubemx配置(2)普通GPIO配置(3)开环控制 二、FOC

O、前言

用作备忘录,也希望能帮助正在入门摸索的朋友少走弯路,从外设开始,到开环,到闭环。参考文章代码:正点原子、野火、硬石,三家文档几乎一样。(个人感觉原子文档写的好)

1 个人经验

刚开始学无刷电机控制时是直接去看的FOC,网上理论一大堆,看了几天,理论大概明白了,想去实践编程,发现都是大多都是电机库,或者一些别人的完整代码,没有步骤教学。经过一顿摸索,我的结论是把理论化为单片机代码实际去控制电机的过程,某种程度上比学习理论更困难。我个人做一些单片机小项目的习惯是从头开始做。从一个空白工程开始,一个外设一个外设的调,调通一个测试一个,要用的所有外设调完再去加入控制代码,由开环到闭环,一步一步的来。直接用别人写好的一套代码总感觉心里没底。对于无刷电机控制,我的步骤是这样的:1调霍尔传感器,2调PWM,3调开环控制,4调闭环

2 软硬件介绍

软件:STM32cubemx+keil5硬件:网上买的一块无刷电机驱动板,芯片是STM32G070。要注意的是我的电机是BLDC,2对极,间隔60度安装的霍尔传感器。所以我现在实现的都是 基于霍尔传感器的开闭环控制。暂时没整过基于编码器的、基于无感的。

一、六步换相

六步换向用到的单片机外设:(根据个人板子引脚要做一些修改) TIM3:选择霍尔传感器模式,用于获取3个霍尔值。TIM1:通道123,普通PWM模式,用于驱动半桥电路的3个上半桥。(因为我这边用的是HPWM-LON的控制。)普通IO:3个,推挽输出,用于驱动半桥电路的3个下半桥。USART2:用于调试用。RTC:用于闭环控制。(这个用RTC中断可能不太合适,但是暂时这样…)代码整体的调用流程: 开环:电机转动换相时,触发霍尔中断,在霍尔中断回调函数里读取当前的相位值,然后根据相位值进行换相。闭环:在开环的基础上,再开一个定时器,在里边做PID运算,更改占空比设定值。六步换向-开环控制代码:/wyfroom/BLDC_LiuBu_KaiHuan_hall六步换向-闭环控制代码

1 新建cubemx工程

2 工程基础配置

(1)RCC时钟配置

选择时钟源,我这块板子只有外部8M晶振。

手动输入最大时钟频率,然后回车。我这块板子是64M。

(2)SYS 调试接口

我的下载器是SWD两根线的,所以我选这个。

(3)工程设置,生成MDK工程

点击生成代码

3 串口

这快板子没显示屏,调试中串口还是很有必要。我这块板子是串口2,看好引脚,串口自动配置的引脚不一定是板子上的。比如我这块板子,就不是这两引脚。

(1)cubemx配置

(2)printf重映射

添加如下代码到工程的 usart.c 文件中的 /* USER CODE BEGIN 0/ 和 /USER CODE END 0 */之间。

#include <stdio.h>#ifdef __GNUC__#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)#else#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)#endifPUTCHAR_PROTOTYPE{//具体哪个串口可以更改huart1为其它串口HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1 , 0xffff);return ch;}

在main.c里添加头文件 #include <stdio.h>

之前忘记说了,这个printf重映射要在keil里也设置一下,不然一使用printf单片机就会卡死。抱歉抱歉(.3.30)

(3)测试

在main的while里加入如下代码

printf("hello\r\n");HAL_Delay(1000);

4 霍尔传感器

(1)Cubemx配置

32定时器有一种霍尔模式,专门为无刷电机霍尔控制整的叭。

打开定时器中断

更改引脚名称(可选),为了编程方便

(2)初始化启动

在main中加入下面启动代码。

__HAL_TIM_ENABLE_IT(&htim3,TIM_IT_TRIGGER); //触发:有某个信号触发。 __HAL_TIM_ENABLE_IT(&htim3,TIM_IT_UPDATE); //更新:有某个寄存器被更新。HAL_TIMEx_HallSensor_Start_IT(&htim3);

(3)测试定时中断

在工程里新建两个文件:hall.c、hall.h。在main里加头文件。加入下面中断回调函数,先测基本定时器中断,串口助手看现象。

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){printf("tim\r\n");}

(4)测试霍尔中断

hall.c 加入如下代码

uint8_t state = 0;//换相中断void HAL_TIM_TriggerCallback(TIM_HandleTypeDef *htim){state = get_hall_state();printf("%d\r\n",state);}//获取霍尔传感器值uint8_t get_hall_state(void){uint8_t state = 0;#if 1/* 读取霍尔传感器 U 的状态 */if(HAL_GPIO_ReadPin(hallu_GPIO_Port, hallu_Pin) != GPIO_PIN_RESET){state|= 0x01U << 0;//printf("u1\r\n");}/* 读取霍尔传感器 V 的状态 */if(HAL_GPIO_ReadPin(hallv_GPIO_Port, hallv_Pin) != GPIO_PIN_RESET){state |= 0x01U << 1;//printf("v1\r\n");}/* 读取霍尔传感器 W 的状态 */if(HAL_GPIO_ReadPin(hallw_GPIO_Port, hallw_Pin) != GPIO_PIN_RESET){state |= 0x01U << 2;//printf("w1\r\n");}#elsestate = (GPIOH->IDR >> 10) & 7; // 读 3 个霍尔传感器的状态#endif//printf("stateL:%d\n",state);return state; // 返回传感器状态}

把电机霍尔接口接到板子上,用手转动电机,能看到串口打印出此时电机对应的霍尔编码值。

这个时候霍尔的状态值读回来了,也就是什么时候换相可以知道了,下一步就是驱动全桥电路,用3个普通PWM+3个普通IO口。

4 开环控制

(1)普通PWM cubemx配置

更改引脚名字

测试PWM是否正常输出,加入PWM启动代码和初始化占空比。

用万用表电压档,去测对应引脚电压是否符合占空比值。在main里加入下面代码:

HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_2);HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_3);__HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_3,800);//U__HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_2,0);//V__HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_1,0);//W

(2)普通GPIO配置

cubemx

测试,在main中加入下代码用电压档,测对应引脚是否正常输出电压。

//普通IO初始化,驱动3个下桥臂HAL_GPIO_WritePin(PWMUL_GPIO_Port,PWMUL_Pin,GPIO_PIN_RESET);//UL//GPIO_PIN_SET GPIO_PIN_RESETHAL_GPIO_WritePin(PWMVL_GPIO_Port,PWMVL_Pin,GPIO_PIN_RESET);//VLHAL_GPIO_WritePin(PWMWL_GPIO_Port,PWMWL_Pin,GPIO_PIN_RESET);//WL

(3)开环控制

我的电机是2对极,60度霍尔,所以能用下面这个换相表。同类型电机可以用,不同的话就要网上找一下对应的换相表,然后改下对应代码。

在hall.c里加入换相代码

uint16_t state=0;uint16_t pwm_pulse=0void HAL_TIM_TriggerCallback(TIM_HandleTypeDef *htim){state = get_hall_state();//printf("%d\r\n",state);//513264switch(state){case 1: /* U+ W- */__HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_3,pwm_pulse);//U+__HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_2,0);//V+__HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_1,0);//W+HAL_GPIO_WritePin(PWMUL_GPIO_Port,PWMUL_Pin,GPIO_PIN_RESET);//U-//GPIO_PIN_SET GPIO_PIN_RESETHAL_GPIO_WritePin(PWMVL_GPIO_Port,PWMVL_Pin,GPIO_PIN_RESET);//V-HAL_GPIO_WritePin(PWMWL_GPIO_Port,PWMWL_Pin,GPIO_PIN_SET);//W-//printf("%d\r\n",pwm_pulse);break;case 2:/* V+ U- */__HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_3,0);//U+__HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_2,pwm_pulse);//V+__HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_1,0);//W+HAL_GPIO_WritePin(PWMUL_GPIO_Port,PWMUL_Pin,GPIO_PIN_SET);//U-//GPIO_PIN_SET GPIO_PIN_RESETHAL_GPIO_WritePin(PWMVL_GPIO_Port,PWMVL_Pin,GPIO_PIN_RESET);//V-HAL_GPIO_WritePin(PWMWL_GPIO_Port,PWMWL_Pin,GPIO_PIN_RESET);//W-break;case 3: /* V+ W- */__HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_3,0);//U+__HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_2,pwm_pulse);//V+__HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_1,0);//W+HAL_GPIO_WritePin(PWMUL_GPIO_Port,PWMUL_Pin,GPIO_PIN_RESET);//U-//GPIO_PIN_SET GPIO_PIN_RESETHAL_GPIO_WritePin(PWMVL_GPIO_Port,PWMVL_Pin,GPIO_PIN_RESET);//V-HAL_GPIO_WritePin(PWMWL_GPIO_Port,PWMWL_Pin,GPIO_PIN_SET);//W-break;case 4:/* W+ V- */__HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_3,0);//U+__HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_2,0);//V+__HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_1,pwm_pulse);//W+HAL_GPIO_WritePin(PWMUL_GPIO_Port,PWMUL_Pin,GPIO_PIN_RESET);//U-//GPIO_PIN_SET GPIO_PIN_RESETHAL_GPIO_WritePin(PWMVL_GPIO_Port,PWMVL_Pin,GPIO_PIN_SET);//V-HAL_GPIO_WritePin(PWMWL_GPIO_Port,PWMWL_Pin,GPIO_PIN_RESET);//W-break;case 5:/* U+ V -*/__HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_3,pwm_pulse);//U+__HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_2,0);//V+__HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_1,0);//W+HAL_GPIO_WritePin(PWMUL_GPIO_Port,PWMUL_Pin,GPIO_PIN_RESET);//U-//GPIO_PIN_SET GPIO_PIN_RESETHAL_GPIO_WritePin(PWMVL_GPIO_Port,PWMVL_Pin,GPIO_PIN_SET);//V-HAL_GPIO_WritePin(PWMWL_GPIO_Port,PWMWL_Pin,GPIO_PIN_RESET);//W-break;case 6:/* W+ U- */__HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_3,0);//U+__HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_2,0);//V+__HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_1,pwm_pulse);//W+HAL_GPIO_WritePin(PWMUL_GPIO_Port,PWMUL_Pin,GPIO_PIN_SET);//U-//GPIO_PIN_SET GPIO_PIN_RESETHAL_GPIO_WritePin(PWMVL_GPIO_Port,PWMVL_Pin,GPIO_PIN_RESET);//V-HAL_GPIO_WritePin(PWMWL_GPIO_Port,PWMWL_Pin,GPIO_PIN_RESET);//W-break;}}

更改pwm_pulse占空比值。然后就可以上电测试。!注意,上电前,一定确保你的这个换相逻辑和你的板子是对应起来的,别一上电上下桥同时导通,烧毁一切。

二、FOC

【FOC无刷电机控制】六步换向 FOC STM32cubemx从零开始搭建BLDC六步换相代码 FOC代码(基于霍尔传感器)

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。