搜索
bottom↓
回复: 26

增量式PID的程序和疑问

[复制链接]

出0入0汤圆

发表于 2014-1-3 11:07:13 | 显示全部楼层 |阅读模式
本帖最后由 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");
}






出0入0汤圆

 楼主| 发表于 2014-1-3 11:17:04 | 显示全部楼层

发个公式,以上程序,就是按照这个公式来写的,应该是没有违背公式的。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2014-1-3 14:30:55 | 显示全部楼层
没弄过PID,来学习

出0入296汤圆

发表于 2014-1-4 16:25:20 | 显示全部楼层
FuARM 发表于 2014-1-3 11:17
发个公式,以上程序,就是按照这个公式来写的,应该是没有违背公式的。 ...

先别管这些,先上实际系统,调试好电机驱动,旋转编码器以后再说如何转化理论公式的问题。
纸上谈兵对PID学习一点用都没有。

出0入0汤圆

 楼主| 发表于 2014-1-5 22:39:10 | 显示全部楼层
Gorgon_Meducer 发表于 2014-1-4 16:25
先别管这些,先上实际系统,调试好电机驱动,旋转编码器以后再说如何转化理论公式的问题。
纸上谈兵对PID ...

嗯,在实际板子上调试,电机速度基本调稳了,感觉效果还是很好的,速度比较稳定,施加一定的阻力给电机,速度也能稳定。
用的就是我发的这个代码的一个变形pPID->delta = pPID->Kp*((e0 - pPID->e_1)+pPID->Ki*e0+pPID->Kd*(e0-2* pPID->e_1+ pPID->e_2));
公式一样,只是把Kp,Ki,Kd分离出来调。
但是还是不明白,如果Ki=0,Kd=0;那么增量就是pPID->Kp*((e0 - pPID->e_1);电机堵转,或者速度被人为的限制死,那么前后两次的误差,应该就是相等的啊,于是增量岂不是0了?
我想应该是我的理解有问题。。。

出0入0汤圆

发表于 2014-1-5 23:12:45 来自手机 | 显示全部楼层
增量为零不代表输出为零。增量式PID的输出是所有以前的累加量,而不是当前的增量。

出15入190汤圆

发表于 2014-1-6 10:08:57 | 显示全部楼层
学习贴,准备自己尝试一下

出0入0汤圆

 楼主| 发表于 2014-1-6 10:23:09 | 显示全部楼层
chenbelief_007 发表于 2014-1-5 23:12
增量为零不代表输出为零。增量式PID的输出是所有以前的累加量,而不是当前的增量。 ...

嗯,增量式PID的输出是所有以前的累加量,这个是对的。
但是我说的前提是,此时的转速已经被外力限定了,因此前后两次的误差之差应该是等于0,那么PID的输出就不会变(Ki=0;Kd=0),
我的理解是,此时如果PID的输出没有达到最大的话,如果电机速度没有达到目标速度,那么PID控制器理应继续增大输出量试图提高转速才对。

出0入0汤圆

 楼主| 发表于 2014-1-6 10:35:17 | 显示全部楼层
谢谢。。。。。。。

出0入0汤圆

 楼主| 发表于 2014-1-6 10:36:16 | 显示全部楼层
chenbelief_007 发表于 2014-1-5 23:12
增量为零不代表输出为零。增量式PID的输出是所有以前的累加量,而不是当前的增量。 ...

这么举个例子吧,还是看Ki,Kd都为0的纯比例的增量式。

假如PID输出量在增加的过程中,使得电机力矩和阻力恰好平衡了,而这时候还没有达到输出量的最大值,转速也没有达到目标速度,
根据公式计算,增量为0,输出量不再增加。

我感觉不合理的地方是:此时既然没有达到目标速度,而且输出量也没有达到最大,那么对于一个理想的控制器而言,应该继续增大输出才对啊,应该“竭尽全力”。

我想我的理解一定是错在哪里。恳请帮忙。

出0入0汤圆

发表于 2014-1-6 14:38:00 | 显示全部楼层
这时需要积分项来达到你的效果,一旦存在误差,积分项会不断增大,这时的输出就会增加,直到当前误差为零。

出0入0汤圆

发表于 2014-1-6 14:40:48 | 显示全部楼层
不应该说是积分项在增大,应该说增量不为零,输出就可以一直增加。

出0入0汤圆

 楼主| 发表于 2014-2-11 09:32:22 | 显示全部楼层
chenbelief_007 发表于 2014-1-6 14:40
不应该说是积分项在增大,应该说增量不为零,输出就可以一直增加。

关键现在看来,增量是0呀

出0入12汤圆

发表于 2014-2-24 10:20:07 | 显示全部楼层
反馈啊  

出0入0汤圆

发表于 2014-3-29 07:54:32 | 显示全部楼层
正在准备自己弄一个~

出0入0汤圆

发表于 2014-5-23 14:38:09 | 显示全部楼层
楼主你好,先借你的程序用一下,呵呵 ,在写毕设。

不知这个问题后来你思考的结果如何?我空想了一下,你设定的前提条件有问题,因为系统不可能凭空由一种状态突变到你所说的恒定误差状态。哪怕真的是从误差0突变到误差X,那也是一种阶跃,比例环节必然要做出响应,类似于系统启动t=0的时刻。

除非你debug然后自己改变量数值

你觉得呢?

出0入0汤圆

 楼主| 发表于 2014-5-29 11:48:33 | 显示全部楼层
alexbird 发表于 2014-5-23 14:38
楼主你好,先借你的程序用一下,呵呵 ,在写毕设。

不知这个问题后来你思考的结果如何?我空想了一下,你 ...

我赶脚,也是这么个事儿。

出0入0汤圆

 楼主| 发表于 2014-5-29 11:48:59 | 显示全部楼层
alexbird 发表于 2014-5-23 14:38
楼主你好,先借你的程序用一下,呵呵 ,在写毕设。

不知这个问题后来你思考的结果如何?我空想了一下,你 ...

我赶脚,也是这么个事儿。

出0入0汤圆

 楼主| 发表于 2014-5-29 11:51:06 | 显示全部楼层
FuARM 发表于 2014-5-29 11:48
我赶脚,也是这么个事儿。

但是,如果测量环节突然出错了,出现我说的恒定误差呢?

出0入0汤圆

 楼主| 发表于 2014-5-29 11:51:28 | 显示全部楼层
alexbird 发表于 2014-5-23 14:38
楼主你好,先借你的程序用一下,呵呵 ,在写毕设。

不知这个问题后来你思考的结果如何?我空想了一下,你 ...

但是,如果测量环节突然出错了,出现我说的恒定误差呢?

出0入0汤圆

发表于 2014-5-30 09:47:19 | 显示全部楼层
FuARM 发表于 2014-5-29 11:51
但是,如果测量环节突然出错了,出现我说的恒定误差呢?

都出错了,还谈什么呢
位置式PID出错的话,输出是错误的绝对位置,机器就直接飞了,比你这错误的后果严重多了。。。

出0入0汤圆

发表于 2014-6-7 19:40:05 | 显示全部楼层
还在努力学习中

出0入0汤圆

发表于 2014-6-9 16:06:29 | 显示全部楼层
学习了!

出0入0汤圆

发表于 2014-8-4 18:40:01 | 显示全部楼层
FuARM 发表于 2014-1-5 22:39
嗯,在实际板子上调试,电机速度基本调稳了,感觉效果还是很好的,速度比较稳定,施加一定的阻力给电机, ...

楼主  感觉到了这个时候就变成类似位置式的"静态误差" 了   对PID也不怎么理解  来着里求解答~

出0入0汤圆

发表于 2014-8-26 10:22:27 | 显示全部楼层
最近也在学习这个,非常感谢楼主。

出0入0汤圆

发表于 2014-12-16 16:11:02 | 显示全部楼层
楼主还在否?也在想找个问题。
Kp_speed*(devk-devk_1)+Ki_speed*devk
纯Kp下如果2次误差相等,输出就为0啊。

出0入0汤圆

发表于 2015-3-6 10:06:12 | 显示全部楼层
我也遇到了楼主这种问题,电机在启动前检测转速为0,pwm输出为0,如果设定一个很小的目标值,这时如果纯比例环节的话Kp(e_0 - e_1) 很小不足以使电机转动,因此下一次计算时Kp(e_0 - e_1)变为0 ,  pwm输出不变,电机还是转不起来,以后电机永远转不起来了。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-29 01:36

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表