站内搜索
更多
简易pid实现
专业版

简易pid实现

工程标签

32位单片机

88
0
0
0

简介

基于 立创·天猛星 MSPM0G3507 开发板制作的简易 PID 入门套件,对带编码器的电机,使用 PID 控制算法,实现 定速功能 和 定距功能,再通过屏幕显示出 PID 参数以及当前值与目标值

简介:基于 立创·天猛星 MSPM0G3507 开发板制作的简易 PID 入门套件,对带编码器的电机,使用 PID 控制算法,实现 定速功能 和 定距功能,再通过屏幕显示出 PID 参数以及当前值与目标值
电赛TI训练营-简易PID项目
复刻成本:60

开源协议

GPL 3.0

创建时间:2025-04-27 19:07:33更新时间:2025-06-12 10:32:29

描述

项目简介

基于 立创·天猛星 MSPM0G3507 开发板制作的简易 PID 入门套件,对带编码器的电机,使用 PID 控制算法,实现 定速功能 和 定距功能,再通过屏幕显示出 PID 参数以及当前值与目标值

项目功能

功能需求
屏幕显示二级菜单,通过按键选择;
屏幕显示PID曲线变化;
按键长短按控制和调参;
实现电机PID的实时定速调整;
实现电机PID的实时定距调整;

原理解析(硬件说明)

搭配天猛星,配合电路实现,详细见原理图

软件代码

PID 定速功能
本节介绍
📝本节您将了解PID的基本公式,通过实际值与目标值的误差,实现让实时速度以最快的时间接近目标速度。

🏆本章⽬标

1️⃣了解PID

2️⃣实现PID定速

定速功能说明
定速功能:使电机当前实时速度以最快的时间接近设定的目标速度。

实现这个功能最基础的想法是:

当 实时速度 小于 目标速度,那就让实时速度变快;

当 实时速度 大于 目标速度,那就让实时速度变慢;

按照这个想法写代码,最基础的想法如下:

当前速度=0, 目标速度=100
if ( 当前速度 < 目标速度 )
{
当前速度++;
}
if( 当前速度 > 目标速度 )
{
当前速度--;
}
基础想法代码
执行代码后 目标速度与当前速度的变化
但是这个想法有问题。目前我的目标速度是100,这个实时速度的变化还能够接受,那如果是10000呢,百万,千万呢?如果还是以 1 为基础进行步进,那速度的提升就太慢了。

这个时候就希望有一个算法,能够让我们当前实时速度的步进单位不要一直是1。 比如:

我的目标速度和实时速度差距非常大的时候,那我的步进单位是100,100的变化;

我的目标速度和实时速度差距非常小的时候,那我的步进单位是0.1,0.1的变化;

这样不管目标有多大,都能够实现快速的接近目标。

PID算法就可以实现。

PID的基本公式
PID算法,即比例P-积分I-微分D控制器,它通过控制系统的偏差(目标值与实际值之间的差)来调节控制变量,使得系统达到或维持在一个预定的状态。

PID的基本公式

PID_OUT = (Kp x P)+ (Ki x I)+(Kd x D)
公式拆分为静态参数和动态参数:

静态参数

Kp 是比例增益
Ki 是积分增益
Kd 是微分增益
动态参数

P = 设定值与实际值之间的误差e
I = 误差e的累加
D = 当前误差e - 之前的误差last_e
将公式转换为代码,如下:

typedef struct
{
float kp, ki, kd; // 三个静态系数
float change_p, change_i, change_d; // 三个动态参数
float error, last_error; // 误差、之前误差
float max_change_i; // 积分限幅
float output, max_output; // 输出、输出限幅
int target; // 目标
}PID;

/****************************************************
功能:PID计算
参数:pid = pid的参数输入
target = 目标值
current = 当前值
返回:PID计算后的结果
****************************************************/
float pid_calc(PID *pid, float target, float current)
{
//用上一次的误差值更新 之前误差last_error
pid->last_error = pid->error;
//获取新的误差 = 目标值 - 当前值
pid->error = target - current;

//计算比例P = 目标值与实际值之间的误差e
float pout = pid-&gt;error;
//计算积分I = 误差e的累加
pid-&gt;change_i += pid-&gt;error;
//计算微分D = 当前误差e - 之前的误差last_e
float dout = pid-&gt;error - pid-&gt;last_error;

//积分I 限制不能超过正负最大值
if(pid-&gt;change_i &gt; pid-&gt;max_change_i)
{
  pid-&gt;change_i = pid-&gt;max_change_i;
}
else if(pid-&gt;change_i &lt; -pid-&gt;max_change_i)
{
  pid-&gt;change_i = -pid-&gt;max_change_i;
}

//计算输出PID_OUT = (Kp x P)+ (Ki x I)+(Kd x D)
pid-&gt;output = (pid-&gt;kp * pout) + (pid-&gt;ki * pid-&gt;change_i) + (pid-&gt;kd * dout);

//输出 限制不能超过正负最大值
if(pid-&gt;output &gt; pid-&gt;max_output) pid-&gt;output = pid-&gt;max_output;
else if(pid-&gt;output &lt; -pid-&gt;max_output) pid-&gt;output = -pid-&gt;max_output;

//返回PID计算的结果
return pid-&gt;output;

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
PID静态参数的调节
如果某个 P,I,D 参数偏离了原点的 PID 值,控制效果就会变化。控制效果与各个参数的规律如图所示。截取自:链接

图 4

当然,如果你能记录PID的曲线的话,就可以导入matlab进行自动调节pid参数,网上有挺多教程,大家可以搜一搜。这里我们就只介绍靠经验来调节了(简称瞎鼓捣)。

比较常用的有试错法,这个是一种经验性的方法,通过尝试不同的PID参数值,找到合适的参数设置。基本步骤如下:

TIP

首先,将I和D参数设置为0,只保留P参数。
增加P参数,直到系统的响应时间变得合适。过高的P参数会导致系统振荡,过低的P参数会导致系统响应慢。
接着,增加I参数,以减小稳态误差。适当调整I参数,直到系统达到满意的性能。
最后,增加D参数,以降低系统的超调量和提高响应速度。适当调整D参数,直到系统达到满意的性能。
假设我们需要控制一个直流减速电机的速度,为了达到某个设定值。我们将使用PID控制器来调节电机的驱动PWM,来达到所需的速度。

简要步骤如下:

初始化参数:首先将Kp,Ki,Kd全部设置为0,这样PID控制器不产生任何控制作用。
调节比例增益Kp:逐渐增加Kp的值,直到系统开始出现持续的振荡(速度在设定值附近上下波动)。此时记录下Kp的值。
调节积分增益Ki:将Kp设置为刚刚Kp值的一半,然后逐渐增加Ki的值,直到系统的静态误差(速度与设定值的差距)变得很小。过大的Ki值可能导致系统响应过慢或振荡,此时需要适当减小Ki值。
调节微分增益Kd:保持当前的Kp和Ki值不变,逐渐增加Kd的值,直到系统的动态性能满足要求(例如,要求速度在设定值附近的波动范围和响应时间)。过大的Kd值可能导致系统响应过于敏感或噪声敏感,此时需要适当减小Kd值。
微调参数:以上步骤得到的Kp,Ki,Kd值可能仍然不是最优解,因此还需要根据实际系统的性能要求进行微调。通常情况下,可以先调整Kp和Ki,然后再调整Kd。在调整过程中,需要关注系统的稳定性、阻尼、响应速度、过冲等性能指标。

电机的定速PID调参过程
三个静态参数影响什么?
这里就以恒温热水壶来举例说明了。

Kp(比例增益)

比例项是误差与控制器输出之间的线性关系。增大Kp会使系统响应速度更快,但可能会导致更大的过冲和振荡。减小Kp可以减少过冲和振荡,但会降低响应速度,甚至导致系统无法达到设定点(静态误差)。

以恒温热水壶为例,如果比例增益Kp设置得较大,当温度偏离设定点时,恒温热水壶会迅速地增加或减少加热功率。这可能导致温度在设定点附近发生过冲和振荡。而较小的Kp值可以减少过冲和振荡,但恒温器对温度偏差的响应速度会变慢。

Ki(积分增益)

积分项考虑了误差的累积效应,可以消除静态误差。增大Ki可以加快误差积分,使系统更快地达到设定点,但过大的Ki会导致积分过程过于敏感,引起系统的振荡和不稳定。

在上面恒温热水壶示例中,如果存在静态误差(即使加热持续了很久,温度仍无法达到设定点),可以通过增大积分增益Ki来消除这种静态误差,让水壶的加热功率再大一些。然而,过大的Ki值可能会导致恒温器对温度波动过于敏感,从而引起系统的振荡。

Kd(微分增益)

微分项关注误差的变化速度,可以预测系统的未来行为。增大Kd可以提高系统的阻尼性能,减小过冲和振荡,但过大的Kd会导致系统对噪声过于敏感,引入不稳定性。

在恒温热水壶示例中,如果系统在接近设定点时出现过冲和振荡,可以通过增大微分增益Kd来减小这些现象。微分项可以预测系统的未来行为,从而提前调整加热功率。然而,过大的Kd值可能会使恒温器对温度噪声过于敏感,从而影响系统的稳定性。

使用PID实现定速闭环控制
为了让电机的速度达到目标的速度,我们需要知道怎么获取电机的当前速度。而在之前的编码器驱动章节,我们就已经实现了电机的速度获取是 get_encoder_count()。

我们将目标速度,和当前编码器采集到的实时速度传入PID控制器中,PID控制器计算完后输出结果,我们再将结果给电机,而在电机驱动章节,我们就已经实现了电机的控制是 set_motor。

定速闭环控制框图
实现的代码:

/************************************************
功能:PID电机定速控制器
参数:target_speed = 目标值
返回:对应PID的地址
************************************************/
PID motor_speed_control(int target_speed)
{
int PWM;
//传入PID静态参数、目标值(目标速度)、当前值(当前编码器获取的实时速度)
//PID输出的值为控制信号,传入到PWM变量中
PWM = pid_calc( &speed_pid, target_speed, get_encoder_count() );
//控制信号转为电机实际控制值
if( PWM > 0 )//控制信号大于0
{
set_motor(0, PWM);//顺时针旋转,pwm为旋转速度
}
else if( PWM < 0 )
{
PWM = -PWM;//将负数转为正数(例如PWM=-10,则-(-10)=10)
set_motor(PWM, 0);//逆时针旋转,pwm为旋转速度
}
return speed_pid;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
需要注意一个问题,电机是PWM驱动的,PWM的范围是09999。我们将PID控制器输出的正负值或者小数点等结果都转为 PWM 的09999的范围,这样电机才能够转动。正负值或者小数点的处理上面的功能函数 PID motor_speed_control(int target_speed) 已经实现了,但是如果PID计算的值超过了PWM的最大值 9999 了怎么办?所以我们还需要限制。

/************************************************
功能:初始化PID各参数
参数:pid = 对应pid的结构体地址
p = pid的静态kp值
i = pid的静态ki值
d = pid的静态kd值
maxI = pid计算后的I最大值,即最大误差累加值
maxOut = PID最大输出值
target = 目标值
***********************************************/
void pid_init(PID
pid, float p, float i, float d, float maxI, float maxOut, int target)
{
pid->kp = p;
pid->ki = i;
pid->kd = d;
pid->max_change_i = maxI;
pid->max_output = maxOut;
pid->target = target;
}

....

void main(void)
{
//传入speed_pid地址
//设定 kp 为35
//设定 ki 为6
//设定 kd 为10
//设定 I的最大值 为9999
//设定 PID最大输出值 为9999
//设定 目标值 为 98
pid_init(&speed_pid, 35, 6, 10, 9999, 9999, 98);

while(1)
{
//实现定速功能
motor_speed_control( speed_pid.target );
}
}

设计图

未生成预览图,请在编辑器重新保存一次

BOM

暂无BOM

3D模型

序号文件名称下载次数
暂无数据

附件

序号文件名称下载次数
1
v1.0.0_easy-pid-kit.hex
1
2
637fd12d282a4d669f7a473c45444052.mp4
2
克隆工程
添加到专辑
0
0
分享
侵权投诉
知识产权声明&复刻说明

本项目为开源硬件项目,其相关的知识产权归创作者所有。创作者在本平台上传该硬件项目仅供平台用户用于学习交流及研究,不包括任何商业性使用,请勿用于商业售卖或其他盈利性的用途;如您认为本项目涉嫌侵犯了您的相关权益,请点击上方“侵权投诉”按钮,我们将按照嘉立创《侵权投诉与申诉规则》进行处理。

请在进行项目复刻时自行验证电路的可行性,并自行辨别该项目是否对您适用。您对复刻项目的任何后果负责,无论何种情况,本平台将不对您在复刻项目时,遇到的任何因开源项目电路设计问题所导致的直接、间接等损害负责。

底部导航