直流电机PID转速闭环调速控制系统.docx

上传人:b****3 文档编号:26976016 上传时间:2023-06-24 格式:DOCX 页数:33 大小:150.51KB
下载 相关 举报
直流电机PID转速闭环调速控制系统.docx_第1页
第1页 / 共33页
直流电机PID转速闭环调速控制系统.docx_第2页
第2页 / 共33页
直流电机PID转速闭环调速控制系统.docx_第3页
第3页 / 共33页
直流电机PID转速闭环调速控制系统.docx_第4页
第4页 / 共33页
直流电机PID转速闭环调速控制系统.docx_第5页
第5页 / 共33页
点击查看更多>>
下载资源
资源描述

直流电机PID转速闭环调速控制系统.docx

《直流电机PID转速闭环调速控制系统.docx》由会员分享,可在线阅读,更多相关《直流电机PID转速闭环调速控制系统.docx(33页珍藏版)》请在冰豆网上搜索。

直流电机PID转速闭环调速控制系统.docx

直流电机PID转速闭环调速控制系统

基于uC/COS的直流电机PID转速闭环调速控制系统Proteus仿真实现

在工业自动控制系统和各种智能产品中常常会用用电动机进行驱动、传动和控制,而现代智能控制系统中,对电机的控制要求越来越精确和迅速,对环境的适应要求越来越高。

随着科技的发展,通过对电机的改造,出现了一些针对各种应用要求的电机,如伺服电机、步进电机、开关磁阻电机等非传统电机。

但是在一些对位置控制要求不高的电机控制系统如传动控制系统中,传统电机如直流电机乃有很大的优势,而要对其进行精确而又迅速的控制,就需要复杂的控制系统。

随着微电子和计算机的发展,数字控制系统应用越来越广泛,数字控制系统有控制精确,硬件实现简单,受环境影响小,功能复杂,系统修改简单,有很好的人机交换界面等特点。

在电机控制系统开发中,常常需要消耗各种硬件资源,系统构建时间长,而在调试时很难对硬件系统进行修改,从而延长开发周期。

随着计算机仿真技术的出现和发展,可用计算机对电机控制系统进行仿真,从而减小系统开发开支和周期。

计算机仿真可分为整体仿真

和实时仿真。

整体仿真是对系统各个时间段对各个对象进行计算和分析,从而对各个对象的变化情况有直观的整体的了解,即能对系统进行精确的预测,如Matlab就是一个典型的实时仿真软件。

实时仿真是对时间点的动态仿真,即随着时间的推移它能动态仿真出当时系统的状态。

Proteus是一个实时仿真软件,用来仿真各种嵌入式系统。

它能对各种微控制器进行仿真,本系统即用Proteus对直流电机控制系统进行仿真。

在系统软件开发中开发中可用操作系统,也可不用操作系统。

如用操作系统,程序可实现模块化,并能对系统资源进行统筹管理,最主要的是可实现多任务运行。

如果需要多任务并行运行,并且需要一定的时间间隔,某些任务对时间的要求不高时,如不用操作系统则要占用定时器资源,并且对栈空间和硬件资源很难进行管理,所以在这种情况下需要操作系统。

本系统用操作系统uC/COS.

uC/COS是一个完整的、可移植、可固化、可剪裁的占先式实时多任务内核.uC/COS

已经有很多产品成功使用的案例且得到美国军方的认证,说明了该系统的可靠性。

uC/COS

源代码公开,代码短,源代码大部分是使用ANSIC编写的,移植性和裁减性好,功能强大,

能可靠应用于各种控制系统中。

   系统构成

 硬件全图

各子系统

1.转速控制输入

如用按键输入则需要复杂的软件实现,并且需要足够的引脚资源,本系统用ADC0832采样电位器上的电压信号来实现转速信号输入。

2.LPC2106微控制器

LPC2106是Phlip公司推出的核心为ARM的控制器。

LPC2106包含一个支持仿真的ARM7TDMI-SCPU、与片内存储器控制器接口的ARM7局部总线、与中断控制器接口的AMBA高性能总线(AHB)和连接片内外设功能的VLSI外设总线(VPB,ARMAMBA总线的兼容超集)。

片内有64K字节静态RAM和128K的FLASH存储器。

可寻址4GB。

在本仿真中LPC2106没加晶振电路,频率在芯片属性中设置。

3.液晶显示

本系统采用Proteus仿真库有的液晶显示模块AMPIRE128X64,为8192像素的单色LCD

屏幕分为两半控制,控制引脚为CS1和CS2。

数据通过移位寄存器输入。

 

4.电机驱动电路

本系统仿真的是最大输入电压为12伏的微型电机,故用通用电机驱动电路实现假设该电路输入电阻为无穷大,输出电阻为0。

5.仿真电机的51单片机

虽然Proteus有电机模块,但其电机模块没有输出转速接口故用一单片机代替它,单片机用ADC0832采样输入的电压,经过处理即输出和真实电机同步的转速(需要大量的浮点运算,可考虑用DSP)。

通过两个按键改变转矩没按一次增大或减小0.001,上面的是增大。

6.仿真结果

仿真1.8秒钟后得下图,可看到转速逐渐增大然后稳定下来。

增大转矩后,可看到转速下降后又恢复

 

7.程序;

1.系统主程序:

main.c

/******************************************************************************

**实时微型直流电机PID转速闭环调速控制系统程序(基于移植于LPC2106上的uc/cos实时操作系统)

**程序编写者:

吴斌

**编写日期:

2007年11月14日

******************************************************************************/

#include"config.h"

#include"LCD.h"

#defineTASK_STK_SIZE512//各任务栈大小

#defineIO_Init()\

PINSEL0=2;\

IODIR|=0x00007FB0;//P0.4\P0.5\P0.7-P1.4为输出其他的为输入

#defineUmax1000//最大调节转速

#defineKp0.7//比例放大系数

#defineTs0.03//采样周期

#definet04//积分时间常数

#definetd0.0005//微分时间常数

#defineq0Kp*(1+Ts*t0+td/Ts)

#defineq1-Kp*(1+2*td/Ts)

#defineq2Kp*td/Ts

#defineADC_DO0x00000040//P0.6

#defineADC_CS0x00000080//P0.7

#defineADC_CLK0x00000100//P0.8

#defineADC_DI0x00000200//P0.9

OS_STKMain_TaskStk[TASK_STK_SIZE];

OS_STKTask1_TaskStk[TASK_STK_SIZE];

OS_STKTask2_TaskStk[TASK_STK_SIZE];

OS_STKTask3_TaskStk[TASK_STK_SIZE];

OS_STKTask4_TaskStk[TASK_STK_SIZE];//各任务栈

OS_EVENT*Conbox;//控制信号邮箱

floatn=0;//输入转速

floatnb=0;//反馈转速

voidMain_Task(void*data);

voidTask1(void*p_arg);

voidTask2(void*p_arg);

voidTask3(void*p_arg);

voidTask4(void*p_arg);//函数声明

voidPWMInit(void)

{

PWMPR=0x00;//不分频,计数频率为Fpclk

PWMMCR=0x02;//设置PWMMR0匹配时复位PWMTC

PWMMR0=2765;//设置PWM周期

PWMMR1=0;//设置PWM占空比

PWMLER=0x03;//PWMMR0、PWMMR1锁存

PWMPCR=0x0200;//允许PWM1输出,单边PWM

PWMTCR=0x09;//启动定时器,PWM使能

PWMMR0=2765;//设置PWM周期

PWMMR1=0;//设置PWM占空比

PWMLER=0x03;//PWMMR0、PWMMR1锁存

}

/*********************************************************************************************************

**函数名称:

main

**功能描述:

c语言的主函数,由它启动多任务环境

********************************************************************************************************/

intmain(void)

{

OSInit();

OSTaskCreate(Main_Task,(void*)0,&Main_TaskStk[TASK_STK_SIZE-1],0);

OSStart();

return0;

}

/******************************************************************************

**函数名称:

Main_Task

**功能描述:

初始化系统及建立任务

******************************************************************************/

voidMain_Task(void*p_arg)

{

p_arg=p_arg;//避免编译警告

TargetInit();

IO_Init();

Conbox=OSMboxCreate((void*)0);

LCD_Main();

OSTaskCreate(Task1,(void*)0,&Task1_TaskStk[TASK_STK_SIZE-1],2);

OSTaskCreate(Task2,(void*)0,&Task2_TaskStk[TASK_STK_SIZE-1],3);

OSTaskCreate(Task3,(void*)0,&Task3_TaskStk[TASK_STK_SIZE-1],1);

OSTaskCreate(Task4,(void*)0,&Task4_TaskStk[TASK_STK_SIZE-1],5);

OSTaskSuspend(0);

}

/******************************************************************************

**函数名称:

Task1_Task

**功能描述:

实时任务,负责采样和处理数据

******************************************************************************/

voidTask1(void*p_arg)

{floatus;//上次输出控制信号

floates;//上次采样误差信号

floates2=0;//上次的上次的采样误差信号

uint32nj;//采样转速信号

floatu;//此次输出控制信号

floate;//此次采样误差信号

p_arg=p_arg;

PWMInit();//PWM初始化

while

(1)

{nj=IOPIN>>16;

nb=(float)nj/10;//采样反馈转速

e=n-nb;

u=us+q0*e+q1*es+q2*es2;//PID处理

if(u>=Umax)

u=Umax;

es2=es;

es=e;

us=u;

OSMboxPost(Conbox,(void*)&u);//发送处理后的信号

OSTimeDlyHMSM(0,0,0,30);

}

}

/******************************************************************************

**函数名称:

Task2_Task

**功能描述:

根据控制信号输出PWM波

******************************************************************************/

voidTask2(void*p_arg)

{uint8err;

float*nh;

p_arg=p_arg;

while

(1)

{nh=(float*)OSMboxPend(Conbox,0,&err);

if(*nh>=Umax-0.5)

{PWMMR0=2765;

PWMMR1=2764;

PWMLER=0x03;

}

else

{PWMMR0=2765;

PWMMR1=(uint32)(*nh/Umax*2765);

PWMLER=0x03;

}

}

}

voidDelay(uint8n)//延时函数

{uint8i;

for(i=1;i<=n;i++);

}

/******************************************************************************

**函数名称:

Task3_Task

**功能描述:

定时采样输入的转速要求(0832采样)

******************************************************************************/

voidTask3(void*p_arg)

{uint8ch,i,flag=0;

p_arg=p_arg;

ch=0;

IOCLR=ADC_CS;

IOCLR=ADC_DI;//片选,DO为高阻态

for(i=0;i<10;i++)

{;}

IOCLR=ADC_CLK;

Delay(4);

IOSET=ADC_DI;

IOSET=ADC_CLK;

Delay(4);//第一个脉冲,起始位

IOCLR=ADC_CLK;

Delay(4);

IOSET=ADC_DI;

IOSET=ADC_CLK;

Delay(4);//第二个脉冲,DI=1表示双通道单极性输入

IOCLR=ADC_CLK;

Delay(4);

IOSET=ADC_DI;

IOSET=ADC_CLK;

Delay(4);//第三个脉冲,DI=1表示选择通道1(CH2)

IOCLR=ADC_DI;//DI转为高阻态,DO脱离高阻态为输出数据作准备

IOSET=ADC_CLK;

Delay(4);

IOCLR=ADC_CLK;

Delay(4);//经实验,这里加一个脉冲AD便能正确读出数据

for(i=0;i<8;i++)

{IOSET=ADC_CLK;

Delay(4);

IOCLR=ADC_CLK;

Delay(4);

if((IOPIN&ADC_DO)!

=0)

ch=(ch<<1)|1;//在每个脉冲的下降沿DO输出一位数据,最终ch为8位二进制数

else

ch=(ch<<1)|0;

}

IOSET=ADC_CS;

n=(float)ch*1000/256;

if(flag==0)

{flag=1;

OSTaskChangePrio(1,4);

}

OSTimeDlyHMSM(0,0,0,300);

}

/******************************************************************************

**函数名称:

Task4_Task

**功能描述:

液晶显示任务

******************************************************************************/

voidTask4(void*p_arg)

{

#ifOSCRITICAL_METHOD==3

OS_CPU_SRcpu_sr;

#endif

uint16w,q,k;

uint8i;

uint8shu1[6],shu2[6];

p_arg=p_arg;

for(;;)

{shu1[4]=10;

w=(uint16)(n*10);

k=10000;

for(i=0;i<4;i++)

{shu1[i]=(uint8)(w/k);

w=w%k;

k=k/10;

}

shu1[5]=(uint8)w;

OS_ENTER_CRITICAL();

LCD_num(80,2,shu1,6);

shu2[4]=10;

q=(uint16)(nb*10);

k=10000;

for(i=0;i<4;i++)

{shu2[i]=(uint8)(q/k);

q=q%k;

k=k/10;

}

shu2[5]=(uint8)q;

LCD_num(80,4,shu2,6);

OS_EXIT_CRITICAL();

OSTimeDlyHMSM(0,0,0,100);

}

}

/******************************************************************************

**EndOfFile

******************************************************************************/

2.自编的LCD驱动程序

(1)头文件LCD.h

/******************************************************************************

**LCD驱动头文件LCD.h(基于LPC21**)

**程序编写者:

吴斌

**编写日期:

2007年11月12日

******************************************************************************/

#ifndef_LCD_H_

#define_LCD_H_

#include"config.h"

#defineSPI_CLK0x00000010//P0.4

#defineSPI_DATA0x00000020//P0.5

#defineRW0x00000800//RW

#defineRS0x00000400//RS

#defineCS10x00001000//CS1

#defineCS20x00002000//CS2

#defineE0x00004000//E

#defineKai0x3F

#defineGuang0x3E

#defineHang0xC0

#defineYe0xB8

#defineLie0x40

#defineSetlie(a)\

IOCLR=RW;\

IOCLR=RS;\

send(Lie+a);

#defineSetye(a)\

IOCLR=RW;\

IOCLR=RS;\

send(Ye+a);

#defineSetweizi(a,b)\

IOCLR=RW;\

IOCLR=RS;\

send(Lie+a);\

send(Ye+b);

#defineWrite(a)\

IOCLR=RW;\

IOSET=RS;\

send(a);

voidsend(uint8dat);

voidLCD_disp(uint8a,uint8b,uint8c,uint8d,uint8m,uint8*shuju);

voidSetCS(uint8a);

voidLCD(uint8a,uint8b,uint8c,uint8d,uint8*shuju);

voidLCD_num(uint8a,uint8b,uint8*shuju,uint8n);

voidLCD_str(uint8a,uint8b,uint8*strtab,uint8n);

voidLCD_hanzi(uint8a,uint8b,uint8*hanzitab,uint8n);

voidLCD_xian(uint8a,uint8b,uint8*strtab,uint8n);

voidLCD_Main(void);

#endif

/******************************************************************************

**EndOfFile

******************************************************************************/

(2)LCD驱动程序LCD.c

/******************************************************************************

**LCD驱动程序(基于LPC21**)

**程序编写者:

吴斌

**编写日期:

2007年11月12日

******************************************************************************/

#include"LCD.h"

voidsend(uint8dat)//用移位寄存器输出一字节数据

{uint8i;

IOSET=E;//E=1

for(i=0;i<8;i++)//发送8位数据

{IOCLR=SPI_CLK;//SPI_CLK=0

if((dat&0x80)!

=0)IOSET=SPI_DATA;

elseIOCLR=SPI_DATA;

dat<<=1;

IOSET=SPI_CLK;//SPI_CLK=1

}

IOCLR=E;//E=0

}

voidLCD_disp(uint8a,uint8b,uint8c,uint8d,uint8m,uint8*shuju)/*LCD显示函数,在第a列b页输出大小为c*d的图像(只能选择在左或右屏幕显示)*/

{uint8i,j,f;

SetCS(m);

for(j=0;j

{Setweizi(a,j+b);

for(i=0;i

{Write(*(shuju+i));

for(f=0;f<0xFF;f++);

}

}

}

void

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 交通运输

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1