文档视界 最新最全的文档下载
当前位置:文档视界 › 基于STM32的直流电机PWM调速控制

基于STM32的直流电机PWM调速控制

基于STM32的直流电机PWM调速控制
基于STM32的直流电机PWM调速控制

(《嵌入式系统及接口技术》课程大作业)

课程名称:嵌入式系统及接口技术

班级专业:

姓名学号:

指导老师:

电动摩托车控制器中的电机PWM调速

摘要:随着“低碳”社会理念的深入,新型的电动摩托车发展迅速,逐渐成为人们主要的代步工具之一,由于直流无刷电机的种种优点,在电动摩托车中也得到了广泛应用,因此,本文控制部分主要介绍一种基于STM32F103芯片的新型直流无刷电机调速控制系统,这里主要通过PWM技术来进行电机的调速控制,且运行稳定,安全可靠,成本低,具有深远的意义。

1.总体设计概述

1.1 直流无刷电机及工作原理

直流无刷电机(简称BLDCM),由于利用电子换向取代了传统的机械电刷和换向器,使得其电磁性能可靠,结构简单,易于维护,既保持了直流电机的优点又避免了直流电机因电刷而引起的缺陷,因此,被广泛应用。另外,由于直流无刷电机专用控制芯片价格昂贵,本文介绍了一种基于STM32的新型直流无刷电机控制系统,既可降低直流无刷电机的应用成本,又弥补了专用处理器功能单一的缺点,具有重要的现实意义和发展前景。

工作原理:直流无刷电机是同步电机的一种,其转子为永磁体,而定子则为三个按照星形连接方式连接起来的线圈,根据同步电机的原理,如果电子线圈产生一个旋转的磁场,则永磁体的转子也会随着这个磁场转动因此,驱动直流无刷电机的根本是产生旋转的磁场,而这个旋转的磁场可以通过调整A、B、C三相的电流来实现,其需要的电流如图1所示

随着我国经济和文化事业的发展,在很多场合,都要求有直流电机PWM调速系统来进行调速,诸如汽车行业中的各种风扇、刮水器、喷水泵、熄火器、反视镜、宾馆中的自动门、自动门锁、自动窗帘、自动给水系统、柔巾机、导弹、火炮、人造卫星、宇宙飞船、舰艇、飞机、坦克、火箭、雷达、战车等场合。

1.2 总体设计方案

总体设计方案的硬件部分详细框图如图1所示。

图1 总体方案系统框图

该方案主要运行状况如下:通过摩托车车把的转动来改变其机械位置,然后这个变量通过ADC 转换后,传送其调速信号给STM32F103,另外,霍尔传感器将其对电机速度的检测信号也传送给STM32,在STM32中,首先根据ADC 的值改变PWM 波形,并且与霍尔传感器的检测信号进行叠加,最终输出叠加后的PWM 波形给功率驱动电路,从而驱动电机并对其进行速度的控制和调节。

2.

系统硬件设计

2.1 总体硬件框图

系统的硬件电路选用STM32F103为主控芯片,作为电机控制的核心,通过霍尔位置传感器检测位置信号,结合功率驱动电路以实现对电机的驱动。 此外,还有电流检测电路可根据电机的状态以调整转速和实现过流保护功能 系统的硬件框图如图2所示:

图2 系统硬件框图

2.2 电机功率驱动电路设计

直流无刷电机是将直流有刷电机的机械换向改进成电子换向而来的,要使其转动,就必须通过电子换向的方法调整电流,

按照转子所在的位置产生转动磁场,主控芯片控制H半桥驱动电路产生电机转动的换向电流,以产生转动的磁场,驱动电路如图3所示

驱动电路的作用是将控制电路输出的脉冲放大到足以驱动功率晶体管或MOSFET管,所以单从原理上讲,驱动电路主要起开关功率放大作用,即脉冲放大器。但随着开关工作频率的提高,驱动电路的优化设计显得越来越重要。驱动电路的最佳驱动特性应具有:功率管开通时,驱动电路提供的基极电流应有快速的上升沿,并一开始有一定的过冲,以加速开通过程,并在集电极电流尖峰时开启驱动基极,从而减小开通损耗;功率管导通期间,驱动电路提供的基极电流在任何负载情况下都能保证功率管处于饱和导通状态,使功率管的饱和压降较低,以保证低的导通损耗;关断瞬时,驱动电路应提供足够的反向基极驱动,以迅速抽出基区的剩余载流子,并加反偏截止电压,使集电极电流迅速下降以减少下降时间。

为了增加系统的抗干扰能力,STM32 输出的6路PWM信号首先必须经隔离再送到IR2136进行驱动,由于开关速度达到20KHz左右,故设计中选用高速光耦器件HCPL4504,见图3,其最高速度可达1Mbit/s,内部的噪声抑制电路可提供高于15kV/us的共模抑制。

IR2136是IR公司的一款功率MOSFET、IGBT专用栅极驱动集成电路,独有的I-IVIC(High voltage integrated circuit)技术使得它可用作驱动工作在母线电压高达600V的电路中的功率MOS器件。其内部采用自举技术,使得功率驱动元件驱动电路仅需输入一个直流电源,使其实现对功率MOSFET和IGBT的最优驱动,并且它还具有完善的保护功能包括欠压保护和过流保护,以便保证系统安全稳定的工作。故本文选用IR2136作为主功率部分的MOSFET驱动,如图3所示:图3中经IR2136驱动的6路PwM信号被直接送到由6个MOSFET管组成的主功率电路。如图所示,该功率驱动采用三相全控电路,电动机的三相绕组为Y 型联结。MOSFET管选用IR公司的IRFZ48,该管导通电阻较低,当连续流过10A 电流时,功耗才1.2w,根本不需要散热片就可以稳定工作。

图3 功率驱动电路

2.3 直流无刷电机的调速

直流无刷电机调速的原理就是在驱动电机转动的基础上,将驱动电流由PWM 信号来控制,改变PWM 信号的脉冲宽度,即通过调节MOSFET通断的时间来调节提供给电机三相的电流大小,从而对电机进行调速控制。

本方案中MOSFET管的导通是通过STM32的PWM 信号来控制的, STM32内部的普通的定时器TIM3和TIM4,每个可以产生四路PWM发生器,这里用TIM3产生4路,TIM4产生两路,共六路可编程的PWM信号,驱动H桥。

直流无刷电机的电子换向是基于转子的位置来控制的,本系统采用3个霍尔传感器对直流无刷电机进行位置测量霍尔传感器安装在电机的内部,将转子的位置转换为三路数字信号直接输出到STM32的GPIO口在本设计中可方便地用于通过检测霍尔位置传感器的信号来实现检测转子的位置,然后据此输出相应的PWM信号控制功率管的导通或关断,从而实现电流的换向,在电机内部产生一个转动的磁场,进而驱动电机旋转。另外,车把转动的时候会通过一个DA转换,然后得到调速的标志flag的值,从而根据这个flag值来改变PWM波的占空比,从而进行电机的调速。

直流无刷电机旋转时三个霍尔传感器的信号值和输出的PWM信号之间的对应关系如图4所示

图4 相位与PWM信号的对应关系

霍尔传感器的位置反馈信号在可以确定转子位置的同时,也可用来测量电机的转速电机每转动一周,每个霍尔传感器即会产生两次换向,三个霍尔传感器共会有6次换相,这六次换相之间的时间差即为电机运转一周所需的时间,继而可计算出电机的转速根据计算出的电机转速,调整PWM信号的脉冲宽度,从而达到调速的目的

3.系统软件设计

本系统编程部分工作在keil4开发环境下完成,采用模块化的设计方法,与各子程序作为实现各部分功能和过程的入口,完成PWM脉宽调速的控制。STM32F103资源分配如下表:

表1 芯片的资源分配

1.PWM产生程序:本设计中采用STM32F103的定时器TIM3,TIM4两个定时器来

产生PWM波形,程序函数如下:

#include "timer.h"

//通用定时器中断初始化

//这里时钟选择为APB1的2倍,而APB1为36M

//arr:自动重装值。

//psc:时钟预分频数

//这里使用的是定时器3

void Timerx_Init(u16 arr,u16 psc)

{

RCC->APB1ENR|=1<<1;//TIM3时钟使能

TIM3->ARR=arr; //设定计数器自动重装值//刚好1ms

TIM3->PSC=psc; //预分频器7200,得到10Khz的计数时钟

//这两个东东要同时设置才可以使用中断

TIM3->DIER|=1<<0; //允许更新中断

TIM3->DIER|=1<<6; //允许触发中断

TIM3->CR1|=0x01; //使能定时器3

MY_NVIC_Init(1,3,TIM3_IRQChannel,2);//抢占1,子优先级3,组2 }

void PWM1_1_Init(u16 arr1,u16 psc1)

{

//此部分需手动修改IO口设置

RCC->APB1ENR|=1<<1; //TIM3时钟使能

GPIOA->CRL&=0XF0FFFFFF;//PA6输出

GPIOA->CRL|=0X0B000000;//复用功能输出

GPIOA->ODR|=1<<6;//PA6上拉

TIM3->ARR=arr1;//设定计数器自动重装值

TIM3->PSC=psc1;//预分频器不分频

TIM3->CCMR1|=7<<4; //CH1 PWM2模式

TIM3->CCMR1|=1<<3; //CH1预装载使能

TIM3->CCER|=1<<0; //OC1 输出使能

TIM3->CR1=0x8000; //ARPE使能

TIM3->CR1|=0x01; //使能定时器3

}

void PWM1_2_Init(u16 arr2,u16 psc2)

{

//此部分需手动修改IO口设置

RCC->APB1ENR|=1<<1; //TIM3时钟使能GPIOA->CRL&=0X0FFFFFFF;//PA7输出GPIOA->CRL|=0XB0000000;//复用功能输出GPIOA->ODR|=1<<7;//PA7上拉

TIM3->ARR=arr2;//设定计数器自动重装值

TIM3->PSC=psc2;//预分频器不分频

TIM3->CCMR1|=7<<12; //CH2 PWM2模式TIM3->CCMR1|=1<<11; //CH2预装载使能

TIM3->CCER|=1<<4; //OC2 输出使能

TIM3->CR1=0x8000; //ARPE使能

TIM3->CR1|=0x01; //使能定时器3

}

void PWM1_3_Init(u16 arr3,u16 psc3)

{

//此部分需手动修改IO口设置

RCC->APB1ENR|=1<<1; //TIM3时钟使能GPIOB->CRL&=0XFFFFFFF0;//PB0输出GPIOB->CRL|=0X0000000B;//复用功能输出GPIOB->ODR|=1<<0;//PB0上拉

TIM3->ARR=arr3;//设定计数器自动重装值

TIM3->PSC=psc3;//预分频器不分频

TIM3->CCMR2|=7<<4; //CH3 PWM2模式

TIM3->CCMR2|=1<<3; //CH3预装载使能

TIM3->CCER|=1<<8; //OC3 输出使能

TIM3->CR1=0x8000; //ARPE使能

TIM3->CR1|=0x01; //使能定时器3

}

void PWM1_4_Init(u16 arr4,u16 psc4)

{

//此部分需手动修改IO口设置

RCC->APB1ENR|=1<<1; //TIM3时钟使能GPIOB->CRL&=0XFFFFFF0F;//PB1输出GPIOB->CRL|=0X000000B0;//复用功能输出GPIOB->ODR|=1<<1;//PB1上拉

TIM3->ARR=arr4;//设定计数器自动重装值

TIM3->PSC=psc4;//预分频器不分频

TIM3->CCMR2|=7<<12; //CH4 PWM2模式TIM3->CCMR2|=1<<11; //CH4预装载使能

TIM3->CCER|=1<<12; //OC4 输出使能

TIM3->CR1=0x8000; //ARPE使能

TIM3->CR1|=0x01; //使能定时器3

}

void PWM2_1_Init(u16 arr5,u16 psc5)

{

//此部分需手动修改IO口设置

RCC->APB1ENR|=1<<2; //TIM4时钟使能GPIOB->CRL&=0XF0FFFFFF;//PB6输出GPIOB->CRL|=0X0B000000;//复用功能输出GPIOB->ODR|=1<<6;//PB6上拉

TIM4->ARR=arr5;//设定计数器自动重装值

TIM4->PSC=psc5;//预分频器不分频

TIM4->CCMR1|=7<<4; //CH1 PWM2模式

TIM4->CCMR1|=1<<3; //CH1预装载使能

TIM4->CCER|=1<<0; //OC1 输出使能

TIM4->CR1=0x8000; //ARPE使能

TIM4->CR1|=0x01; //使能定时器4

}

void PWM2_2_Init(u16 arr6,u16 psc6)

{

//此部分需手动修改IO口设置

RCC->APB1ENR|=1<<2; //TIM4时钟使能

GPIOB->CRL&=0X0FFFFFFF;//PB7输出

GPIOB->CRL|=0XB0000000;//复用功能输出

GPIOB->ODR|=1<<7;//PB7上拉

TIM4->ARR=arr6;//设定计数器自动重装值

TIM4->PSC=psc6;//预分频器不分频

TIM4->CCMR1|=7<<12; //CH2 PWM2模式

TIM4->CCMR1|=1<<11; //CH2预装载使能

TIM4->CCER|=1<<4; //OC2 输出使能

TIM4->CR1=0x8000; //ARPE使能

TIM4->CR1|=0x01; //使能定时器4

}

2、霍尔传感器部分的程序

#include "huoer.h"

void huoer_Init(void)

{

RCC->APB2ENR|=1<<5; //使能PORTD时钟

GPIOD->CRL&=0XF000FFFF; //PD4,5,5设置成输入

GPIOD->CRL|=0X08880000;

GPIOD->ODR|=1<<4; //PD4上拉

GPIOD->ODR|=1<<5; //PD5上拉

GPIOD->ODR|=1<<6; //PD6上拉

}

3、延时程序

#include

#include "delay.h"

static u8 fac_us=0;//us延时倍乘数

static u16 fac_ms=0;//ms延时倍乘数

//初始化延迟函数

//SYSTICK的时钟固定为HCLK时钟的1/8

//SYSCLK:系统时钟

void delay_init(u8 SYSCLK)

{

SysTick->CTRL&=0xfffffffb;//bit2清空,选择外部时钟HCLK/8 fac_us=SYSCLK/8;

fac_ms=(u16)fac_us*1000;

}

//延时nms

//SysTick->LOAD为24位寄存器,所以,最大延时为:

//nms<=0xffffff*8*1000/SYSCLK

//对72M条件下,nms<=1864

void delay_ms(u16 nms)

{

u32 temp;

SysTick->LOAD=(u32)nms*fac_ms;//时间加载(SysTick->LOAD为24bit) SysTick->V AL =0x00; //清空计数器

SysTick->CTRL=0x01 ; //开始倒数

do

{

temp=SysTick->CTRL;

}

while(temp&0x01&&!(temp&(1<<16)));//等待时间到达

SysTick->CTRL=0x00; //关闭计数器

SysTick->V AL =0X00; //清空计数器

}

//延时nus

//nus为要延时的us数.

void delay_us(u32 nus)

{

u32 temp;

SysTick->LOAD=nus*fac_us; //时间加载

SysTick->V AL=0x00; //清空计数器

SysTick->CTRL=0x01 ; //开始倒数

do

{

temp=SysTick->CTRL;

}

while(temp&0x01&&!(temp&(1<<16)));//等待时间到达

SysTick->CTRL=0x00; //关闭计数器

SysTick->V AL =0X00; //清空计数器

}

4、主程序

#include

#include "sys.h"

#include "delay.h"

#include "timer.h"

#include "huoer.h"

int main(void)

{

u8 flag; //DA转换过来的调速标志

Stm32_Clock_Init(9); //系统时钟设置

delay_init(72); //延时初始化

PWM1_1_Init(900,0); //不分频。PWM频率=72000/900=8Khz

PWM1_2_Init(900,0);

PWM1_3_Init(900,0);

PWM1_4_Init(900,0);

PWM2_1_Init(900,0);

PWM2_2_Init(900,0);

while(1)

{

switch(flag)

{

case 0: PWM1_V AL=900;

PWM2_V AL=900;

PWM3_V AL=900;

PWM4_V AL=900;

PWM5_V AL=900;

PWM6_V AL=900;

break;

case 1: if((huoer1==1)&&(huoer3==0)) PWM1_V AL=300;

else PWM1_V AL=900;

if((huoer1==0)&&(huoer2==1)) PWM2_V AL=300;

else PWM2_V AL=900;

if((huoer2==0)&&(huoer3==1)) PWM3_V AL=300;

else PWM3_V AL=900;

if((huoer1==0)&&(huoer3==1)) PWM4_V AL=300;

else PWM4_V AL=900;

if((huoer1==1)&&(huoer2==0)) PWM5_V AL=300;

else PWM5_V AL=900;

if((huoer2==1)&&(huoer3==0)) PWM6_V AL=300;

else PWM6_V AL=900;

break;

case 2: if((huoer1==1)&&(huoer3==0)) PWM1_V AL=350;

else PWM1_V AL=900;

if((huoer1==0)&&(huoer2==1)) PWM2_V AL=350;

else PWM2_V AL=900;

if((huoer2==0)&&(huoer3==1)) PWM3_V AL=350;

else PWM3_V AL=900;

if((huoer1==0)&&(huoer3==1)) PWM4_V AL=350;

else PWM4_V AL=900;

if((huoer1==1)&&(huoer2==0)) PWM5_V AL=350;

else PWM5_V AL=900;

if((huoer2==1)&&(huoer3==0)) PWM6_V AL=350;

else PWM6_V AL=900;

break;

case 3: if((huoer1==1)&&(huoer3==0)) PWM1_V AL=400;

else PWM1_V AL=900;

if((huoer1==0)&&(huoer2==1)) PWM2_V AL=400;

else PWM2_V AL=900;

if((huoer2==0)&&(huoer3==1)) PWM3_V AL=400;

else PWM3_V AL=900;

if((huoer1==0)&&(huoer3==1)) PWM4_V AL=400;

else PWM4_V AL=900;

if((huoer1==1)&&(huoer2==0)) PWM5_V AL=400;

else PWM5_V AL=900;

if((huoer2==1)&&(huoer3==0)) PWM6_V AL=400;

else PWM6_V AL=900;

break;

case 4: if((huoer1==1)&&(huoer3==0)) PWM1_V AL=450;

else PWM1_V AL=900;

if((huoer1==0)&&(huoer2==1)) PWM2_V AL=450;

else PWM2_V AL=900;

if((huoer2==0)&&(huoer3==1)) PWM3_V AL=450;

else PWM3_V AL=900;

if((huoer1==0)&&(huoer3==1)) PWM4_V AL=450;

else PWM4_V AL=900;

if((huoer1==1)&&(huoer2==0)) PWM5_V AL=450;

else PWM5_V AL=900;

if((huoer2==1)&&(huoer3==0)) PWM6_V AL=450;

else PWM6_V AL=900;

break;

case 5: if((huoer1==1)&&(huoer3==0)) PWM1_V AL=500;

else PWM1_V AL=900;

if((huoer1==0)&&(huoer2==1)) PWM2_V AL=500;

else PWM2_V AL=900;

if((huoer2==0)&&(huoer3==1)) PWM3_V AL=500;

else PWM3_V AL=900;

if((huoer1==0)&&(huoer3==1)) PWM4_V AL=500;

else PWM4_V AL=900;

if((huoer1==1)&&(huoer2==0)) PWM5_V AL=500;

else PWM5_V AL=900;

if((huoer2==1)&&(huoer3==0)) PWM6_V AL=500;

else PWM6_V AL=900;

break;

case 6: if((huoer1==1)&&(huoer3==0)) PWM1_V AL=550;

else PWM1_V AL=900;

if((huoer1==0)&&(huoer2==1)) PWM2_V AL=550;

else PWM2_V AL=900;

if((huoer2==0)&&(huoer3==1)) PWM3_V AL=550;

else PWM3_V AL=900;

if((huoer1==0)&&(huoer3==1)) PWM4_V AL=550;

else PWM4_V AL=900;

if((huoer1==1)&&(huoer2==0)) PWM5_V AL=550;

else PWM5_V AL=900;

if((huoer2==1)&&(huoer3==0)) PWM6_V AL=550;

else PWM6_V AL=900;

break;

case 7: if((huoer1==1)&&(huoer3==0)) PWM1_V AL=600;

else PWM1_V AL=900;

if((huoer1==0)&&(huoer2==1)) PWM2_V AL=600;

else PWM2_V AL=900;

if((huoer2==0)&&(huoer3==1)) PWM3_V AL=600;

else PWM3_V AL=900;

if((huoer1==0)&&(huoer3==1)) PWM4_V AL=600;

else PWM4_V AL=900;

if((huoer1==1)&&(huoer2==0)) PWM5_V AL=600;

else PWM5_V AL=900;

if((huoer2==1)&&(huoer3==0)) PWM6_V AL=600;

else PWM6_V AL=900;

break;

}

}

}

4.系统软件仿真

根据已知条件,利用keil4进行软件仿真,这里前提是假设霍尔传感器的三个值huoer1,huoer2,huoer3为别为0、1、0,然后分别假设flag的值为1 和7 ,仿真可以得到GPIOA6的PWM波形如下,这样,可以看出程序PWM脉宽进行了调整,但是,在实际的过程中,应根据电动车的速度,适当的设置系统的频率等参数。

图5 软件仿真PWM波形

5.结论

本设计对直流无刷电机的原理及其控制进行了研究,探讨了基于Cortex- M3的处理器在直流无刷控制系统中的应用方法系统采STM32F103为控制芯片,结合功率管组成的功率驱动电路,实现对直流无刷电机的启动和稳速调控。

此部分硬件部分主要为STM32F103最小系统、电源电路、电机功率驱动电路等,完成各部分电路设计并使用Altium Designer 6.9画出电路设计原理图,软件部分是在STM32集成开发环境KEIL4下编写各模块程序,包括PWM波输出模块、霍尔传感器模块、延时模块等并通过主控制程序将各模块融合一起。

参考文献

[1]潘在河,严卫生.ARM在无刷直流电机控制系统中的应用[J].机械与电子,2009.

[2]常秋安.浅谈他励直流电机与三相交流电机调速方式与故障维修[J].设备管理与改造,2011.

[3]詹瑜坤.直流无刷电机原理及其数字化控制发展方向[J].中国科技信息,2010.

[4] 康华光,《电子技术基础》(模拟部分),高等教育出版社,2007.11.

[5]康华光,《电子技术基础》(数字部分),高等教育出版社,2007.11.

(注:可编辑下载,若有不当之处,请指正,谢谢!)

相关文档