基于FPGA的直流电机PWM调速系统设计与实现.docx
《基于FPGA的直流电机PWM调速系统设计与实现.docx》由会员分享,可在线阅读,更多相关《基于FPGA的直流电机PWM调速系统设计与实现.docx(15页珍藏版)》请在冰点文库上搜索。
基于FPGA的直流电机PWM调速系统设计与实现
FPGA课程设计
题目:
基于FPGA的直流电机PWM调速系统设计与实现
班级:
微电子学1202班
:
杜英
学号:
1206080201
日期:
2016年3月24日
基于FPGA的直流电机PWM调速系统设计与实现
1设计任务与要求
1.1设计任务
完成基于FPGA的直流电机PWM调速系统设计与实现,实现对直流电机的闭环调速,速度值采用LCD或数码管显示。
1.2设计要求
1.2.1了解PWM控制方法及应用;掌握PWM直流电机调速控制原理;掌握直流电机调速及驱动控制原理;完成基于FPGA的直流电机PWM调速系统设计。
采用PWM(脉冲宽度调制)技术,速度值采用LCD或数码管显示。
1.2.2通过课程设计的实践,进一步了解和掌握硬件描述语言(VHDL或Verilog)和TOP-DOWN的设计流程,提高对实际项目的分析和设计能力,体会FPGA项目开发的过程,熟悉实验报告的编写规范。
2设计原理分析
2.1直流电机结构如下图1.1所示
图2.1直流电机的构造
将直流电源通过电刷接通线组线圈,使线组线圈导体(电枢导体)有电流通过,在电磁的作用下,线组线圈将会产生磁场,同时产生的磁场与主磁极的磁场产生电磁力,这个电磁力作用于转子,使转子以一定的速度开始旋转,电机就开始工作。
在电机的外部电路加入开关型的霍尔元件,同时在电子转子的转盘上加入一个使霍尔元件产生输出的带有磁场的磁钢片。
当直流电机旋转时转盘与磁钢片一起旋转,当磁钢片转到霍尔元件上方时,可以使霍尔元件的输出端高电平变为低电平。
当磁钢片离开霍尔元件上方后,霍尔元件输出端又恢复高电平。
如此,点击每旋转一周,会使霍尔元件的输出端产生一个低脉冲,可以通过检测单位时间内霍尔元件输出端低脉冲的个数推算出直流电机的转速。
本次设计中,调节PWM占空比进而控制直流电机转速,在本次设计中,为了保护霍尔元件,故设定程序每6秒刷新一次数据,所以在数码管显示的数据乘以10就是在该占空比时的直流电机每分钟转速。
在这次的实验中数码管采用的8位共阴极数码管,通过锁存器输入数据使得数码管的8个段码数字显示,再通过选择输出数据对所需数码管进行选择。
2.2电路原理图
图2.2电路原理图
3设计方案
上述原理图中包含PWM模块、测速模块、计数模块、电机模块、滤波模块。
电机的外部电路加入开关型的霍尔元件,同时在电子转子的转盘上加入一个使霍尔元件产生输出的带有磁场的磁钢片。
当直流电机旋转时转盘与磁钢片一起旋转,当磁钢片转到霍尔元件上方时,可以使霍尔元件的输出端高电平变为低电平。
当磁钢片离开霍尔元件上方后,霍尔元件输出端又恢复高电平。
如此,点击每旋转一周,会使霍尔元件的输出端产生一个低脉冲,可以通过检测单位时间内霍尔元件输出端低脉冲的个数推算出直流电机的转速。
本次设计为六秒记一次数,乘十就是每分钟转速值。
再通过驱动模块显示数码管数据。
4设计步骤
(1)首先确定整体设计方案,确定设计需要使用的软件;
(2)设计电路模块,编写各模块程序代码并进行仿真编译;
(3)完成整体电路图设计后,使用QuartusⅡ软件对整体电路进行仿真调试;
(4)连接硬件,使用示波器观察产生的波形,对不足之处进行改进调试。
5调试结果说明
连接好试验箱,把硬件与实验箱接通,将程序下载到实验箱中。
进行实验,示波器观察PWM脉冲波形(占空比),看实验结果与预期效果是否相同,若相同,则实验无误。
其波形如下:
占空比为50%时
占空比为90%时
将程序下载到实验箱中后,其实际操作过程如下:
K12为使能键,使K12=‘1’;输入时钟信号为1MHZ;
(1)K4=1时,示波器和LED的显示如下:
示波器显示的是霍尔元件单位时间内计数的个数为31.011
显示器是每六秒电机转的圈数为186转
结论:
31.011*6=186.066于186近似,所以结论符合要求。
(2)K4=1,k3=1时,示波器和LED的显示如下:
结论:
68.6338*6=411.8028于412近似,所以结论符合要求。
(3)K4=1,k3=1,K2=1时,示波器和LED的显示如下:
结论:
85.516*6=513.096于513近似,所以结论符合要求。
(4)K4=1,k3=1,K2=1,K1=1时,示波器和LED的显示如下:
结论:
90.0339*6=540.2034于541近似,所以结论符合要求。
通过以上的比较,发现示波器中的结果与数码管上数据大概一致,即实验结果基本达到要求。
6心得体会
本次课程设计,用FPGA控制直流电机,完成直流电机PWM调速系统设计,实现对直流电机的闭环调速,速度值采用LCD或数码管显示。
是一次很好的学习和实践的机会。
通过课程设计,我明白了电机工作的原理,以及用FPGA控制电机的原理。
最重要的是,对如何设计一个系统有了更进一步的了解,积累了很多经验。
从下载测试的结果来看,设计的要求基本上都实现了。
但是仍存在不少问题。
每个模块生成基本电路后,把各个模块的进行连接,仿真结果是正确的。
但是当连接到试验箱后,电机正常转动,LED却无法显示。
检查电路和程序还有电路图,并发现什么问题。
无意中发现LED偶尔会出现数字,但也只是闪一下。
最后才发现是因为电机转动太快了,LED无法及时显示或者是一直在闪,人眼无法识别。
在程序中加入了滤波模块,才解决了问题。
在设计的过程中,开始照着EDA课本上的原理设计,后来才发现所设计的电路有很多地方都满足不了设计要求,使设计一度遭遇了很大困难。
通过与同学讨论请教,逐步改进了设计,终于使设计的电路和设计要求相吻合。
在这中间,通过不断提出问题,解决问题,我对这次设计的原理有了更深的了解,也给我分析问题,解决问题提供了很多好的方法,好的思路。
同时,我也发现了自己存在的很多不足。
发现自己在设计一个系统的时候不能够统筹兼顾,不能够从总体上把握设计的思路,也不能看清问题的核心与关键所在。
这些都需要在下面不断学习实践,理论毕竟只是理论,要多参加实践,这样才能提高自己的能力,积累经验。
附录一
PWM模块程序
Libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_arith.all;
useieee.std_logic_unsigned.all;
entityPWMis
port(
clock:
instd_logic;
duty_cycle:
instd_logic_vector(3downto0);
pwm_en:
instd_logic;
pwm_out:
outstd_logic);
endentity;
architectureartofPWMis
signalpwm_out_io:
std_logic;
signalcount:
std_logic_vector(3downto0);
begin
pwm_out<=pwm_out_io;
process(clock)
begin
ifrising_edge(clock)then
ifpwm_en='1'then
count<=count+1;
endif;
endif;
endprocess;
process(clock)
begin
ifrising_edge(clock)then
ifpwm_en='1'andcountpwm_out_io<='1';
else
pwm_out_io<='0';
endif;
endif;
endprocess;
end;
测速模块程序
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_arith.all;
useieee.std_logic_unsigned.all;
entitycesuis
port(clk:
instd_logic;--时钟输入1Mhz
ena:
outstd_logic;--允许计数
clr:
outstd_logic;--计数器清零信号产生
load:
outstd_logic);--锁存、显示输出允许高有效
endcesu;
architecturebehavofcesuis
signalclkk:
std_logic;--1HZ时钟信号
signalcount:
integerrange0to7;--6秒计数
signalclr1:
std_logic;--清零信号
signalena1:
std_logic;--允许计数信号
signalload1:
std_logic;--允许计数信号
--signalcq1,cq2,cq3,cq4:
INTEGERRANGE0TO15;--计数数据
begin
process(clk)
variablec:
std_logic;
variablet:
integerrange0to500000;
begin
ifclk'eventandclk='1'then
t:
=cnt+1;
ift=500000then
t:
=0;c:
=notc;
endif;
endif;
clkk<=c;
endprocess;
process(clkk)--6秒计数
begin
ifclkk'eventandclkk='1'then
count<=count+1;
ifcount<6then
ena1<='1';load1<='0';clr1<='0';
elsifcount=6then
ena1<='0';load1<='1';clr1<='0';
elsifcount=7then
ena1<='0';load1<='1';clr1<='1';
endif;
endif;
ena<=ena1;
load<=load1;
clr<=clr1;
endprocess;
endbehav;
计数模块程序
libraryieee;
useieee.std_logic_1164.all;
entityt10is
port(clk:
instd_logic;--计数时钟信号
clr:
instd_logic;--清零信号
ena:
instd_logic;--计数使能信号
cq:
outintegerrange0to15;--4位计数结果输出
carry_out:
outstd_logic);--计数进位
endt10;
architecturebehavoft10is
signalcq1:
integerrange0to15;
begin
process(clk,ena)
begin
ifclr='1'thencq1<=0;----计数器异步清零
elsifclk'eventandclk='1'then
ifena='1'then
ifcq1=10thencq1<=1;
elsecq1<=cq1+1;
endif;----等于9,则计数器清零
endif;
endif;
endprocess;
process(cq1)
begin
ifcq1=10thencarry_out<='1';----进位输出
elsecarry_out<='0';
endif;
endprocess;
cq<=cq1;
endbehav;
驱动模块程序
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_unsigned.all;
entityqudong_8is
port(clk:
instd_logic;--动态显示刷新速度时钟
QQ1,QQ2,QQ3:
instd_logic_vector(3downto0);--32位BCD码输入,最0~3低位,28~31最高位
qudong1:
outstd_logic_vector(7downto0);--驱动信号输出,0~7分别为abcdefgp
contrl:
bufferstd_logic_vector(2downto0));--数码管位选输出,000最低位数码管有效,111最高位数码管有效
endqudong_8;
architecturebehaviorofqudong_8is
signaldisp:
std_logic_vector(3downto0);
signaltemp:
std_logic_vector(2downto0);
begin
process(clk)
begin
ifclk'eventandclk='1'then
temp<=temp+1;
endif;
contrl<=temp;
endprocess;
process(contrl)--位选信号产生进程
begin
casecontrlis
--when"000"=>disp<=QQ7;
--when"001"=>disp<=QQ6;
--when"010"=>disp<=QQ5;
--when"011"=>disp<=QQ4;
when"100"=>disp<=QQ3;
when"101"=>disp<=QQ2;
when"110"=>disp<=QQ1;
--when"111"=>disp<="0000";
whenothers=>disp<="0000";
endcase;
endprocess;
process(disp)--译码进程
begin
casedispis
when"0000"=>qudong1<="00111111";
when"0001"=>qudong1<="00000110";
when"0010"=>qudong1<="01011011";
when"0011"=>qudong1<="01001111";
when"0100"=>qudong1<="01100110";
when"0101"=>qudong1<="01101101";
when"0110"=>qudong1<="01111101";
when"0111"=>qudong1<="00000111";
when"1000"=>qudong1<="01111111";
when"1001"=>qudong1<="01101111";
whenothers=>qudong1<="00000110";
endcase;
endprocess;
endbehavior;
消抖模块程序
libraryieee;
useieee.std_logic_1164.all;
entityxiaodouis
port(clk,input:
instd_logic;
output:
outstd_logic);
endxiaodou;
architecturebehavofxiaodouis
signalcp:
std_logic;
signalcount:
integerrange0to3;
begin
process(clk)
begin
if(clk'eventandclk='1')then--检测上升沿
if(input='1')then--如果有输入信号
if(count=3)thencount<=count;--当计数达到3时,保持计数值不变
elsecount<=count+1;--当其小于3时,进行加1处理
endif;
if(count=2)thencp<='1';--如果计数达到2,cp置1
elsecp<='0';--其余情况全部为0
endif;
elsecount<=0;--如果计数出现非法状况,进行清零复位
endif;
endif;
output<=cp;--信号输出
endprocess;
endbehav;