找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 8883|回复: 1
收起左侧

单片机直流电机PWM调速系统的设计与Proteus仿真工程

[复制链接]
ID:477182 发表于 2019-2-16 16:50 | 显示全部楼层 |阅读模式
0.png


直流电机
PWM调速系统的设计与仿真
  •          引言

1本课题设计的目的和要求

              1.              直流电机PWM调速系统的目的:

   (1) 熟悉直流电机PWM调速系统的整体运行过程和总体布局

                 (2) 掌握该硬件电路的设计方法

       (3) 掌握电机PWM调速系统程序的设计和调试

       2. 直流电机PWM调速系统的要求

      (1)可输入0~1范围的占空比,占空比可用电位器输入、拨码开关输入或键盘输入。

(2)设计电机驱动电路,根据输入的占空比控制电机转速。

(3)检测电机转速,并用LED或LCD显示。

(4)在PROTUES下仿真。



二、系统总体框图与原理说明

              2.1 总体方案原理及设计框图

                            本设计是基于AT89c51为核心的直流调速器,由单片机控制和产生适合要求的PWM信号,该PWM信号通过驱动芯片电路进行直流调速,使输出电压平均值和功率可以按照PWM信号的占空比而变化,从而达到对直流电机调速的目的。拨码开关输入0~1范围的占空比,用LCD1602作为主液晶显示器,显示输入的占空比控制电机转速,能够实现较好的人机交互。


总体方案设计框图



三、硬件电路图



              3.1 PWM产生方式

              (1)PWM(脉冲宽度调制)是通过控制固定电压的直流电源开关频率,改变负载两端的电压,从而达到控制要求的一种电压调整方法。PWM可以应用在很多方面,比如:电机调速、温度控制、压力控制等等。

              在PWM驱动控制的调整系统中,按一个固定的频率来接通和断开的电源,并且根据需要改变一个周期内“接通”和“断开”时间的长短。通过改变直流电机电枢上电压的“占空比”来达到改变平均电压大小的目的,从而来控制电动机的转速。正因为如此,PWM又被称为“开关驱动装置”。PWM波形如图所示:

PWM波形图

              设电机始终接通电路时,电机转速最大为,设占空比为:

则电机的平均转速为

其中指的是电机的平均速度,是指电机在全通电时最大速度,D指的是占空比。

由上面的公式可见,当改变占空比D时,就可以得到不同电机平均速度,从而达到调速的目的。

              (2)单片机片内软件生成PWM信号

                            PWM信号采用延时的方式产生,这样实现比较容易,可以节约硬件成本。

if(Flag0)

{

for(a=0;a<N*PWM_percent;a++)

{

              if(flag) k1=1;


              else k2=1;

}

for(a=0;a<N*(1-PWM_percent);a++)

{

              k1=k2=0;

}

}

else

{

k1=k2=1;

}


3.2拨码开关模块的设计

              本设计输入用4位的拨码开关,能产生16数值,每一种数值对应于一个占空比的值,当输入为16时,最大的占空比为100%,能调节到最大的电机转速。






3.3显示模块的设计

              本设计用LCD1602作为显示模块,它是一种专门用来显示字母、数字、符号等的点阵型液晶模块,可以显示两行,提供各种控制命令,如:清屏、字符闪烁、光标闪烁、显示移位等多种功能。




在进行写入数据时,我们设计了一个函数将要输入的字符串整个写入,减少了代码量,也使程序看起来更加简洁

void lcd_show_str(unsigned char *str)

{


              while (*str != '\0')

              {

                            LED_data(*str++); //同一优先级,先取内容后自增

              }

}

因为要显示测得的速度,而速度又是一个不止1位的整数,所以必须分离速度的各个位数值并写入LCD1602中。程序实现如下。

void display()

{

  LED_start(0x86);

  if(speed/10000==0)

  {

                  s[0]=' ';

   }

   else

   {

                               s[0]=speed/10000+0x30;

   }

  if(speed/1000==0)

   {

                 s[1]=' ';

              }

              else

              {

                              s[1]=              speed%10000/1000+0x30;

              }

              if(speed/100==0)

              {

                            s[2]= ' ';            

              }

              else

              {

                            s[2]=speed%10000%1000/100+0x30;

              }

              if(speed/10==0)

              {

                            s[3]=' ';

              }

              else

              {

                            s[3]=speed%10000%1000%100/10+0x30;

              }

    s[4]=speed%10000%1000%100%10+0x30;




    lcd_show_str(s);


}


3.4直流电机驱动模块

              本设计采用L298芯片来驱动电机,内部含有四通道逻辑驱动电路,是一种二相和四相的专用驱动器,PWM配合桥式L298可以较为容易的实现电机的调速,其中还用到了二极管对电机进行保护作用。电路图如下。



3.3模拟直流电机测速模块

              利用MOTOR-ENCODER每转一圈1/2引脚输出一次高电平的性能,我们将1/2引脚接入异或门的两个输入端,再将输出端接到外部中断1处,外部中断1每次收到一个高电平则进入中断,中断内是将speed加一,另外定时器0中断控制1s中记一次数,因此可以得到电动机每秒的转速,另外设置定时器1中断,使得T1计数十次的时候也就是1s时Speed清零。程序如下,电路图也如下

  1. ////****************************************************************************----1秒计时//

  2. void int1_isr(void)interrupt 2//中断1函数
  3. {
  4. speed++;
  5. }
  6. timer0()interrupt 1 using 1 //T0中断函数
  7. {
  8.               P2_1=~P2_1;
  9.               TH0=(65535-65050)/256;
  10.     TL0=(65335-65050)%256;
  11. }
  12. timer1()interrupt 3 using 2 //T1中断函数

  13. {
  14.               display();
  15.               speed=0;
  16. }
复制代码

              

MORTOR-ENCODER电机                    中断引脚设置

3.4 电动机调速功能实现模块

电动机调速功能分为以下四种:

  • 加速
  • 减速
  • 反转
  • 停止

1.加速模块利用增加PWM波的占空比增加电机速度,每按一次按键加速5%。程序设计是利用对按键按下的判断处理占空比变量加一。代码如下

  •       减速模块同理利用减小PWM占空比实现

  •       反转模块利用L298N的引脚IN0IN1输入01实现反转,代码中设置了反转标志位flag,如果flag1进行正转,如果flag0进行反转。在主函数生成pwm波时对flag进行判断以输出0,1实现电机的反转

  •       停功能

刹停功能的实现同样利用L298芯片实现,同时也将占空比变为0。同样设置一个刹停标志位Flag0,当刹停按键按下时Flag0置零并将占空比变量置零,而在PWM波形输出模块中,Flag0为1是输出PWM波输出的条件,因此不输出PWM波且,IN1和IN2都为高电平因此达到刹停效果。

  •       自定义速度功能

自定义速度功能通过设置占空比实现,这里将PWM波的占空比分为了16档,用到了拨码开关,共4位二进制数也就是=16种情况。最高占空比为100%,低电平有效,而这些利用单片机P1引脚的高四位实现,具体代码如下。

if(P1_2==0)                                          //自定义速度(15个档)

{

              delay(5);                                          //消抖

              PWM_percent=(((0xf0)&(~P1))*100)/(0xf0);

              PWM_percent=PWM_percent*0.01;                                                                                                                       //将输入的二进制数转换成为占空比

}


3.5按键设计模块

在设计过程中,我们利用外部中断0,将接了五个按键的引脚连线同时接入一个与门,与门的输出则接到外部中断0,使得每次按下按键都会进入中断0函数,执行相应的功能代码。

题目要求实现五种功能,



四、仿真说明

              (1)初始界面时,拨码开关没有设置PWM,直流电机处于停止状态,LCD1602显示PWM为0%,电机速度也为0,示波器显示波形也为低电平。

   


              (2)按一次加速按键,占空比增加5%

         

按一次减速按键,速度减小5%(之前占空比为20%)

按刹停按键,速度减小至0,占空比为0

调节拨码开关设置自定义占空比


按反转键,电机反转并在LCD中由Z变为F

测速模块

利用encode电机的转一圈上方两侧引脚输出高电平接一个异或门从而通过上升沿反映电机转一圈,并给中断1送信号speed+1,记出一秒内speed表转速。



P3.1口输出PWM波形




六、心得体会

巧妙运用计时器可以达到预想中的计时效果,运用各元件的特性可以最优化电路图,在设计的过程中如果遇到问题别灰心,静下来想一想,或者在网上找找他人的做法,也许对你的设计有异曲同工之妙。程序设计需细致,符号一错全盘出错。中断是个好东西,如果巧妙利用外部中断可以使得你的程序更加具有可辩性和通用性。

  1. #include<reg51.h>
  2. #define N 750
  3. #define uchar unsigned char
  4. #define uint unsigned int
  5. sbit k1=P3^0;
  6. sbit k2=P3^1;
  7. sbit P2_0=P2^0;
  8. sbit P2_1=P2^1;
  9. sbit P2_2=P2^2;
  10. sbit P1_0=P1^0;
  11. sbit P1_1=P1^1;
  12. sbit P1_2=P1^2;
  13. sbit P3_2=P3^2;
  14. sbit P1_3=P1^3;
  15. bit flag=1;
  16. unsigned char s[6]="00000";
  17. sbit en=P2^5;                //1602             6管脚
  18. sbit rs=P2^7;                //1602端口         4管脚
  19. sbit rw=P2^6;                //lcd1602控制端口  5管脚
  20. double PWM_percent=0;
  21. int speed=0;
  22. //****************************************************************************----延时小函数//
  23. void lcd_show_str(unsigned char *str);
  24. void LED_start(uchar com);
  25. void LED_data(uchar date);
  26. void delay(uint z);
  27. void display();
  28. void display_percent();
  29. void lcd_show_str(unsigned char *str)
  30. {

  31.         while (*str != '\0')
  32.         {
  33.                 LED_data(*str++); //同一优先级,先取内容后自增
  34.         }
  35. }
  36. void delay(uint z)//延时1ms函数
  37. {

  38.         uint x,y;
  39.         for(x=0;x<z;x++)
  40.              for(y=0;y<110;y++);
  41. }

  42. //******************************************************************************---LED显示//
  43. void LED_start(uchar com)//向1602写一字节(控制指令)
  44. {
  45.   rs=0;
  46.   P0=com;
  47.   delay(5);
  48.   en=0;
  49.   delay(10);
  50.   en=1;
  51. }
  52. void LED_data(uchar date)//向1602写一字节(数据)
  53. {
  54.   rs=1;
  55.   P0=date;
  56.   delay(5);
  57.   en=0;
  58.   delay(5);
  59.   en=1;
  60. }
  61. void display()
  62. {
  63.   LED_start(0x86);
  64.   if(speed/10000==0)
  65.   {
  66.             s[0]=' ';
  67.   }
  68.    else
  69.    {
  70.                    s[0]=speed/10000+0x30;
  71.    }
  72.    if(speed/1000==0)
  73.    {
  74.            s[1]=' ';
  75.         }
  76.         else
  77.         {
  78.                   s[1]=        speed%10000/1000+0x30;
  79.         }
  80.         if(speed/100==0)
  81.         {
  82.                 s[2]= ' ';       
  83.         }
  84.         else
  85.         {
  86.                 s[2]=speed%10000%1000/100+0x30;
  87.         }
  88.         if(speed/10==0)
  89.         {
  90.                  s[3]=' ';
  91.         }
  92.         else
  93.         {
  94.                 s[3]=speed%10000%1000%100/10+0x30;
  95.         }
  96. s[4]=speed%10000%1000%100%10+0x30;
  97.        
  98.          

  99.   lcd_show_str(s);

  100. }

  101. void display_percent()
  102. {
  103.         int m=PWM_percent*100;
  104.         LED_start(0xc8);
  105.   if(m/100==0)
  106.   LED_data(' ');
  107.   else
  108.   LED_data(m/100+0x30);                   //百分百占空比,否则显示空格

  109.   if(m/10==0)
  110.                 LED_data(' ');
  111.   else
  112.                 LED_data(m%100/10+0x30);              //显示十位
  113.           LED_data(m%100%10+0x30);              //显示个位
  114. }
  115. //****************************************************************************----功能区//

  116. void int0_isr(void)interrupt 0 //中断0函数    和   它的流氓按键们
  117. {
  118.        
  119. if(P1_0==0)                                          //加速
  120. {
  121.         delay(5);                                          //消抖
  122. if(PWM_percent<1)
  123.         PWM_percent=PWM_percent+0.05;
  124. if(PWM_percent+0.05>1)//判断占空比溢出
  125.         PWM_percent=1;
  126. }


  127. if(P1_1==0)                                          //减速
  128. {
  129.         delay(5);                                          //消抖
  130. if(PWM_percent>0)
  131.         PWM_percent=PWM_percent-0.05;
  132. if(PWM_percent+0.05<0)
  133.         PWM_percent=0;
  134. }


  135. if(P1_3==0)                           //停止
  136. {
  137.         delay(5);                                          //消抖
  138.         PWM_percent=0;
  139. }

  140. if(P1_2==0)                                          //自定义速度(15个档)
  141. {
  142.         delay(5);                                          //消抖
  143.         PWM_percent=(((0xf0)&(~P1))*100)/(0xf0);
  144.         PWM_percent=PWM_percent*0.01;                                                                       //将输入的二进制数转换成为占空比
  145. }

  146. if(P2_0==0)
  147. {       
  148.         delay(5);                                          //消抖
  149.         flag=~flag;                                                //反向加速
  150. }
  151. display_percent();                                    //每次调速后显示
  152. LED_start(0xcf);
  153. if(flag) LED_data('Z');
  154. else LED_data('F');  
  155.        
  156. }
  157. void init()               //初始化函数
  158. {
  159.   en=0;
  160.   rw=0;
  161.   LED_start(0x01);        //lcd初始化
  162.   LED_start(0x38);        //5X7显示
  163.   LED_start(0x0c);
  164.        
  165.         LED_start(0x80);
  166.         lcd_show_str("speed:");
  167.        
  168.   
  169.         LED_start(0x8b);              //第一行显示转速
  170.         lcd_show_str("r/m");

  171.        
  172.   LED_start(0xc0);        //在第二行显示Percent:
  173.   lcd_show_str("Percent:");
  174.   
  175.   display_percent();
  176.         LED_data('%');
  177.         LED_start(0xcf);
  178.         LED_data('Z');
  179.        
  180. }

  181. ////****************************************************************************----1秒计时//
  182. void int1_isr(void)interrupt 2//中断1函数
  183. {
  184. speed++;
  185. }
  186. timer0()interrupt 1 using 1 //T0中断函数
  187. {
  188.         P2_1=~P2_1;
  189.         TH0=(6335-70000)/256;
  190.         TL0=(6335-70000)%256;
  191. }
  192. timer1()interrupt 3 using 2 //T1中断函数
  193. {
  194.         display();
  195.         speed=0;
  196.        
  197. }
  198. main()
  199. {
  200. int a;
  201. EX0=1;
  202. IT0=1;
  203. EX1=1;
  204. IT1=1;
  205. P2_1=1;
  206. TMOD=0x61; //定时器T0方式1计时,计数器0方式0计数
  207. TH0=(6335-70000)/256;
  208. TL0=(6335-70000)%256;       
  209. TH1=256-10;
  210. TL1=256-10;
  211. EA=1;
  212. ET0=1;
  213. ET1=1;
  214. TR0=1;
  215. TR1=1;
  216. init();
  217. do
  218. {
  219. for(a=0;a<N*PWM_percent;a++)
  220. {
  221.         if(flag) k1=1;
  222.        
  223.         else k2=1;
  224. }
  225. for(a=0;a<N*(1-PWM_percent);a++)
  226. {
  227.         k1=k2=0;
  228. }
  229. }while(1);

  230. }

复制代码


全部资料51hei下载地址:
第四组PWM电机调速系统.rar (618.66 KB, 下载次数: 243)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:712614 发表于 2020-4-13 22:06 | 显示全部楼层
下面是测试效果
51hei.png
51hei.png
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表