直流电机转速控制系统报告
- 格式:doc
- 大小:1.08 MB
- 文档页数:16
微机系统与应用课程设计实验报告直流电机转速测量与控制系统设计与实现评语:成绩教师:年月日班级:学号:姓名:实验地点:实验时间:直流电机转速测量与控制系统设计与实现一、应用系统设计方案设计目的:了解以微机为核心的闭环控制系统的组成原理。
掌握电机转速闭环控制系统的构成方法。
了解霍尔器件的工作原理:电机转速的测量与控制的基本原理。
掌握PWM调速原理和应用方法。
掌握控制系统的设计与调试方法,提高分析问题和解决问题能力。
二、课程设计的内容:设计一个对直流电机转速测量与转速控制的闭环控制系统。
微机控制中心在监控界面上设置电机转速。
电机转速测量利用霍尔传感器电路产生转速脉冲,定时/计数电路通过脉冲计数获得转速参量。
电机转速调整采用PWM(脉宽调节)方法,控制中心采样到电机转速参量,算得转速值同预定转速设置值进行比较,若不相同,则调整控制转速脉冲的占空比,来达到调速的目的。
(占空比=脉冲宽度/脉冲周期)三、系统功能要求与设计要求:1)系统监控界面设计:监控系统具有转速参数设置窗口、采样的电机转速数据显示窗口、转速动态曲线显示窗口及强行干预系统运行的按钮功能或相应功能选择菜单。
2)监控程序设计要求:监控程序用查询方式获取转速数据。
监控程序用中断方式获取转速数据。
3)硬件设计要求:充分利用现有实验系统资源设计一个性能较好的直流电机转速闭环控制系统。
利用带锁存的I/O接口电路(如8255,74LS273,D/A-DA0832)输出控制电机转速的脉冲。
采样转速用霍尔传感器件提供电机转速脉冲。
利用定时/计数电路对电机转速脉冲计数。
微机可从定时/计数电路中获得电机转速数值,并产生控制电机转速的PWM 脉冲。
四、设计详情:1)闭环控制系统原理图图一电机转速测量与控制闭环系统基本功能图2)电机控制及转速测量原理图图二电机控制及转速测量原理图3)硬件连线图图三硬件连线图4)操作步骤直流电机在控制脉冲作用下转动,电机转盘上的永久磁铁随之旋转,霍尔传感器件3101T受磁场的影响,从端口OUT输出脉冲信号,电机旋转一圈,霍尔传感器输出一个脉冲,脉冲频率于电机转速成正比。
通过测出脉冲信号的频率(单位时间脉冲个数)就可以计算出电机的转速。
测量转速时,需要一个定时器,设定时间为T,还需要一个计数器,将霍尔传感器的(OUT端)输出脉冲引导计数器的输入端。
电机转动时,同时启动定时器和计数器,当定时器定时时间T到时,停止计数器的脉冲计数,并读出计数器的计数值S(即:时间T内的转数),可以计算出主流电机的转速R=S/T。
直流电机转速调整:首先确定控制脉冲占空比的调整方式,一种是设定正(或负)脉冲宽度,不断调整负脉(或正)冲宽度实现转速,当转速高于设定转速时,加大负脉冲(或减小正脉冲)的宽度。
另一种是同时调整正负脉冲的宽度实现直流电机转速调整。
在调整了脉冲占空比后,同时启动的定时器和计数器,进行转速测量,直流电机转速调整与测量交叉进行。
A.编制利用带锁存功能I/O端口(如8255,74LS273,D/A-DA0832)输出控制电机转速的PWM脉冲程序B. 编制利用定时器/计数器测量电机转速程序C.A)程序和B)程序合并,实现电机转速测量与控制D.编制系统监控界面的程序E.电机转速测量与闭环控制系统的连调。
五、课程设计试验环境:a)实验仪器●微机一台(Pentium 4)●微机接口技术实验箱一个●ISA – PCI转接卡一块●连接电缆一条●万用表一块●微机接口技术实验讲义一本●导线、剥线钳等b)软件环境:Windows XP 平台和Visual C++ 6.0 编译器六、实验主要代码// ReaderDlg.cpp : implementation file#include <windows.h>#include "stdafx.h"#include "Reader.h"#include "ReaderDlg.h"#include "PCI9052Dll.h" //总线转换#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endifint iospeed; //设置转速int rate; //实际转速int times = 0; //运行时间double key = 1.0; //占空比int normal = 0; //异常判断int stop = 0;/////////////////////////////////////////////////////////////////////////////// CReaderDlg dialogCReaderDlg::CReaderDlg(CWnd* pParent /*=NULL*/): CDialog(CReaderDlg::IDD, pParent){//{{AFX_DATA_INIT(CReaderDlg)m_edit6 = _T("");m_edit4 = _T("");m_edit5 = _T("");m_speed = 0;m_edit3 = _T("");//}}AFX_DATA_INIT// Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);}void CReaderDlg::DoDataExchange(CDataExchange* pDX){CDialog::DoDataExchange(pDX);//{{AFX_DATA_MAP(CReaderDlg)DDX_Text(pDX, IDC_EDIT6, m_edit6);DDX_Text(pDX, IDC_EDIT4, m_edit4);DDX_Text(pDX, IDC_EDIT5, m_edit5);DDX_Text(pDX, IDC_EDIT1, m_speed);DDV_MinMaxInt(pDX, m_speed, 0, 2500);DDX_Text(pDX, IDC_EDIT3, m_edit3);//}}AFX_DATA_MAP}BEGIN_MESSAGE_MAP(CReaderDlg, CDialog)//{{AFX_MSG_MAP(CReaderDlg)ON_WM_PAINT()ON_WM_QUERYDRAGICON()ON_BN_CLICKED(IDC_BUTTON1, OnButton1)ON_EN_CHANGE(IDC_EDIT1, OnChangeEdit1)ON_BN_CLICKED(IDC_BUTTON2, OnButton2)ON_BN_CLICKED(IDC_BUTTON3, OnButton3)ON_EN_CHANGE(IDC_EDIT3, OnChangeEdit3)ON_EN_CHANGE(IDC_EDIT6, OnChangeEdit6)ON_EN_CHANGE(IDC_EDIT4, OnChangeEdit4)ON_EN_CHANGE(IDC_EDIT5, OnChangeEdit5)//}}AFX_MSG_MAPEND_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////// CReaderDlg message handlersBOOL CReaderDlg::OnInitDialog(){CDialog::OnInitDialog();// Set the icon for this dialog. The framework does this automatically// when the application's main window is not a dialogSetIcon(m_hIcon, TRUE); // Set big iconSetIcon(m_hIcon, FALSE); // Set small icon// TODO: Add extra initialization herereturn TRUE; // return TRUE unless you set the focus to a control}// If you add a minimize button to your dialog, you will need the code below// to draw the icon. For MFC applications using the document/view model,// this is automatically done for you by the framework.void CReaderDlg::OnPaint(){if (IsIconic()){CPaintDC dc(this); // device context for paintingSendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);// Center icon in client rectangleint cxIcon = GetSystemMetrics(SM_CXICON);int cyIcon = GetSystemMetrics(SM_CYICON);CRect rect;GetClientRect(&rect);int x = (rect.Width() - cxIcon + 1) / 2;int y = (rect.Height() - cyIcon + 1) / 2;// Draw the icondc.DrawIcon(x, y, m_hIcon);}else{CDialog::OnPaint();}}// The system calls this to obtain the cursor to display while the user drags // the minimized window.HCURSOR CReaderDlg::OnQueryDragIcon(){return (HCURSOR) m_hIcon;}void CReaderDlg::OnButton1() //启动按钮{// TODO: Add your control notification handler code here//初始化unsigned short iobase,addr;OpenDevice();GetIoBase(&iobase); //得到基地址addr=iobase+3; //8255控制字OutByte(addr,0x8a);addr = iobase + 11; //8253计数器0控制字OutByte(addr , 0x32);addr = iobase + 8; //计数器0初始化OutByte(addr,0x09);OutByte(addr,0x3d);addr = iobase +11 ; //8253计数器1、2控制字OutByte(addr,0x52);OutByte(addr,0xa0);addr = iobase + 9 ; //计数器1初始化OutByte(addr,100); //初始值为100addr = iobase + 10 ; //计数器2初始化OutByte(addr,0x01);addr = iobase +2; //PC口置1OutByte(addr,0xff);OutByte(iobase,0x01); //PA0置1,电机以最高速度转动//闭环调节系统char a11,a12; //辅助变量,调节占空比int num = 1; //用来判断是否计时到1秒unsigned char speed;unsigned char tt; //判断PB口状态,辅助计时while(stop == 0){Sleep(1);//转速if(num == 1){times++; //运行时间CReaderDlg::OnChangeEdit3(); //显示运行时间addr=iobase+9; //计时器1初始化OutByte(addr, 100);addr=iobase+2; //PC口控制计数器0、1的GATE,同步计数OutByte(addr, 0x00);OutByte(addr, 0xff);num = 0;}addr=iobase+1; //读PB状态,判断是否计时超过1秒InByte(addr,&tt);if(tt==1) //时间到,进入转速计算语句{addr=iobase+2; //PC口置零,GATE失效,停止计数OutByte(addr,0x00);addr=iobase+9; //读计数器1的计数值InByte(addr,&speed);if((int)speed<0) speed=0;rate = 60*(100-(int)speed); //转速计算CReaderDlg::OnChangeEdit6(); //显示转速num = 1;if(rate > iospeed && key >= 0.1) //修改占空比key = key-0.1;else if(rate < iospeed && key <= 0.9)key = key+0.1;CReaderDlg::OnChangeEdit4(); //显示占空比if(abs(rate-iospeed)/iospeed > 0.1) //判断正常/异常normal = 0; //异常elsenormal = 1; //正常}a11=(char)(100*key); //电机驱动脉冲高电平持续时间OutByte(iobase, 0x01);addr=iobase+10;OutByte(addr, 0);OutByte(addr, a11);unsigned char a;int b;while(1) //高电平倒计时{addr=iobase+2;InByte(addr,&a);b=(int)a;if((b & 0x10))break;}a12=(char)(100*(1-key)); //电机驱动脉冲低电平持续时间OutByte(iobase, 0x00);addr=iobase+10;OutByte(addr, 0);OutByte(addr, a12);while(1) //低电平倒计时{addr=iobase+2;InByte(addr,&a);b=(int)a;if((b & 0x10))break;}}//CloseDevice();}void CReaderDlg::OnChangeEdit1(){// TODO: If this is a RICHEDIT control, the control will not// send this notification unless you override the CDialog::OnInitDialog() // function and call CRichEditCtrl().SetEventMask()// with the ENM_CHANGE flag ORed into the mask.// TODO: Add your control notification handler code here}void CReaderDlg::OnButton2() //停止按钮{stop = 1;// TODO: Add your control notification handler code hereunsigned short iobase;OpenDevice();GetIoBase(&iobase);OutByte(iobase, 0x00); //置驱动脉冲无效MessageBox("电机已停止工作!");CloseDevice();}void CReaderDlg::OnChangeEdit2(){// TODO: If this is a RICHEDIT control, the control will not// send this notification unless you override the CDialog::OnInitDialog() // function and call CRichEditCtrl().SetEventMask()// with the ENM_CHANGE flag ORed into the mask.// TODO: Add your control notification handler code here}void CReaderDlg::OnButton3() //设置转速确认按钮{// TODO: Add your control notification handler code hereUpdateData();//m_speed.GetDlgItemInt(iospeed);iospeed = m_speed;}void CReaderDlg::OnChangeEdit3() //显示运行时间{// TODO: If this is a RICHEDIT control, the control will not// send this notification unless you override the CDialog::OnInitDialog() // function and call CRichEditCtrl().SetEventMask()// with the ENM_CHANGE flag ORed into the mask.// TODO: Add your control notification handler code hereCString temp;temp.Format("%d",times);m_edit3 = temp;//m_edit3=times;UpdateData(false);UpdateWindow();}void CReaderDlg::OnChangeEdit6() //显示实测转速{// TODO: If this is a RICHEDIT control, the control will not// send this notification unless you override the CDialog::OnInitDialog() // function and call CRichEditCtrl().SetEventMask()// with the ENM_CHANGE flag ORed into the mask.// TODO: Add your control notification handler code hereCString temp;temp.Format("%d",rate);m_edit6 = temp;UpdateData(false);UpdateWindow();}void CReaderDlg::OnChangeEdit4() //显示占空比{// TODO: If this is a RICHEDIT control, the control will not// send this notification unless you override the CDialog::OnInitDialog() // function and call CRichEditCtrl().SetEventMask()// with the ENM_CHANGE flag ORed into the mask.// TODO: Add your control notification handler code hereCString temp;temp.Format("%lf",key);m_edit4 = temp;UpdateData(false);UpdateWindow();}void CReaderDlg::OnChangeEdit5() //显示异常状况{// TODO: If this is a RICHEDIT control, the control will not// send this notification unless you override the CDialog::OnInitDialog() // function and call CRichEditCtrl().SetEventMask()// with the ENM_CHANGE flag ORed into the mask.// TODO: Add your control notification handler code hereCString temp;if(normal == 1)temp.Format("正常");elsetemp.Format("异常");m_edit4 = temp;UpdateData(false);UpdateWindow();}七、系统测试结果八、课程设计中遇到的问题及解决办法这次实验的课题相对于其他三个而言,难度比较大,做起来相对困难,由于实验器材的限制,我们两个组合成了一个组,一共十个人。