OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 8332|回复: 24

懂PID的大神指导下,不要不想就说。

[复制链接]

11

主题

43

帖子

0

精华

初级会员

Rank: 2

积分
107
金钱
107
注册时间
2013-8-3
在线时间
0 小时
发表于 2014-4-28 11:38:03 | 显示全部楼层 |阅读模式
刚刚学习PID,知道有两种PID  增量式和位置式, 
这是原子推荐看的一个pdf里面的一段代码。


int IncPIDCalc(int NextPoint)
{
register int iError, iIncpid;
//当前误差
iError = sptr->SetPoint - NextPoint;
//增量计算
iIncpid = sptr->roportion * iError //E[k]项
- sptr->Integral * sptr->LastError //E[k-1]项
+ sptr->Derivative * sptr->revError; //E[k-2]项
//存储误差,用于下次计算
sptr->revError = sptr->LastError;
sptr->LastError = iError;
//返回增量值
return(iIncpid);
}
我想问的是,  WM_OUT+= IncPIDCalc(Now_speed)
                    WM_OUT=IncPIDCalc(Now_speed)
这两句的PWM_OUT 一个是当前的控制增量,一个是累加的控制增量,我找了好多资料和程序,写法就这两种,问问大神们,给我讲下区别,主要是控制直流电机的速度!

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

120

主题

7878

帖子

13

精华

资深版主

Rank: 8Rank: 8

积分
12012
金钱
12012
注册时间
2013-9-10
在线时间
427 小时
发表于 2014-4-28 12:54:17 | 显示全部楼层
现在,程序把烂铜烂铁变得智能化了,人呢,一旦离开了这烂铜烂铁就不知道干啥了
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
22
金钱
22
注册时间
2014-2-15
在线时间
0 小时
发表于 2014-4-28 15:47:07 | 显示全部楼层
我也是刚学计算机控制系统。IncPIDCalc(Now_speed)为增量式PID算法,相当于△u(k),PWM_OUT+= IncPIDCalc(Now_speed)是要转化为位置PID,即u(k)=u(k-1)+△u(k).不知你是否满意
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手上路

积分
23
金钱
23
注册时间
2013-11-8
在线时间
0 小时
发表于 2014-4-28 16:27:49 | 显示全部楼层
我对PID略懂,对于第一个PWM_OUT+= IncPIDCalc(Now_speed);这个是增量式的,什么意思呢,比方说你控制直流电机额定转速1500r/min,当前电流是40A转速是2000r/min,你需要把电流减小经过IncPIDCalc()计算后,计算出来的值可正可负,与原来的PWM_OUT相加,也就是在原有PWM_OUT基础上是提高还是减少以把速度减少至1500r/min;第二个PWM_OUT=IncPIDCalc(Now_speed);这个就是位置式的,就是没有基础每次的PWM_OUT基础都是0,用PID运算,算出当前的电流或者脉冲的宽度,输出给电机.
回复 支持 反对

使用道具 举报

2

主题

1447

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
2258
金钱
2258
注册时间
2010-12-16
在线时间
206 小时
发表于 2014-4-28 18:36:41 | 显示全部楼层
又是一个被所谓增量PID荼毒的人.

所谓增量PID,虽然只是经典PID求个导数,但连求导数的物理意义都搞不懂的情况下,想搞懂求导结果的物理意义,根本是扯淡.
技术讨论请发帖 , 需要我回复请点左下的 < 回复 > 让系统通知我 . 本人不通过其他方式返回任何参数.
回复 支持 反对

使用道具 举报

11

主题

43

帖子

0

精华

初级会员

Rank: 2

积分
107
金钱
107
注册时间
2013-8-3
在线时间
0 小时
 楼主| 发表于 2014-4-28 20:12:56 | 显示全部楼层
回复【5楼】shihantu:
---------------------------------
大神,求解释啊,新手不懂啊
回复 支持 反对

使用道具 举报

11

主题

43

帖子

0

精华

初级会员

Rank: 2

积分
107
金钱
107
注册时间
2013-8-3
在线时间
0 小时
 楼主| 发表于 2014-4-28 20:14:49 | 显示全部楼层
回复【4楼】zhujie:
---------------------------------
和2楼说的刚好相反。不过貌似懂了点!!
回复 支持 反对

使用道具 举报

11

主题

43

帖子

0

精华

初级会员

Rank: 2

积分
107
金钱
107
注册时间
2013-8-3
在线时间
0 小时
 楼主| 发表于 2014-4-28 20:15:17 | 显示全部楼层
回复【3楼】舟田鱼:
---------------------------------
你看下3楼讲的,觉得你说的和他相反!!
回复 支持 反对

使用道具 举报

2

主题

1447

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
2258
金钱
2258
注册时间
2010-12-16
在线时间
206 小时
发表于 2014-4-28 21:12:17 | 显示全部楼层
懂微分不?看过自动控制的书没?都没有的话,就不要纠结这个问题,老老实实用标准的PID,不要想什么变种有什么意义,就像回字有几种写法一样,怎么写对实际使用区别不大.

真懂的人不要吐槽最后一句话,面向新手解释多了有碍理解.说运算效率的就算了,真正需要运算效率的场合就不是这么用了.
技术讨论请发帖 , 需要我回复请点左下的 < 回复 > 让系统通知我 . 本人不通过其他方式返回任何参数.
回复 支持 反对

使用道具 举报

2

主题

1447

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
2258
金钱
2258
注册时间
2010-12-16
在线时间
206 小时
发表于 2014-4-28 21:17:49 | 显示全部楼层
先说好,没有完全理解标准的PID就不要用所谓的增量PID调试,保证要多惨就能死多惨.
技术讨论请发帖 , 需要我回复请点左下的 < 回复 > 让系统通知我 . 本人不通过其他方式返回任何参数.
回复 支持 反对

使用道具 举报

11

主题

43

帖子

0

精华

初级会员

Rank: 2

积分
107
金钱
107
注册时间
2013-8-3
在线时间
0 小时
 楼主| 发表于 2014-4-28 23:12:27 | 显示全部楼层
回复【10楼】shihantu:
---------------------------------
都是眼泪啊,好把 我找本自动控制的书看看把!!!
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
22
金钱
22
注册时间
2014-2-15
在线时间
0 小时
发表于 2014-4-28 23:23:37 | 显示全部楼层
回复【8楼】西域大盘鸡:
---------------------------------
PWM_OUT+= IncPIDCalc(Now_speed),应该是位置式PID通过增量式PID推出的递推计算公式u(k)=u(k-1)+△u(k),△u(k)=q0*e(k)+q1*e(k-1)+q2*e(k-2)。         而PWM_OUT=IncPIDCalc(Now_speed),当执行机构需要的不是控制量的绝对值,而是控制量的增量(例如去驱动步进电动机)时,要用PID的“增量算法”即给执行机构的是△u(k)而不是u(k).不知是否合理
回复 支持 反对

使用道具 举报

9

主题

48

帖子

0

精华

初级会员

Rank: 2

积分
105
金钱
105
注册时间
2014-3-15
在线时间
0 小时
发表于 2014-5-13 21:46:05 | 显示全部楼层
你能把你的采集编码器脉冲的频率的程序发一份给我吗?或者整个程序,我也在和你做一样的事儿,遇到样的问题啊,PID控制直流电机QQ1106256891
回复 支持 反对

使用道具 举报

11

主题

43

帖子

0

精华

初级会员

Rank: 2

积分
107
金钱
107
注册时间
2013-8-3
在线时间
0 小时
 楼主| 发表于 2014-5-14 00:03:00 | 显示全部楼层
#include "motor.h"//电机
// #include "encoder.h"
#include "oled.h"
int Trans =0;
extern u16 engineLoc[2],engineLocDst[2];
extern s16 engineLocErr[2][3];
extern s32 enginePidOp[2],engingSpd[2];
double engineKp=0,engineKi=85,engineKd=0;//12 0.72 0.08

void EngineTim4Init(u16 arr,u16 psc)
{
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
TIM_OCInitTypeDef  TIM_OCInitStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4| RCC_APB2Periph_AFIO, ENABLE); //时钟使能

TIM_TimeBaseStructure.TIM_Period = arr-1; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值  计数到5000为500ms
TIM_TimeBaseStructure.TIM_Prescaler =psc-1; //设置用来作为TIMx时钟频率除数的预分频值  10Khz的计数频率  
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性:TIM输出比较极性高
TIM_OC2Init(TIM4, &TIM_OCInitStructure);//根据T指定的参数初始化外设TIM3 OC2
  TIM_OC1Init(TIM4, &TIM_OCInitStructure);//根据T指定的参数初始化外设TIM3 OC2

TIM_OC2PreloadConfig(TIM4, TIM_OCPreload_Enable);  //使能TIM4在CCR2上的预装载寄存器
TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable);
TIM_Cmd(TIM4, ENABLE);  //使能TIM4
}

void EngineIoInit(void)
{
GPIO_InitTypeDef  GPIO_InitStructure;
 
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOA,ENABLE);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9;//电机1方向  
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
  GPIO_Init(GPIOB, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;//PWM两路输出 注意需要设置复用输出类型
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;//电机2方向
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 
GPIO_Init(GPIOA, &GPIO_InitStructure);
}

void Engine1SpeedSet(s32 velo1)
{
if(velo1>0)
{
ENGINE1_DIR1=1;
ENGINE1_DIR2=0;
if(velo1<ENGINE_MAX_SPD) TIM_SetCompare2(TIM4,velo1);
else TIM_SetCompare2(TIM4,ENGINE_MAX_SPD);
}
else if(velo1><0)
{
ENGINE1_DIR1=0;
ENGINE1_DIR2=1;
if(velo1>(-ENGINE_MAX_SPD)) TIM_SetCompare2(TIM4,(Trans-velo1));
else TIM_SetCompare2(TIM4,ENGINE_MAX_SPD);
}
else
{
ENGINE1_DIR1=0;
ENGINE1_DIR2=0;
TIM_SetCompare2(TIM4,0);
}
}
void Engine2SpeedSet(s32 velo2)
{
if(velo2>0)
{
ENGINE2_DIR1=1;
ENGINE2_DIR2=0;
if(velo2<ENGINE_MAX_SPD) TIM_SetCompare1(TIM4,velo2);
else TIM_SetCompare1(TIM4,ENGINE_MAX_SPD);
}
else if(velo2><0)
{
ENGINE2_DIR1=0;
ENGINE2_DIR2=1;
if(velo2>(-ENGINE_MAX_SPD)) TIM_SetCompare1(TIM4,(Trans-velo2));
else TIM_SetCompare1(TIM4,ENGINE_MAX_SPD);
}
else
{
ENGINE2_DIR1=0;
ENGINE2_DIR2=0;
TIM_SetCompare1(TIM4,0);
}
}
void Engine1PositionPID()
{
engineLocErr[0][2]=engineLocErr[0][1];
engineLocErr[0][1]=engineLocErr[0][0];
engineLocErr[0][0]=engineLocDst[0]-engineLoc[0];
if(abs(engineLocErr[0][0])>80) 
enginePidOp[0]=engineKp*(engineLocErr[0][0]-engineLocErr[0][1])+engineKi*engineLocErr[0][0]+engineKd*(engineLocErr[0][0]-engineLocErr[0][1]*2+engineLocErr[0][2]);
else enginePidOp[0]=0;
Engine1SpeedSet(enginePidOp[0]);//注意

}
void Engine2PositionPID()
{
engineLocErr[1][2]=engineLocErr[1][1];
engineLocErr[1][1]=engineLocErr[1][0];
engineLocErr[1][0]=engineLocDst[1]-engineLoc[1];
if(abs(engineLocErr[1][0])>80) 
enginePidOp[1]=engineKp*(engineLocErr[1][0]-engineLocErr[1][1])+engineKi*engineLocErr[1][0]+engineKd*(engineLocErr[1][0]-engineLocErr[1][1]*2+engineLocErr[1][2]);
else enginePidOp[1]=0;
Engine2SpeedSet(enginePidOp[1]);
}
回复 支持 反对

使用道具 举报

11

主题

43

帖子

0

精华

初级会员

Rank: 2

积分
107
金钱
107
注册时间
2013-8-3
在线时间
0 小时
 楼主| 发表于 2014-5-14 00:03:29 | 显示全部楼层
回复【13楼】小石头:
---------------------------------
自己看看
回复 支持 反对

使用道具 举报

11

主题

43

帖子

0

精华

初级会员

Rank: 2

积分
107
金钱
107
注册时间
2013-8-3
在线时间
0 小时
 楼主| 发表于 2014-5-14 00:04:00 | 显示全部楼层
回复【13楼】小石头:
---------------------------------
注释有些不对
回复 支持 反对

使用道具 举报

9

主题

48

帖子

0

精华

初级会员

Rank: 2

积分
105
金钱
105
注册时间
2014-3-15
在线时间
0 小时
发表于 2014-5-14 12:28:45 | 显示全部楼层
回复【16楼】西域大盘鸡:
---------------------------------
对了,你采集编码器脉冲的程序呢
回复 支持 反对

使用道具 举报

11

主题

43

帖子

0

精华

初级会员

Rank: 2

积分
107
金钱
107
注册时间
2013-8-3
在线时间
0 小时
 楼主| 发表于 2014-5-14 19:15:02 | 显示全部楼层
回复【17楼】小石头:
---------------------------------
编码器分好几种,你用的是那种,程序不一样~!!~~!
回复 支持 反对

使用道具 举报

9

主题

48

帖子

0

精华

初级会员

Rank: 2

积分
105
金钱
105
注册时间
2014-3-15
在线时间
0 小时
发表于 2014-5-15 17:37:59 | 显示全部楼层
回复【18楼】西域大盘鸡:
---------------------------------
输出方波的那种
回复 支持 反对

使用道具 举报

11

主题

43

帖子

0

精华

初级会员

Rank: 2

积分
107
金钱
107
注册时间
2013-8-3
在线时间
0 小时
 楼主| 发表于 2014-5-15 17:53:58 | 显示全部楼层
回复【19楼】小石头:
---------------------------------
我的和你的不一样,我的是同步串行输出的,你的是并联的~!!~!~
回复 支持 反对

使用道具 举报

4

主题

52

帖子

0

精华

初级会员

Rank: 2

积分
89
金钱
89
注册时间
2014-11-26
在线时间
0 小时
发表于 2014-12-15 21:58:17 | 显示全部楼层
原子哥推荐的PDF文档是哪一个?
回复 支持 反对

使用道具 举报

96

主题

762

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1228
金钱
1228
注册时间
2012-10-19
在线时间
15 小时
发表于 2014-12-16 11:47:56 | 显示全部楼层
PWM_OUT+= IncPIDCalc(Now_speed);这个的意思就说在现在输出的基础上叠加上PI的变换
PWM_OUT=IncPIDCalc(Now_speed);    这个就是每次的输出直接等于PID的值
第一个用的是误差值进行计算,第二个用的当前的值与初始值(PWM等于0的状态)和目前值进行比较,查看出当前值的位置来进行控制。
第一种无需累积,超调量小,稳定时间相对较长。第二种需要累积,超调量可能会过大,但稳定时间真的很短。各有优势,没有哪个好,看具体应用。
我做应用时直接用的MATLAB里的那个PID模块的算法,与这两种相比,缺点是有浮点运算,占用CPU相比而言多点,优点是直接MATLAB仿真得到P,I,D的参数,还有采样频率。
回复 支持 反对

使用道具 举报

11

主题

64

帖子

0

精华

初级会员

Rank: 2

积分
90
金钱
90
注册时间
2014-8-4
在线时间
14 小时
发表于 2015-5-11 14:58:33 | 显示全部楼层
我的观点认为这两种写法都是从一开始计算的,一种位置式的一种增量式,增量式的表面上看来只有和三种状态有关en en-1 en-2,但是别忘了增量式的是递推关系的,这就意味着要想得到最终的结果就必须要有第一项,Uk=Uk-1+△Uk
照此递推下去一定是要得到U0,都是从一开始计算,所以说增量式和位置式的原理是一样的,只不过算法上增量式的优越性很大
生命不息,学习不止
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
21
金钱
21
注册时间
2015-8-18
在线时间
0 小时
发表于 2015-8-18 22:11:30 | 显示全部楼层
这样的就不需要采样时间和比例系数、微分系数那些的么?
回复 支持 反对

使用道具 举报

15

主题

184

帖子

0

精华

高级会员

Rank: 4

积分
647
金钱
647
注册时间
2014-4-29
在线时间
299 小时
发表于 2015-8-19 15:37:08 | 显示全部楼层
增量式pid输出结果是这个,PWM_OUT+= IncPIDCalc(Now_speed);
但是你写的算式不对,系数也不对,系数应该先变换一下。
总之你应该先找一下增量式的pid的原理说明的东西亲手推导一下,pid增量式的代码在网上的百度到的基本都是错的,建议有时间就看看自动控制原理,没时间就看看pid的数学公式本身。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-7-22 07:19

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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