先说一下控制系统的构成,一个经典的控制系统是一个反馈控制系统,通常由一个被控对象,一个控制器,一个给定信号,还有传感器组成,通常给定信号要和传感器反馈过来的反馈信号进行比较得到误差作为控制器的输入,而控制器的输出用来控制被控对象,它是被控对象的输入。
而控制器又以 pid 控制器最为经典,一个 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执行一次了。由于一个控制系统的实现需要许多传感器和设备,因此无法给出具体的示例代码,希望我的文章对想做实时控制的朋友有所帮助。
|