快速入门PID控制器(单片机控制类)

PID控制器是工业控制和电机控制的基础,本文介绍了PID的原理,包括比例(P)、积分(I)和微分(D)三部分。通过举例说明PID如何稳定车速,从P控制器到PD、PID控制器的演变过程,阐述了积分和微分在抑制震荡、适应不同路况中的作用。同时,文章还展示了简单的单片机PID控制代码片段。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言pid是一种传统控制理论,现代的工业控制或者一般的电机控制都需要PID控制器,尤其在RoboMaster的赛场上pid更是常见,因此学习pid是打好RoboMaster比赛的关键。
  • 一、pid是什么?
  • 二、pid原理
  • 总结


前言

pid非常常用,学习pid对于日常控制电机等其他东西有很大帮助,以下是我自己对于PID控制的看法,以下内容涉及单片机定时器,你看的代码段会很多,其实只有最后一段有用。前面都是推导和改进

一、pid是什么?

pid(Proportional Integral Derivative)即  比例(p)  积分(i)  微分(d)

大家看到积分微分感觉这个和高数密切联系,其实不是。走在前面,和大家说一下,积分就是一个个加起来,就是高中说的求和。微分就是求导数。

二:pid原理

首先我们假设一个人在开车,这个人希望把车速开到50km/h,当他起步的时候,车速离目标速度(50km/h)差得很多,这个时候就需要把油门加得很大。当车速离目标速度差不多时,我们是不是应该把油门加得小一点。这个就是pid中的P的作用和原理,其实p就是实际和目标的差值。差得越大P越大。在程序中我们是这样实现的,以下是pid的雏形代码,其中kp是我们用来手动调节pid输出量的,kp越大,相同差值下pid输出的量更大。

float kp=0.9;//定义差值比例
int speed=0;//定义实时速度,这里先定义一个0,它的数值是通过反馈的数据得来的,比如仪表盘得来的速度
int want_speed=50;//定义想要的速度
int speed_erro=0;//定义速度的差
int pid_out=0;//定义pid输出的量

speed_erro=want_speed-speed;//想要的速度减去实际的速度得到速度差
pid_out=kp*speed_erro;//得到pid输出

这个pid是有缺陷的,准确的说这个不是pid而是p控制器。它的缺陷很明显,当我们的速度差比较大的时候,这个控制器将会输出一个非常大的量。用回刚才开车的例子,这个司机看到速度差得太多,于是猛地加油门,由于他加的太快了,速度快要到目标速度(50km/h)时候,加速度非常大,这个时候车速就超过目标速度很多了,司机看到速度快这么多,于是踩下刹车(速度差越大,刹车踩得越急)。又因为踩得太急,速度降得太快,司机看到速度太慢了,又猛地加大油门.....一直这样震荡下去,这个就是p控制器的不足。我们应该怎么解决呢?很简单,我们让司机不要一下踩这么大油门和刹车就可以了,于是我们引入的d控制器。d控制器的作用相当与弹簧的阻尼,它可以抑制我们刚刚说的震荡,让车速趋于稳定。d是微分,就是把速度就行求导,速度的求导就是加速度。求加速度想要前后两次速度,而且求导得有时间。我们应该怎么办呢?很简单,我们可以使用定时器中断来获取前后两次速度,还有中间间隔的时间。我先介绍一种获取前后速度的算法:

int i=0;

switch(i)
{
	case(0):语句a1;语句a2;break;
	case(1):语句b1;语句b2;i=0;break;
}
i++;
 

当i=0时候执行语句a1,语句a2,执行完毕后i自增由0变为1;当进行下一轮循环的时候执行语句b1,语句b2,并且i变0(把0赋给i),由此一直循环下去。

于是我们可以这样:这里写了一个定时器的伪代码

int i=0;
int speed=0;
int first_speed=0;
int second_speed=0;

void 定时器中断函数()
{
switch(i)
{
	case(0):first_speed=speed;break;
	case(1):second_speed=speed;i=0;break;
}
i++;
}

于是我们结合之前的p控制器我们就得到了以下pd控制器

//以下是之前p控制器定义的参数
float kp=0.9;//定义差值比例
int speed=0;//定义实时速度,这里先定义一个0,它的数值是通过反馈的数据得来,比如仪表盘得来的速度
int want_speed=50;//定义想要的速度
int speed_erro=0;//定义速度的差
int pid_out=0;//定义pid输出的量

//以下是d控制器新定义的参数
float Kd=0.2;//定义微分比例
int first_speed=0;//定义第一次采取的速度的值
int second_speed=0;//定义第二次采取的速度的值
int a=0//定义加速度
int i=0;//定义变量i

void 定时器中断函数()
{
speed_erro=want_speed-speed;//想要的速度减去实际的速度得到速度差
a=second_speed-first_speed;//第二次速度减去第一次速度得到加速度
switch(i)
{
	case(0):first_speed=speed;break;
	case(1):second_speed=speed;i=0;pid_out=kp*speed_erro+kd*a;break;
    
}
i++;
}

这样的pd控制器可以在水平路段保持目标速度了

这样还不完美

我们刚刚讲了,司机加的油门会随着速度差值的减小而减小。但是当汽车在上坡的时候会怎么样?没错!就是司机的速度会始终小于目标速度(50km/h)。这个时候,如果我们可以告诉司机,你应该继续加点油才可以到达目标速度,而且要不断观察速度,每次少于目标速度,都要再加一点油。那么我们就基本可以在任何路段都可以保持目标速度了。以下是我们的最终代码了

//以下是之前p控制器定义的参数
float kp=0.9;//定义差值比例
int speed=0;//定义实时速度,这里先定义一个0,它的数值是通过反馈的数据得来,比如仪表盘得来的速度
int want_speed=50;//定义想要的速度
int speed_erro=0;//定义速度的差
int pid_out=0;//定义pid输出的量
float Kd=0.2;//定义微分比例
int first_speed=0;//定义第一次采取的速度的值
int second_speed=0;//定义第二次采取的速度的值
int a=0//定义加速度
int i=0;//定义变量i

//以下是定义新增的参数
float ki=0.1;
int second_erro=0;//定义第二次的差值
int integral=0//定义积分

void 定时器中断函数()
{
speed_erro=want_speed-speed;//想要的速度减去实际的速度得到速度差
a=second_speed-first_speed;//第二次速度减去第一次速度得到加速度

switch(i)
{
	case(0):first_speed=speed;break;
	case(1):second_speed=speed;second_erro=want_speed-speed;i=0;integral+=(second_erro-erro);pid_out=kp*speed_erro+kd*a;break;
    
}
i++;
}

代码如下(示例):

data = pd.read_csv(
    'https://labfile.oss.aliyuncs.com/courses/1283/adult.data.csv')
print(data.head())

该处使用的url网络请求的数据。


总结

提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Golden只喝白兰地

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值