硬汉嵌入式论坛

 找回密码
 立即注册
查看: 3580|回复: 12
收起左侧

[有问必答] PID参数怎么样调试出来?

[复制链接]

27

主题

25

回帖

106

积分

初级会员

积分
106
发表于 2019-8-31 13:46:04 | 显示全部楼层 |阅读模式
一个设定频率,一个测量频率,通过PID调节控制DAC寄存器的值,这个DAC12位的,执行机构通过这个电压改变频率,这个PID算法的各个参数怎么搞出来?
//extern int U_Set;
//extern u16 CCR1_Val;
/*====================================================================================================
PID Function
The PID (比例、积分、微分) function is used in mainly
control applications. PIDCalc performs one iteration of the PID
algorithm.
While the PID function works, main is just a dummy program showing
a typical usage.
=====================================================================================================*/
typedef struct PID {
float SetPoint; // 设定目标Desired value
float Proportion; // 比例常数Proportional Const
float Integral; // 积分常数Integral Const
float Derivative; // 微分常数Derivative Const
float LastError; // Error[-1]
float PrevError; // Error[-2]
float SumError; // Sums of Errors
} PID;
/*====================================================================================================/
PID计算部分
=====================================================================================================*/
PID   vPID={0,0.1,0.001,0.001,0,0,0};
float PIDCalc( PID *pp, float NextPoint )
{
float dError,
Error;
Error = pp->SetPoint - NextPoint; // 偏差
pp->SumError += Error; // 积分
dError = pp->LastError - pp->PrevError; // 当前微分
pp->PrevError = pp->LastError;
pp->LastError = Error;
    if(pp->SumError>900)  pp->SumError=900;
    else if(pp->SumError<-900)   pp->SumError=-900;
return (pp->Proportion * Error // 比例项
+ pp->Integral * pp->SumError // 积分项
+ pp->Derivative * dError // 微分项
);
}
float Vol(int vSet,int v3){
float vOut; // PID Response (Output)
float vIn; // PID Feedback (Input)
vPID.SetPoint = vSet; // Set PID Setpoint
vIn = (float)v3; // Read Input
vOut = PIDCalc ( &vPID,vIn ); // Perform PID Interation  
return vOut;
}
void mian()
{
while(1)
{
if(Flag_3S==1)
  {
   if(target-TIM_ExtCntFreq>=6||target-TIM_ExtCntFreq<=-6)
   {
        Pv=Vol(target,TIM_ExtCntFreq);// PID算法
        dac_value=dac_value+Pv/2.04;//DAC 寄存器调节
    DAC_SetChannel1Data(DAC_Align_12b_R,dac_value);
   }
   led3=~led3;
   Flag_3S=0;
}
   
  }
}

回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106913
QQ
发表于 2019-8-31 13:48:00 | 显示全部楼层
帮顶
回复

使用道具 举报

39

主题

929

回帖

1051

积分

至尊会员

积分
1051
发表于 2019-8-31 14:44:54 | 显示全部楼层
PID就4个参数,都是靠使用过程中人工设置的,所以,楼主要问的到底是什么?
回复

使用道具 举报

27

主题

25

回帖

106

积分

初级会员

积分
106
 楼主| 发表于 2019-9-1 20:51:34 | 显示全部楼层
ghslfgkkl88 发表于 2019-8-31 14:44
PID就4个参数,都是靠使用过程中人工设置的,所以,楼主要问的到底是什么?

是这样的,我用两个STM32单片机,1号单片机STM32单片机发生频率F,2号单片机测量这个频率,通过设定目标频率,通过PID算法控制,控制DAC输出电压,1号单片机通过ADC测量这个电压值,发生800-1500HZ频率的,就是不知道PID算法执行OUT参数怎么设置?
回复

使用道具 举报

39

主题

929

回帖

1051

积分

至尊会员

积分
1051
发表于 2019-9-1 21:38:26 | 显示全部楼层
bbxyliyang01 发表于 2019-9-1 20:51
是这样的,我用两个STM32单片机,1号单片机STM32单片机发生频率F,2号单片机测量这个频率,通过设定目标 ...

那PID一般由你的2号单片机计算。步骤一般如下:
1. 2号单片机输出一个初始DA电压,比如为Vo
2. 2号单片机检测1号单片机的频率,并根据PID的4个参数,计算出Vo需要增加或减少的量,比如为Vx
3. Vo = Vo+Vx(Vx为有符号数,正时为加,负时为减),计算得到新的Vo
4. 将新的Vo输出,返回到步骤2执行
回复

使用道具 举报

27

主题

25

回帖

106

积分

初级会员

积分
106
 楼主| 发表于 2019-9-2 08:06:05 | 显示全部楼层
ghslfgkkl88 发表于 2019-9-1 21:38
那PID一般由你的2号单片机计算。步骤一般如下:
1. 2号单片机输出一个初始DA电压,比如为Vo
2. 2号单片 ...

太感谢了,您说的很清晰,我按您的改了,成功了,但程序中 if(pp->SumError>900)  pp->SumError=900;
     else if(pp->SumError<-900)   pp->SumError=-900;这几句什么用处,看到不少很明白,为什么要加这几句话,这个程序我也是参考别人的程序,我很好奇,为什么他的算法没有积分时间,微分时间?
回复

使用道具 举报

335

主题

2037

回帖

3047

积分

版主

Rank: 7Rank: 7Rank: 7

积分
3047
发表于 2019-9-2 08:24:03 | 显示全部楼层
比较经典的方式是,根据实际状况编写一个理论模型,在matlab中仿真,可确定参数。然后再写成程序。 实用的方法,先预估一个参数,一个一个的调试,看过冲和震荡时间。
回复

使用道具 举报

27

主题

25

回帖

106

积分

初级会员

积分
106
 楼主| 发表于 2019-9-3 09:21:45 | 显示全部楼层
caicaptain2 发表于 2019-9-2 08:24
比较经典的方式是,根据实际状况编写一个理论模型,在matlab中仿真,可确定参数。然后再写成程序。 实用的 ...

感谢您的回复!
回复

使用道具 举报

39

主题

929

回帖

1051

积分

至尊会员

积分
1051
发表于 2019-9-3 09:44:58 | 显示全部楼层
bbxyliyang01 发表于 2019-9-2 08:06
太感谢了,您说的很清晰,我按您的改了,成功了,但程序中 if(pp->SumError>900)  pp->SumError=900;
   ...

1. 正900和负900就是限制范围的,限制每次不超过这个范围,工程中经常这么做,可有效防止数据变化太大造成溢出和错乱等
2. 积分和微分你没学过还是忘记了?学微积分的时候,都是从离散开始讲起的,比如X1点的值是Y1,X2点的值是Y2,那么X1~X2之间的积分就是Y2*(X2-X1),微分就是(Y2-Y1)/(X2-X1),这里的X2-X1就是你所说的积分时间和微分时间,而你没看到它们,是因为你所找的代码把这个时间量化为1,即时间单位 X2-X1=1,所以最后积分只剩Y2(对应你的Error),而微分只剩Y2-Y1(对应你的pp->LastError - pp->PrevError)
3. 对于PID将这些个时间量化为1的情况,我也不知道效果如何,实际没试过
回复

使用道具 举报

27

主题

25

回帖

106

积分

初级会员

积分
106
 楼主| 发表于 2019-9-3 13:40:08 | 显示全部楼层
ghslfgkkl88 发表于 2019-9-3 09:44
1. 正900和负900就是限制范围的,限制每次不超过这个范围,工程中经常这么做,可有效防止数据变化太大造 ...

感谢您对回复,感谢了!明白了!
回复

使用道具 举报

5

主题

81

回帖

96

积分

初级会员

积分
96
发表于 2022-10-4 13:25:06 | 显示全部楼层
楼主你好,请问dac_value=dac_value+Pv/2.04;//DAC 寄存器调节  这句话没看懂,为什么要除以2.04?
我现在遇到个问题,拿你的例子打个比方,就是不知道输出电压和频率之间的具体计算关系,只知道定性关系,比如DAC电压越高,频率越高,但是每上调1mV电压,频率到底升高多少不知道

我改如何传递参数
回复

使用道具 举报

5

主题

81

回帖

96

积分

初级会员

积分
96
发表于 2022-10-4 13:26:46 | 显示全部楼层
ghslfgkkl88 发表于 2019-9-3 09:44
1. 正900和负900就是限制范围的,限制每次不超过这个范围,工程中经常这么做,可有效防止数据变化太大造 ...

大佬你好,能帮忙看下这个帖子下,我的问题吗
回复

使用道具 举报

39

主题

929

回帖

1051

积分

至尊会员

积分
1051
发表于 2022-10-8 23:53:23 来自手机 | 显示全部楼层
流型 发表于 2022-10-4 13:25
楼主你好,请问dac_value=dac_value+Pv/2.04;//DAC 寄存器调节  这句话没看懂,为什么要除以2.04?
我现在 ...

他这里为什么要除以2.04我也不知道,可能是他硬件电路有个什么转换或者基准什么的。但我认为是不需要除2.04的,增量式PID计算出来的就是控制量的增量,直接按有符号数做加法就行。
回复

使用道具 举报

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

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-9 17:02 , Processed in 0.200192 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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