打印
[程序源码]

适用于单片机的简单易懂的 PID 计算函数与 C 代码

[复制链接]
1007|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
panxiaoyi|  楼主 | 2022-10-2 11:04 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

#include "stdio.h"

int dat;
int goal=180;                                                //设定值
int now;                                                     //现在值
int gap[3];                                                  //缓存,最少3个成员

int Pid(unsigned char P, unsigned char I, unsigned char D, int goal, int now, int *gap) //P/I/D系数,目标值,现在值,缓存
{
        gap[2]=gap[1];
        gap[1]=gap[0];
        gap[0]=goal-now;                                                                    //负反馈式PID
        //gap[0]=now-goal;                                                                  //正反馈式PID。这2条语句请2选1

        return (P*(gap[0]-gap[1])+I*gap[0]+D*(gap[0]-gap[1]-gap[1]+gap[2]));                //PID计算公式
}

int main()                                                   //以下的是测试代码
{
        while(1)                                                 //使用PID计算,请注意要定时定点的采集测量数据才有效
        {
                printf("请输入当前温度\n");                          //提示字符
                scanf("%3d[0-9]",&now);                              //从键盘获取最多3个0-9的字符,然后转化为十进制,再赋值给变量
                scanf("%*[^\n]%*c");                                 //清空输入缓存,等同于非标准的fflush(stdin)
                dat=Pid(9,8,7,goal,now,gap);                         //PID计算
                printf("当前的温度=%d,PID计算结果=%d,",now,dat);   //输出原始值
                if(dat<0) dat=0; if(dat>255) dat=255;                //计算结果限幅
                printf("PWM占空比=%d/255\n\n",dat);                  //输出PWM调整参数
        }
}

/*
调试结果:

请输入当前温度
150
当前的温度=150,PID计算结果=720,PWM占空比=255/255

请输入当前温度
175
当前的温度=175,PID计算结果=-570,PWM占空比=0/255

请输入当前温度
176
当前的温度=176,PID计算结果=191,PWM占空比=191/255

请输入当前温度
ADCD
当前的温度=176,PID计算结果=39,PWM占空比=39/255

请输入当前温度
18234
当前的温度=182,PID计算结果=-112,PWM占空比=0/255
*/


001.rar

895 Bytes

使用特权

评论回复
沙发
LcwSwust| | 2022-10-2 11:14 | 只看该作者
你这增量式的公式,怎么是位置式的用法。

使用特权

评论回复
板凳
panxiaoyi|  楼主 | 2022-10-2 16:20 | 只看该作者
LcwSwust 发表于 2022-10-2 11:14
你这增量式的公式,怎么是位置式的用法。

你的意思是下面的做法才是合适的,是吗?有空我测试看看
dat=Pid(9,8,7,goal,now,gap);
修改成
dat+=Pid(9,8,7,goal,now,gap);


使用特权

评论回复
地板
LcwSwust| | 2022-10-2 18:12 | 只看该作者
panxiaoyi 发表于 2022-10-2 16:20
你的意思是下面的做法才是合适的,是吗?有空我测试看看

是的,假如设定值与目标值一直是固定的误差,原来的用法输出值是一直不变的,修改后才是正确的,输出会逐渐变化。

使用特权

评论回复
5
uant| | 2022-10-4 09:35 | 只看该作者
感谢分享,不过计算过程还是不太懂

使用特权

评论回复
6
panxiaoyi|  楼主 | 2022-10-4 10:32 | 只看该作者
uant 发表于 2022-10-4 09:35
感谢分享,不过计算过程还是不太懂
本次差距 = 目标值 - 测量值   //适合输出结果越大,输出功率越大
本次差距 = 测量值 - 目标值   //适合输出结果越大,输出功率越小

输出值 = 上次输出值 + P x (本次差距 - 上次差距) + I x 本次差距 + D x ((本次差距 - 上次差距) - (上次差距 - 上上次差距))


使用特权

评论回复
7
panxiaoyi|  楼主 | 2022-10-4 10:39 | 只看该作者
scanf("%*[^\n]%*c");  //清空输入缓存,清空电脑接受键盘的缓存,与PID计算没有任何关系


使用特权

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

本版积分规则

49

主题

393

帖子

2

粉丝