打印
[STM32F1]

STM32F103C8T6实现直流电机速度PID控制

[复制链接]
736|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
前言
前面完成了基于STM32F103C8T6+L298N+MG513P30直流电机的PWM控制和两种方法的编码器实时速度反馈,拿到这个反馈值后我们就可以使用经典的PID算法,对电机的转速进行准确的控制了,这篇文章主要分享PID基本原理和Keil5的PID编程。

一、PID的基本原理
PID算法是上个世纪30年代左右提出的控制算法,大至航空航天、小至家庭温度调控都可以使用PID算法,虽然PID算法从提出到现在已经历经了快一个世纪,其后也出现了很多现代的智能算法,比如蒙特卡洛、智能控制等等,但现在PID仍然经久不衰,可以说目前80%以上的控制仍然使用PID算法。

PID算法是自动控制原理课程学习的一部分,但在课程中老师讲解的是最基本的原理,没有任何拓展,更别提应用了,首先,先简单说一下PID控制算法的原理。


上图为PID算法的控制框图,在我们控制电机速度时,期望输入就是电机的期望速度值,期望输入与由编码器测得的实际速度作差,求出的误差值传给PID的控制部分,算出需要输出的控制信号,将该控制信号传给控制器,也就是输出给电机驱动板L298N,这样形成一个循环,就实现了对电机速度的精准控制。

使用特权

评论回复
评论
梅花香自123 2023-7-23 16:51 回复TA
———————————————— 版权声明:本文为CSDN博主「K.Fire好好睡觉」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/qq_52785580/article/details/123002248 
沙发
梅花香自123|  楼主 | 2023-7-23 16:52 | 只看该作者
中间PID的控制部分的连续型公式如下:

使用特权

评论回复
板凳
梅花香自123|  楼主 | 2023-7-23 16:52 | 只看该作者
但是在计算机中计算机很难实现连续型变量的积分或者微分操作,因此在计算机中,我们使用离散型的积分和微分,就是取时间间隔T为1,离散型PID公式如下:

使用特权

评论回复
地板
梅花香自123|  楼主 | 2023-7-23 16:52 | 只看该作者
各个项的主要作业及效果如下:

P:增加快速性,过大会引起震荡和超调,P单独作用会一直有静态误差
I:减少静态误差,过大会引起震荡
D:减小超调,过大会使响应速度变慢
在实际的应用中,有可能不需要PID同时使用,比如在速度控制中一般只使用PI控制就够了,各种各样的PI、PD控制大家可以去B站或者看其他博主的博客,已经讲的很详细了。

使用特权

评论回复
5
梅花香自123|  楼主 | 2023-7-23 16:53 | 只看该作者
变式PID
PID算法有很多进化版本,分类别的简单阐述一下

增量式PID

在电机的速度PID控制算法中,因为我们一般使用PI算法就够了,所以我们可以使用增量式PID算法,这样可以让我们的公式和代码更加简洁。

使用特权

评论回复
6
梅花香自123|  楼主 | 2023-7-23 16:54 | 只看该作者
积分限幅

因为积分的效果是累加,随着时间的推移,积分项的值会升到很高,积分本来的作用是用来减小静态误差,但积分项过大会引起过大的震荡,所以我们可以加一个判断函数if,当积分项的值达到一定值后,就让积分项保持这个值,避免引起更大的震荡。

使用特权

评论回复
7
梅花香自123|  楼主 | 2023-7-23 16:54 | 只看该作者
积分分离

如果刚开始的误差比较大,那么积分项则会在刚开始就累计到了一个很大的数值,那么当第一次实际输出达到期望值时,不会立刻停止,而是会产生一个很大的过冲。这时就需要用到积分分离,就是当误差值过大时,我们就不使用积分项,只让PD项单独作用,当误差值较小后,在加入积分项,以减小静态误差。

使用特权

评论回复
8
梅花香自123|  楼主 | 2023-7-23 16:55 | 只看该作者
Keil5程序
为了使用方便,我们先定一个PID结构体,结构体储存左右轮的PID参数、限幅值、误差等参数。

typedef struct
{
         //相关速度PID参数
        float Velcity_Kp;
        float Velcity_Ki;
        float Velcity_Kd;
        float Ur;                                //限幅值
       
        u8 PID_is_Enable;                //PID使能
        int Un;                                        //期望输出值
        int En_1;                                //上一次的误差值
        int En_2;                                //上上次的误差值
        int PWM;                                //输出PWM值
       
}PID_InitDefStruct;

使用特权

评论回复
9
梅花香自123|  楼主 | 2023-7-23 16:55 | 只看该作者
在程序初始化部分,定义一个初始化函数,对其中的参数进行初始化配置。
void PID_Init(PID_InitDefStruct* p)
{
        p->Velcity_Kp = 5;
        p->Velcity_Ki = 0.5;
        p->Velcity_Kd = 0;
        p->Ur = 7100;
        p->PID_is_Enable = 1;
        p->Un = 0;
        p->En_1 = 0;
        p->En_2 = 0;
        p->PWM = 0;
}

使用特权

评论回复
10
梅花香自123|  楼主 | 2023-7-23 16:55 | 只看该作者
当编码器的定时器,每隔10ms反馈一次编码器测出的实际速度后,调用PID函数,求解输出给电机驱动板的PWM值,然后通过Set_Pwm函数进行设置,以此控制电机转速。
void Velocity_PID(int TargetVelocity,int CurrentVelocity,PID_InitDefStruct* p)
{
        if(p->PID_is_Enable == 1)
        {
                int En = TargetVelocity - CurrentVelocity;//误差值                                                     
       
                p->Un += p->Velcity_Kp*(En - p->En_1) + p->Velcity_Ki*En + p->Velcity_Kd*(En - 2*p->En_1 + p->En_2);//增量式PID
               
                p->En_2=p->En_1;
                p->En_1=En;
               
                p->PWM = p->Un;
               
                /*输出限幅*/
                if(p->PWM>p->Ur) p->PWM=p->Ur;
                if(p->PWM<-p->Ur) p->PWM=-p->Ur;
        }
        else
        {
                PID_Init(p);
        }
       
}

使用特权

评论回复
11
梅花香自123|  楼主 | 2023-7-23 16:56 | 只看该作者
测试给电机输入理想转速为1500mm/s,随便设置了一组PI参数,得到实验结果如下:

2794364bceb3e3abe8.png (164.83 KB )

2794364bceb3e3abe8.png

使用特权

评论回复
12
梅花香自123|  楼主 | 2023-7-23 16:57 | 只看该作者
可以通过上位机看一下波形,可以看到在稳定状态的静差是比较小的

使用特权

评论回复
13
梅花香自123|  楼主 | 2023-7-23 16:57 | 只看该作者
总结
对于PID算法这才是****的第一步吧,想要调出完美地控制程序,还需要复杂的PID参数整定,这里可以配合上位机进行调试,以后调出来在分享。

使用特权

评论回复
14
周半梅| | 2023-12-29 08:03 | 只看该作者

对于没有else的场景,使用ifPresent即可

使用特权

评论回复
15
Pulitzer| | 2023-12-29 09:06 | 只看该作者

每个Strategy交由Spring管理,并在构造后注册

使用特权

评论回复
16
童雨竹| | 2023-12-29 11:02 | 只看该作者

使用Optional简化if判空

使用特权

评论回复
17
Wordsworth| | 2023-12-29 12:05 | 只看该作者

不同的代码逻辑就代表了不同的策略

使用特权

评论回复
18
Clyde011| | 2023-12-29 13:08 | 只看该作者

对于优秀程序员来说,这不是好代码

使用特权

评论回复
19
公羊子丹| | 2023-12-29 14:01 | 只看该作者

通过对判断条件取反,代码在逻辑表达上会更加清晰

使用特权

评论回复
20
万图| | 2023-12-29 15:04 | 只看该作者

会以switch-case的方式出现

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

92

主题

1059

帖子

0

粉丝