PID学习笔记

PID学习笔记

PID三个参数的含义

KP比例环节

产生震荡(主导作用)

首先要设置一个输出限幅【一定要加】:限制电机输出的最大值(输出的最大力)

KI  积分环节

消除稳态误差(恒定误差)积分环节-时间的累加

KD 微分环节

为了减小KP产生的剧烈震荡,微分环节求导

PID具体调节时候的先后顺序

先将所有参数置

将输出限幅设为最大值

增大p参数,使响应速度达到比较好的水平

逐渐增加d参数,在保证响应速度的前提下尽可能降低超调或震荡

逐渐增加i参数和积分限幅,使稳态误差消失

串级调参:需要先断开两环的连接(将外环注释掉),手动指定内环目标值,进行内环调参,当内环控制效果较好后再接上外环进行外环调参

具体调节的一些细节:

积分限幅一般比输出限幅小一点
如果最后小车不能停在目标位置需要加低通滤波

 

PID代码:

外环目标值:需要电机达到的角度

外环反馈值:电机的实时角度

内环反馈值:电机的实时速度

输出值:电机电流大小

typedef struct

{

         float kp, ki, kd; //三个系数

    float error, lastError; //误差、上次误差

    float integral, maxIntegral; //积分、积分限幅

    float output, maxOutput; //输出、输出限幅

}PID;

 typedef struct

{

    PID inner; //内环

    PID outer; //外环

    float output; //串级输出,等于inner.output

}CascadePID;

 

//用于初始化pid参数的函数

void PID_Init(PID *pid, float p, float i, float d, float maxI, float maxOut)

{

    pid->kp = p;

    pid->ki = i;

    pid->kd = d;

    pid->maxIntegral = maxI;

    pid->maxOutput = maxOut;

}

 

//进行一次pid计算

//参数为(pid结构体,目标值,反馈值),计算结果放在pid结构体的output成员中

void PID_Calc(PID *pid, float reference, float feedback)

{

    pid->lastError = pid->error;

    pid->error = reference - feedback; //计算新error=目标值-反馈值

    float dout = (pid->error - pid->lastError) * pid->kd;//微分

    float pout = pid->error * pid->kp;//比例

    pid->integral += pid->error * pid->ki;//积分

    //积分限幅

    if(pid->integral > pid->maxIntegral) pid->integral = pid->maxIntegral;

    else if(pid->integral < -pid->maxIntegral) pid->integral = -pid->maxIntegral;

    pid->output = pout+dout + pid->integral;//输出

    //输出限幅

    if(pid->output > pid->maxOutput) pid->output =   pid->maxOutput;

    else if(pid->output < -pid->maxOutput) pid->output = -pid->maxOutput;

}

//参数(PID结构体,外环目标值,外环反馈值即内环目标值,内环反馈值)

 

 void PID_CascadeCalc(CascadePID *pid, float outerRef, float outerFdb, float innerFdb)

{

    PID_Calc(&pid->outer, outerRef, outerFdb); //计算外环

    PID_Calc(&pid->inner, pid->outer.output, innerFdb); //计算内环

    pid->output = pid->inner.output; //内环输出就是串级PID的输出

}

CascadePID mypid = {0}; //创建串级PID结构体变量

int main()

{

    PID_Init(&mypid.inner, 10, 0, 0, 0, 1000); //初始化内环参数

    PID_Init(&mypid.outer, 5, 0, 5, 0, 100); //初始化外环参数

    while(1) //进入循环运行

    {

        float outerTarget = ...; //获取外环目标值

        float outerFeedback = ...; //获取外环反馈值

        float innerFeedback = ...; //获取内环反馈值

        PID_CascadeCalc(&mypid, outerTarget, outerFeedback, innerFeedback); //进行PID计算

        设定执行机构输出大小(mypid.output);

        delay(10); //延时一段时间

    }

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值