|
本帖最后由 FuARM 于 2014-1-3 11:07 编辑
这是本人按照公式写的一个增量式PID的程序,和测试程序,不知正确与否,恳请懂的人指出错误和建议。
想用在小车直流电机的控制上来,直流电机上有挡光片测速。MCU PWM调节转速。
按照推荐的调节PID的步骤,先将Ki=Kp*T/Ti置位0,将Kd=Kp*Td/T=0,当作纯比例控制器来调节,
因此让Ti=10000000.0(足够大就行,让Ki接近0),Td=0。此时A=Kp,B=-Kp;C=0;
增量计算(根据后面的程序改的伪代码):
e_0 = Set - Get;//目标值-本次测量值
delta = A*e_0 + B*e_1 + C*e_2 = Kp(e_0 - e_1) ;
e_2 = e_1;
e_1 = e_0;
out += delta;
那么,按照以上推导,在纯比例控制中,增量=Kp*(前两次误差的差值);
我的疑问是:
假设目标值是100,初始状态e_0=0,e_1=0;
时刻1测量值是10,那么误差就是90,e_0=90,e_1=0;那么delta增量会有一个值,同时实际输出量out也有一个值
如果时刻2测量值还是10,那么e_0=90,e_1=90; Kp(e_0 - e_1) =0;delta增量=0,此时out不增加。
试想,当输出量out还不足以驱动电机或者电机被负载堵转时,误差恒定不变,但是delta却等于0,输出out不变,电机也不会增加力矩,这似乎有悖我们控制电机转速的初衷。
以上是我的理解,不知道正确么,恳请大家指导。
/************************************************************************/
#include <math.h>
#define Kp (1.0) //PID调节的比例常数
#define Ti (10000000.0) //PID调节的积分常数
#define Td (0.0) //PID调节的微分时间常数
#define T (0.1) //采样周期
#define AA (Kp * (1 + (T / Ti) + (Td / T))) //A
#define BB ((-Kp) * (1+(2 * Td / T))) //B
#define CC (Kp * Td / T) //C
//误差的阀值,小于这个数值的时候,不做PID调整,避免误差较小时频繁调节引起震荡
#define Emin 3
//调整值限幅,防止积分饱和
#define Umax 20
#define Umin -20
//输出值限幅
#define Pmax 245
#define Pmin 0
typedef struct PID
{
int Set; //目标值
int Get; //当前测量值
int e_1;
int e_2;
double A;
double B;
double C;
int delta;
int out;
}PID_t;
void pid_init(PID_t * pPID);
void pid_ctrl(PID_t * pPID);
void pid_init(PID_t * pPID)
{
pPID->Set = 0;
pPID->Get = 0;
pPID->e_1 = 0;
pPID->e_2 = 0;
pPID->delta = 0;
pPID->out = 0;
pPID->A=AA;
pPID->B=BB;
pPID->C=CC;
}
void pid_ctrl(PID_t * pPID)
{
int e_0 = pPID->Set - pPID->Get;//求差值
pPID->delta = (int)(pPID->A*e_0 + pPID->B*pPID->e_1 + pPID->C*pPID->e_2);
pPID->e_2 = pPID->e_1;
pPID->e_1 = e_0;
pPID->out += pPID->delta;
}
PID_t PID_A;
void main(void)
{
int i;
pid_init(&PID_A);
printf("Kp=%f,Ki=%f,Kd=%f\n",Kp,(Kp*T/Ti),(Kp*Td/T));
printf("A=%f,B=%f,C=%f\n\n",AA,BB,CC);
printf("input the set val\n");
scanf("%d",&PID_A.Set);
printf("Set=%d\n",PID_A.Set);
while(1){
scanf("%d",&PID_A.Get);
pid_ctrl(&PID_A);
printf("get=%8d\n",PID_A.Get);
printf("delta=%8d, out=%8d\n",PID_A.delta,PID_A.out);
printf("e_1 =%8d, e_2=%8d\n",PID_A.e_1,PID_A.e_2);
}
printf("leave");
}
|
阿莫论坛20周年了!感谢大家的支持与爱护!!
你熬了10碗粥,别人一桶水倒进去,淘走90碗,剩下10碗给你,你看似没亏,其实你那10碗已经没有之前的裹腹了,人家的一桶水换90碗,继续卖。说白了,通货膨胀就是,你的钱是挣来的,他的钱是印来的,掺和在一起,你的钱就贬值了。
|