panxiaoyi 发表于 2022-10-2 11:04

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


#include "stdio.h"

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

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

        return (P*(gap-gap)+I*gap+D*(gap-gap-gap+gap));                //PID计算公式
}

int main()                                                   //以下的是测试代码
{
        while(1)                                                 //使用PID计算,请注意要定时定点的采集测量数据才有效
        {
                printf("请输入当前温度\n");                        //提示字符
                scanf("%3d",&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
*/

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
你的意思是下面的做法才是合适的,是吗?有空我测试看看

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

uant 发表于 2022-10-4 09:35

感谢分享,不过计算过程还是不太懂

panxiaoyi 发表于 2022-10-4 10:32

uant 发表于 2022-10-4 09:35
感谢分享,不过计算过程还是不太懂

本次差距 = 目标值 - 测量值   //适合输出结果越大,输出功率越大
本次差距 = 测量值 - 目标值   //适合输出结果越大,输出功率越小

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

panxiaoyi 发表于 2022-10-4 10:39

scanf("%*[^\n]%*c");//清空输入缓存,清空电脑接受键盘的缓存,与PID计算没有任何关系

页: [1]
查看完整版本: 适用于单片机的简单易懂的 PID 计算函数与 C 代码