OpenEdv-开源电子网

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

在整定PID参数时,数值一直在震荡,振幅有40%,请各位大神指点指点

[复制链接]

11

主题

135

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2548
金钱
2548
注册时间
2017-9-8
在线时间
446 小时
发表于 2025-3-17 09:38:44 | 显示全部楼层 |阅读模式
100金钱
如题 ,现在在做一个给气囊打气,并将气囊压力保持在设定值的项目。气压传感器是IIC通信的,间隔1秒发送一次数据。微型气泵用来打气,使用PWM控制,因为气囊不大,微型气泵在PID工作时达不到工作电压范围就超调了,然后开始震荡。
又因为微型气泵不在工作电压范围,就导致在同一PWM值下,有时启动,有时不启动,现象就是一直在振幅40%左右震荡。
调整多次PID参数都是这样,没什么改善。第一次做PID,不是很懂,请各位大神指点指点。
PID参数初始化:
  1. void  PID_Init(float Kp, float Ki, float Kd, float setpoint, float dt)
  2. {
  3.     pid.Kp = Kp;                          // 比例系数
  4.     pid.Ki = Ki;                                         // 积分系数
  5.     pid.Kd = Kd;                                          // 微分系数
  6.     pid.setpoint = setpoint;                 // 目标压力值
  7.     pid.integral = 0;                                 // 积分项累计值,误差和
  8.     pid.prev_error = 0;                          // 上一次误差(用于微分计算)
  9.     pid.dt = dt;                                        // 控制周期(需与传感器采样周期匹配)
  10.     pid.out_min = 0;                                 // PWM最小占空比(如0%)
  11.     pid.out_max = 360;                                // PWM最大占空比(如100%)
  12. }
复制代码
  1. PID_Init(0.5, 0.03, 0.1, 50.0, 1);
复制代码
PID计算函数:
  1. float  PID_Compute(float measured)
  2. {
  3.     float  error,derivative,output;
  4.         //计算误差       
  5.         error = pid.setpoint - measured;
  6.    
  7.     // 积分项
  8.     pid.integral += error * pid.dt;
  9.    
  10.     // 微分项
  11.         derivative = (error - pid.prev_error) / pid.dt;
  12.    
  13.     // 计算输出
  14.     output = pid.Kp * error + pid.Ki * pid.integral + pid.Kd * derivative;
  15.    
  16.     // 输出限幅
  17.     output = (output > pid.out_max) ? pid.out_max :
  18.              (output < pid.out_min) ? pid.out_min : output;
  19.    
  20.     return  output;
  21. }
复制代码
main函数调用:
  1.   if(g_RunTime-TIME2>=1000)//1s间隔,因为传感器反应时间
  2.                 {
  3.                         Lwp6130_Send_Command_BLAST();
  4.                         current_pressure = Lwp6130_FullData_Read_BLAST();                                               
  5.                        
  6.                         // PID计算并更新PWM
  7.                         output1 = PID_Compute(current_pressure);                       
  8.                         pwmvalue=(uint16_t)(output1*10+1000);
  9.                         printf("current_pressure=%f,output1=%f,pwmvalue=%d\r\n",current_pressure,output1,pwmvalue);
  10.                         TIM_SetCompare2(TIM4, pwmvalue);

  11.                         TIME2=g_RunTime;
  12.                 }
复制代码
PWM初始化:
  1. TIM4_PWM_init(3599,0);
复制代码

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

使用道具 举报

12

主题

3370

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8580
金钱
8580
注册时间
2020-5-11
在线时间
3998 小时
发表于 2025-3-17 12:05:33 | 显示全部楼层
本帖最后由 LcwSwust 于 2025-3-17 12:09 编辑

1.prev_error未见赋值;
2.integral建议限幅;
3.未见数据或曲线,也不知道震荡周期,以及延迟时间;
建议将设置值\检测值\输出量绘制成曲线,有些串口助手之类的软件是可以显示数据曲线的,找一找.

专治疑难杂症
回复

使用道具 举报

2

主题

457

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4387
金钱
4387
注册时间
2018-5-14
在线时间
946 小时
发表于 2025-3-17 13:31:26 | 显示全部楼层
感觉是kp太大了,如果你1s-2s就能把气囊打到压力值,建议调小kp,延长时间,PID更多是通过积分进行补偿,出现这种情况哪怕设置了ki也不起作用。
回复

使用道具 举报

11

主题

135

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2548
金钱
2548
注册时间
2017-9-8
在线时间
446 小时
 楼主| 发表于 2025-3-17 14:36:31 | 显示全部楼层
LcwSwust 发表于 2025-3-17 12:05
1.prev_error未见赋值;
2.integral建议限幅;
3.未见数据或曲线,也不知道震荡周期,以及延迟时间;

PID计算函数我改了下
  1. float  PID_Compute(float measured)
  2. {
  3.     float  error,derivative,output;
  4.         //计算误差       
  5.         error = pid.setpoint - measured;
  6.    
  7.     // 积分项
  8.     pid.integral += error * pid.dt;
  9.         if(pid.integral > pid.out_max) pid.integral=pid.out_max;
  10.     else if(pid.integral < -pid.out_max) pid.integral=-pid.out_max;
  11.        
  12.     // 微分项
  13.         derivative = (error - pid.prev_error) / pid.dt;
  14.         pid.prev_error = error;
  15.    
  16.     // 计算输出
  17.     output = pid.Kp * error + pid.Ki * pid.integral + pid.Kd * derivative;
  18.    
  19.     // 输出限幅
  20.     output = (output > pid.out_max) ? pid.out_max :
  21.              (output < pid.out_min) ? pid.out_min : output;
  22.    
  23.     return  output;
  24. }
复制代码

那个显示曲线的软件是不是VOFA+这个?
回复

使用道具 举报

13

主题

137

帖子

0

精华

高级会员

Rank: 4

积分
547
金钱
547
注册时间
2018-11-2
在线时间
113 小时
发表于 2025-3-17 14:42:02 | 显示全部楼层
“就导致在同一PWM值下,有时启动,有时不启动”,这说明方案有问题,调程序有什么用。与其用PID还不如检测到压力不够泵就全开,压力够了泵就全关
回复

使用道具 举报

11

主题

135

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2548
金钱
2548
注册时间
2017-9-8
在线时间
446 小时
 楼主| 发表于 2025-3-17 14:43:05 | 显示全部楼层
姚先起 发表于 2025-3-17 13:31
感觉是kp太大了,如果你1s-2s就能把气囊打到压力值,建议调小kp,延长时间,PID更多是通过积分进行补偿,出 ...

KP我试过改小,但因为气泵工作PWM值需要1500以上,需要很长的时间才能启动,启动后几秒就超调了,把KP改小到一定程度,就到不了设定值了
回复

使用道具 举报

11

主题

135

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2548
金钱
2548
注册时间
2017-9-8
在线时间
446 小时
 楼主| 发表于 2025-3-17 15:22:59 | 显示全部楼层
qinlu123 发表于 2025-3-17 14:42
“就导致在同一PWM值下,有时启动,有时不启动”,这说明方案有问题,调程序有什么用。与其用PID还不如检测 ...

我想过,把充气分三个阶段,用三种不同的速度充气,测试好每个速度在单位时间内的充气量,用的时候直接用定时器定时充气。但我的设定值是可以在1-100间随便设置的,每个设定值要做一个对应的操作,太麻烦了
回复

使用道具 举报

12

主题

3370

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8580
金钱
8580
注册时间
2020-5-11
在线时间
3998 小时
发表于 2025-3-17 16:12:56 | 显示全部楼层
本帖最后由 LcwSwust 于 2025-3-17 16:16 编辑
jian0052 发表于 2025-3-17 14:36
PID计算函数我改了下

那个显示曲线的软件是不是VOFA+这个?

好的,只是对于输出限幅的问号语句我没见过,更喜欢用两个if语句那种,总之确认功能没问题就行.关于显示曲线的软件,总之能用就行.

另外就是控制策略问题,气泵本身的特性,可能一开始阻力较大,需要较大的占空比才能让电机启动,然后只需要很小的占空比就能维持转动.

三个办法你考虑一下:
一是摸清气泵的底细,估计他什么时候停止,怎么让它快速启动.比如100%工作0.1秒,然后改变占空比为PID输出值.
应该要有个状态机,判断占空比低于多少时电机停转,占空比高于多少时能开始转动.

二是间歇工作,比如100%占空比工作1秒,停止9秒,PID输出控制这里的工作时间;
三是做一个电机转速的检测(比如通过检测气泵电机的电流计算感应电动势来得到转速,或在断开供电的时候直接测量电机发电的电压得到转速),PID输出控制转速,
转速也由一个PID算法控制,这个系统就是"串级PID".



专治疑难杂症
回复

使用道具 举报

13

主题

137

帖子

0

精华

高级会员

Rank: 4

积分
547
金钱
547
注册时间
2018-11-2
在线时间
113 小时
发表于 2025-3-17 16:17:47 | 显示全部楼层
jian0052 发表于 2025-3-17 14:43
KP我试过改小,但因为气泵工作PWM值需要1500以上,需要很长的时间才能启动,启动后几秒就超调了,把KP改 ...

到不了设定值怎么会和Kp有关,只要KI不为0就一定能达到设定值,仿真一下看看为啥到不了设定值
回复

使用道具 举报

13

主题

137

帖子

0

精华

高级会员

Rank: 4

积分
547
金钱
547
注册时间
2018-11-2
在线时间
113 小时
发表于 2025-3-17 16:31:26 | 显示全部楼层
先把微分项参数设置为0,比例和积分项参数设置为一样,参数不要太大因为你1秒才读一次压力传感器计算一次PID所以十几秒(PID计算十几次)能接近目标值就已经很不错了。根据我的经验,阶跃响应的响应时间至少要计算几十次PID才行。你现在要么提高压力的检测频率要么减小PID参数。
回复

使用道具 举报

2

主题

457

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4387
金钱
4387
注册时间
2018-5-14
在线时间
946 小时
发表于 2025-3-17 16:33:56 | 显示全部楼层
jian0052 发表于 2025-3-17 14:43
KP我试过改小,但因为气泵工作PWM值需要1500以上,需要很长的时间才能启动,启动后几秒就超调了,把KP改 ...

先把Kp调小,然后你PWM输出太低,泵不启动,不要紧。调大ki,然后前面的时间,假设是前10s,因为kp不够导致输出过低没让泵转,所以ki作用下,积分会越来越大,你的out输出会慢慢的还是会到1500以上,这是泵就会起来,到压力值后,kp*0=0,所以kp不起作用了,超过设定值,ki会出现负累计,也会修正气泵输出。kp在pid中的作用其实不大,主要作用是快速反应,比如你距离目标压力足够远时,都是kp作用,但是随着时间增加,kp作用会变得很不明显,除非你的气囊瞬间漏气或者超压。
回复

使用道具 举报

13

主题

137

帖子

0

精华

高级会员

Rank: 4

积分
547
金钱
547
注册时间
2018-11-2
在线时间
113 小时
发表于 2025-3-17 16:35:56 | 显示全部楼层
把你的泵拍个照片看看,我怎么感觉你这个泵的特性这么熟悉
回复

使用道具 举报

11

主题

135

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2548
金钱
2548
注册时间
2017-9-8
在线时间
446 小时
 楼主| 发表于 2025-3-17 16:50:32 | 显示全部楼层
qinlu123 发表于 2025-3-17 16:35
把你的泵拍个照片看看,我怎么感觉你这个泵的特性这么熟悉

压力传感器就是必须最短1秒查询1次 微信图片_20250317164630.jpg
回复

使用道具 举报

13

主题

137

帖子

0

精华

高级会员

Rank: 4

积分
547
金钱
547
注册时间
2018-11-2
在线时间
113 小时
发表于 2025-3-17 16:57:12 | 显示全部楼层
jian0052 发表于 2025-3-17 16:50
压力传感器就是必须最短1秒查询1次

压力检测范围是多大,接受成本是多少
回复

使用道具 举报

11

主题

135

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2548
金钱
2548
注册时间
2017-9-8
在线时间
446 小时
 楼主| 发表于 2025-3-17 17:09:32 | 显示全部楼层
qinlu123 发表于 2025-3-17 16:57
压力检测范围是多大,接受成本是多少

压力范围是0-150KPa,接受成本是啥?
回复

使用道具 举报

13

主题

137

帖子

0

精华

高级会员

Rank: 4

积分
547
金钱
547
注册时间
2018-11-2
在线时间
113 小时
发表于 2025-3-17 17:15:41 | 显示全部楼层
jian0052 发表于 2025-3-17 17:09
压力范围是0-150KPa,接受成本是啥?

这种压力范围的压力传感器大把大把的,数字的也有模拟的也有,换个压力传感器吧,一秒钟一更新做显示还行做控制完全不够用
回复

使用道具 举报

11

主题

135

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2548
金钱
2548
注册时间
2017-9-8
在线时间
446 小时
 楼主| 发表于 2025-3-17 17:32:08 | 显示全部楼层
qinlu123 发表于 2025-3-17 17:15
这种压力范围的压力传感器大把大把的,数字的也有模拟的也有,换个压力传感器吧,一秒钟一更新做显示还行 ...

需要换成多长时间采一次的够用?
回复

使用道具 举报

13

主题

137

帖子

0

精华

高级会员

Rank: 4

积分
547
金钱
547
注册时间
2018-11-2
在线时间
113 小时
发表于 2025-3-17 17:36:52 | 显示全部楼层
jian0052 发表于 2025-3-17 17:32
需要换成多长时间采一次的够用?

50ms以内吧,我之前做的压力相关的项目都是20ms读一次压力传感器
回复

使用道具 举报

13

主题

137

帖子

0

精华

高级会员

Rank: 4

积分
547
金钱
547
注册时间
2018-11-2
在线时间
113 小时
发表于 2025-3-17 17:40:16 | 显示全部楼层
jian0052 发表于 2025-3-17 17:32
需要换成多长时间采一次的够用?

你可以先把PID参数调小试试,验证一下可行性,看能不能在牺牲响应时间的前提下保证不振荡
回复

使用道具 举报

11

主题

135

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2548
金钱
2548
注册时间
2017-9-8
在线时间
446 小时
 楼主| 发表于 2025-3-17 18:53:37 | 显示全部楼层
还是不行,KP和KI都调成0.05了,还是一直震荡,振幅还偏大了
回复

使用道具 举报

11

主题

135

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2548
金钱
2548
注册时间
2017-9-8
在线时间
446 小时
 楼主| 发表于 2025-3-18 08:38:40 | 显示全部楼层
qinlu123 发表于 2025-3-17 17:36
50ms以内吧,我之前做的压力相关的项目都是20ms读一次压力传感器

PID的周期是跟读传感器的周期一样么,还是更快
回复

使用道具 举报

11

主题

135

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2548
金钱
2548
注册时间
2017-9-8
在线时间
446 小时
 楼主| 发表于 2025-3-18 09:27:26 | 显示全部楼层
qinlu123 发表于 2025-3-17 17:36
50ms以内吧,我之前做的压力相关的项目都是20ms读一次压力传感器

改读压力传感器时间的时候,PID周期也是同样的么,计算函数里的dt需不需要改
回复

使用道具 举报

2

主题

457

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4387
金钱
4387
注册时间
2018-5-14
在线时间
946 小时
发表于 2025-3-18 09:30:29 | 显示全部楼层
jian0052 发表于 2025-3-17 18:53
还是不行,KP和KI都调成0.05了,还是一直震荡,振幅还偏大了

被你误导了,你这个应用为啥是要用PID?你的气囊会漏气吗?你可以做个实验,让气泵起转,最低速度给气囊打气,气囊如果完全不漏气,压力肯定是会上升的直到气泵打不动为止气泵会自己过流保护而停止。停止后才会从气泵处漏气出去,漏出气后气泵又打,又不漏气反而多气了,那不就是你目前的现象嘛。PID根本就没作用。你给气囊扎个洞,有漏气才会出现积分补偿的作用。所以你的应用不适合用PID,反而回差补压的方法更适合。或者你在气泵出口加个单向阀防止漏气。
回复

使用道具 举报

11

主题

135

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2548
金钱
2548
注册时间
2017-9-8
在线时间
446 小时
 楼主| 发表于 2025-3-18 10:09:54 | 显示全部楼层
姚先起 发表于 2025-3-18 09:30
被你误导了,你这个应用为啥是要用PID?你的气囊会漏气吗?你可以做个实验,让气泵起转,最低速度给气囊 ...

我的气囊是会漏气的,漏的比较慢,我试验过,打完气后,气泵停止后漏的快一点,但是打气太快了,所以表现出现在的样子,根本稳定不下来
回复

使用道具 举报

11

主题

135

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2548
金钱
2548
注册时间
2017-9-8
在线时间
446 小时
 楼主| 发表于 2025-3-18 10:15:18 | 显示全部楼层
本帖最后由 jian0052 于 2025-3-18 10:20 编辑

下面是我打印的数据,从开始到震荡,current_pressure是压力值,output1是PID输出,pwmvalue是输出PWM值,与output是10倍取整的关系,气泵大致在1500左右开启,但有时到了1400的时候才能停

1

1

2

2

3.png
4.png
5.png

6

6

7.png

回复

使用道具 举报

13

主题

137

帖子

0

精华

高级会员

Rank: 4

积分
547
金钱
547
注册时间
2018-11-2
在线时间
113 小时
发表于 2025-3-18 11:31:21 | 显示全部楼层
jian0052 发表于 2025-3-18 09:27
改读压力传感器时间的时候,PID周期也是同样的么,计算函数里的dt需不需要改

PID的控制周期和读压力周期同步,dt也要改
回复

使用道具 举报

11

主题

135

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2548
金钱
2548
注册时间
2017-9-8
在线时间
446 小时
 楼主| 发表于 2025-3-18 12:55:54 | 显示全部楼层
qinlu123 发表于 2025-3-18 11:31
PID的控制周期和读压力周期同步,dt也要改

好的,谢谢
回复

使用道具 举报

2

主题

457

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4387
金钱
4387
注册时间
2018-5-14
在线时间
946 小时
发表于 2025-3-19 08:36:02 | 显示全部楼层
jian0052 发表于 2025-3-18 10:15
下面是我打印的数据,从开始到震荡,current_pressure是压力值,output1是PID输出,pwmvalue是输出PWM值, ...

你的气压在某个时刻有个突变过程,从10百帕到40百帕速度很快,建议在这个突变前的压力不要使用PID调节气泵。
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-4-6 12:02

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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