增量式and位置式PID程序实现(内含详细注释)

你好!这里是风筝的博客,

欢迎和我一起交流。


又是一年电赛时节。控制类必不可少的PID算法:
我也是从网上整理而来的:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <string.h>


typedef struct {
    float SetValue; //用户期望值,也就是我们期望系统调节到输出此值然后稳定在这一状态
    float pid_Calc_out; //PID计算输出结果值,用来驱动执行机构
    float error; //当前偏差值
    float error_last; //上一次计算的偏差值
    float error_pre; //上上一次计算的偏差值,在增量式里用到
    float Kp; //比例系数
    float Ki; //积分系数
    float Kd; //微分系数
    float integral; //积分值
}PID;//结构体,方便管理

/*
初始化PID控制器的一些参数
入口参数是PID结构体指针
*/
void PID_Init(PID *pPID)
{
    pPID->SetValue=0.0f;    // 期望值设置为0
    pPID->pid_Calc_out=0.0f;//PID控制器输出设置为0
    pPID->error=0.0f;//当前偏差值设置为0
    pPID->error_last=0.0f;//上次偏差设置为0
    pPID->error_pre=0.0f;//上上次偏差设置为0
    pPID->integral=0.0f;//积分值设置为0
    pPID->Kp=0.08f;//比例系数设置为0.08 
    pPID->Ki=0.01f;//积分系数设置为0.01
    pPID->Kd=0.2f;//微分系数设置为0.2
}

/*
位置式PID运算核心,输入参数pPID_Calc是类型为PID结构的结构体指针,Next_val是用户期望系统调节到输出此值然后稳定在这一状态的设定值,
返回值即为PID运算输出的结果。
*/
float PID_Calc(PID *pPID_Calc,float Next_val,float actual)//位置式
{
    pPID_Calc->SetValue=Next_val;//把用户期望值赋给PID控制器的用户设定值

    pPID_Calc->error=pPID_Calc->SetValue-actual;//期望值减去当前值,得到当前偏差

    pPID_Calc->integral+=pPID_Calc->error;
    //PID积分运算,此处没有作积分限幅处理,是为了完全与数学公式相同,运用到实际的系统需要做积分限幅处理,防止积分饱和。
    //当系统存在一个方向的误差时,由于积分的累加作用会使控制量一直增大,可能会使控制量达到执行器的执行阈值,
    //如果此时误差方向还是没有改变,控制量会继续增大但是执行器会一直保持在阈值,此时控制量就进入了饱和区。
    //进入饱和区越深,退出饱和区时间就会越长,在饱和区时执行器会一直在阈值位置,如果误差发生反向,执行器不会立刻有反应,控制量会慢慢减小,
    //等执行器推出饱和区才会有反应。这样就会使控制的动态响应变差,控制性能变差。
    //所以必须防止积分饱和


    pPID_Calc->pid_Calc_out=(pPID_Calc->Kp*pPID_Calc->error)/* 当前偏差*比例系数Kp */+

        (pPID_Calc->Ki*pPID_Calc->integral)/* 积分*积分系数Ki */+

        pPID_Calc->Kd*(pPID_Calc->error-pPID_Calc->error_last)/* (当前偏差-上次偏差)*微分系数 */;

    //当前偏差*比例系数Kp + 积分*积分系数Ki + (当前偏差-上次偏差)*微分系数 结果就是PID控制器的输出
//pwm=Kp*e(k)+Ki*∑e(k)+Kd[e(k)-e(k-1)]
    pPID_Calc->error_last=pPID_Calc->error;
    //PID运算完一次后,当前偏差作为下一次偏差的上次偏差保存到pPID_Calc->error_last

    return (pPID_Calc->pid_Calc_out*1.0f);//输出PID运算结果。
}


float PID_ADJ(PID *pPID_Calc,float Next_val)//增量式,只和最近三次偏差有关
{
    float Out;
    pPID_Calc->SetValue=Next_val;//把用户期望值赋给PID控制器的用户设定值

    //得到增量
    Out =( pPID_Calc->Kp*(pPID_Calc->error-pPID_Calc->error_last))  +
        (pPID_Calc->Ki*pPID_Calc->error)    +
        pPID_Calc->Kd*(pPID_Calc->error-2*pPID_Calc->error_last+pPID_Calc->error_pre);

    pPID_Calc->error_pre = pPID_Calc->error_last;

    pPID_Calc->error_last=pPID_Calc->error;
    //PID运算完一次后,当前偏差作为下一次偏差的上次偏差保存到pPID_Calc->error_last

    pPID_Calc->pid_Calc_out+=Out;
    return (pPID_Calc->pid_Calc_out);
}

  • 7
    点赞
  • 93
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值