Chinaunix首页 | 论坛 | 博客
  • 博客访问: 116396
  • 博文数量: 43
  • 博客积分: 2500
  • 博客等级: 少校
  • 技术积分: 530
  • 用 户 组: 普通用户
  • 注册时间: 2008-09-04 16:56
文章分类

全部博文(43)

文章存档

2011年(1)

2010年(2)

2008年(40)

我的朋友

分类: C/C++

2008-10-16 16:52:38

从早上折腾到现在,中午吃了个饭接着做到现在,终于有点点心得:
耐心+信心+决心=收获
我要加油,以后要接着做得更好,更成功。
MMRESULT timeSetEvent( UINT uDelay,
                                 UINT uResolution,
                                 LPTIMECALLBACK lpTimeProc,
                                 WORD dwUser,
                                 UINT fuEvent )

        uDelay:以毫秒指定事件的周期。
         Uresolution:以毫秒指定延时的精度,数值越小定时器事件分辨率越高。缺省值为1ms。
         LpTimeProc:指向一个回调函数。
         DwUser:存放用户提供的回调数据。
         FuEvent:指定定时器事件类型:
         TIME_ONESHOT:uDelay毫秒后只产生一次事件
         TIME_PERIODIC :每隔uDelay毫秒周期性地产生事件。
 
在使用过程要注意几点:
在初始化过程中有添加函数   
UINT nID= ::timeSetEvent (1000, 5,CallBackFunc,(DWORD)this,TIME_PERIODIC); 
其中函数的应用必须加入头文件:#include "mmsystem.h"
                         #pragma comment(lib, "winmm.lib")
设置调用函数:
void PASCAL CallBackFunc(UINT wTimerID, UINT msg,DWORD dwUser,DWORD dwl,DWORD dw2)
{
//printf("11111111111\n");
//exit(0);
//在此处调用你要编写的函数
 
 
一个pid实例

简单PID数字控制的VC程序实现

作者:
南京航空航天大学

对于学控制的人都知道, Matlab 在全数字仿真领域占尽了风头,不但功能强大,其 simulink 工具使用图形的方式既直观又方便,但是它在实际的数字控制中却无能为力,因为它运算速度太慢,做一次 for 循环所用的时间是 c 语言的好多倍,而 VC++ 在效率方面很有优势,因为他使用可以是 c 语言,它和 windows 操作系统很接近,许多 API 函数都是以 c 语言的形式提供的,因为它与操作系统很好的结合,所以其效率和实时性都比较高。

下面要说一下控制系统的构成,一个经典的控制系统是一个反馈控制系统,通常由一个被控对象,一个控制器,一个给定信号,还有传感器组成,通常给定信号要和传感器反馈过来的反馈信号进行比较得到误差作为控制器的输入,而控制器的输出用来控制被控对象,它是被控对象的输入。下面是它的结构简图:



图 1 一个控制系统的结构简图

而控制器又以 pid 控制器最为经典,一个 pid 控制器的结构图如下:

图 2 一个 pid 控制器的结构

误差信号 = 给定信号 - 反馈信号(对于一个负反馈的系统)

通常给定信号为系统自己产生的,可以是一个常值,或者是正弦等,通常可以用一个函数来获取给定信号, double GetDemandSignal();

反馈信号通常上通过数据采集器采集到的数字信号,然后通过一个比例把它换算成实际对应的数值,同理,可以定义一个函数来获取反馈信号, double GetFeedbackSignal(); 这两个函数具体实现根据系统不同而不同,这里不再给出其实现代码了。

下面主要讲下 PID 控制的数字算法的伪代码

const double dTimeInterval =0.001;//采样间隔为0.001秒
//PID参数,实际使用时根据系统调试
double Kp =2.5;
double Ki =5.0;
double Kd = 1.2;
void CALLBACK PIDControl(UINT uID,UINT uMsg,DWORD dwUser,DWORD dw1,DWORD dw2)
{
static double dValue[3];
	static double dOldError;
	double dOutSignal;		//PID控制的输出
	double dError;
	double dDemandSignal = GetDemandSignal();
double dFeedbackSignal = GetFeedbackSignal();
dError = dDemandSignal – dFeedbackSignal;
dValue[0]=Kp* dError;比例
dValue[1]= dValue[1]+Ki* dError*dTimeInterval;//积分
dValue[2]=Kd * (dError-dOldError)/ dTimeInterval;//微分
dOutSignal = dValue[0]+ dValue[1]+ dValue[2];
SendControlSignal(dOutSignal);//这个函数是把控制量输出到D/A,然后传送到以后的环节进行控制
}
以上的代码是一个定时中断处理函数,每1ms执行一次控制,因此必须要有一个定时器来控制上面所写的代码的执行,定时间隔不同,dTimeInterval也不同。对于windows系统,可以用timeSetEvent()函数来注册一个定时中断处理函数,最小的定时间隔可以达到1ms,在一般的控制系统中能满足要求。
具体方法为gl_uTimerID = ::timeSetEvent(1,1, PIDControl,0,TIME_PERIODIC); 然后PIDControl这个函数就会每1ms执行一次了。由于一个控制系统的实现需要许多传感器和设备,因此无法给出具体的示例代码,希望我的文章对想做实时控制的朋友有所帮助。
阅读(18477) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~