精华内容
下载资源
问答
  • 代码是基于STM32F103ZET6和编码器直流电机编写的,增量式PID控制电机转动速度的程序,并且是基于正点原子代码格式编写的,对于初学者有重要的参考研究意义。本代码工程书写规范,带有注释,分程序块编写。本人测试...
  • 非常实用的 增量式PID算法PDF文档+MATLAB源程序,完全测试通过
  • PID的C语言例程
  • 位置式PID与增量式PID代码实现(python一、PID控制器简介二、一阶惯性环节三、位置式PID3.1 简介3.2 python程序四、增量式PID4.1简介4.2 python程序五、几种控制效果对比 一、PID控制器简介 PID(P比例,I积分,D微分)...

    本文只展示部分代码,完整代码请访问我的github

    一、PID控制器简介

    PID(P比例,I积分,D微分)是一种model free的控制器,使用该控制器,无需对控制系统进行建立模型,只需对P、I 、D这三个参数进行调整即可,使用起来十分方便,因此在控制系统中被广泛使用。

    水温PID控制系统
    u ( t ) = K p e ( t ) + K i ∫ 0 t e ( t ) d t + K d d e ( t ) d t (1) u(t) = K_pe(t) + K_i\int_{0}^{t} e(t)dt +K_d\frac{de(t)}{dt} \tag{1} u(t)=Kpe(t)+Ki0te(t)dt+Kddtde(t)(1)

    • 积分项有助于消除稳态误差
    • 微分项有助于加快系统相应
    • PD控制:提高稳定性,改善瞬态响应
    • PI控制:改善稳态误差

    二、一阶惯性环节

    以下的代码中将用一阶惯性环节作为被控对象来进行展开。此处简单介绍一下一阶惯性系统。
    一阶惯性环节(系统)比较常见,如单容水箱、电容等含有储存元件或容量的元件系统,该系统输出一开始并不与输入同步按比例变化,直到过渡过程结束输出 y ( t ) y(t) y(t)才与输入 x ( t ) x(t) x(t)保持比例关系。

    • 运动方程:
      T d y ( t ) d t + y ( t ) = K x ( t ) T\frac{dy(t)}{dt} + y(t) = Kx(t) Tdtdy(t)+y(t)=Kx(t)
    • 传递函数
      G ( s ) = Y ( s ) X ( s ) = K T s + 1 G(s)= \frac{Y(s)}{X(s)} =\frac{K}{Ts +1} G(s)=X(s)Y(s)=Ts+1K
      其中T是时间常数,K是比例常数
    • 在数字控制系统中通常写为:
      T [ y ( k ) − y ( k − 1 ) ] + y ( k ) = K x ( k ) T\left[y(k)-y(k-1) \right]+ y(k) = Kx(k) T[y(k)y(k1)]+y(k)=Kx(k) ⇒ \Rightarrow y ( k ) = K x ( k ) + T y ( k − 1 ) 1 + T y(k)= \frac{Kx(k)+Ty(k-1)}{1+T} y(k)=1+TKx(k)+Ty(k1)

    三、位置式PID

    3.1 简介

    在计算机控制系统中往往使用位置式PID算法与增量式PID算法。下面给出位置式PID的公式。
    u ( k ) = K p e ( k ) + K i ∑ i = 0 e ( i ) + K d [ e ( k ) − e ( k − 1 ) ] (2) u(k) = K_pe(k) + K_i\sum_{i=0} e(i) +K_d\left[e(k)-e(k-1) \right] \tag{2} u(k)=Kpe(k)+Kii=0e(i)+Kd[e(k)e(k1)](2)
    从公式可以看出,这就是对式(1)的直接数字化,容易理解,输出u(k)便是PID控制器的输出位置。
    该控制器存在的缺点
    由于积分饱和带来的影响,控制器需要相当一段长的时间退出饱和区,由此引起系统产生大幅度超调。这里如果想继续了解积分饱和,请点击链接查看matlab官方的讲解。

    3.2 python程序

    #位置式PID系统
    class PositionalPID:
        def __init__(self, P: float, I: float, D: float):
            self.Kp = P
            self.Ki = I
            self.Kd = D
    
            self.PIDOutput = 0.0  # PID控制器输出
            self.SystemOutput = 0.0  # 系统输出值
            self.LastSystemOutput = 0.0  # 系统的上一次输出
    
            self.PIDErrAdd = 0.0
            self.ResultValueBack = 0.0
            self.Error = 0.0
            self.LastError = 0.0
    
        def SetStepSignal(self, StepSignal):
            self.Error = StepSignal - self.SystemOutput
    
            KpWork  = self.Kp *self.Error
            KiWork = self.Ki* self.PIDErrAdd
            KdWork = self.Kd * (self.Error- self.LastError)
            self.PIDOutput = KpWork + KiWork + KdWork
            self.PIDErrAdd += self.Error
            self.LastError = self.Error
    
            # 以一阶惯性环节为例子演示控制效果
    
        def SetInertiaTime(self, IntertiaTime, SampleTime):
            self.SystemOutput = (IntertiaTime * self.LastSystemOutput + SampleTime * self.PIDOutput) / (
                        SampleTime + IntertiaTime)
            self.LastSystemOutput = self.SystemOutput
    

    四、增量式PID

    4.1简介

    Δ u ( k ) = u ( k ) − u ( k − 1 ) = \Delta u(k) = u(k)-u(k-1)= Δu(k)=u(k)u(k1)=
    K p [ e ( k ) − e ( k − 1 ) ] + K i e ( k ) + K d [ e ( k ) − 2 e ( k − 1 ) + e ( k − 2 ) ] (3) K_p\left[e(k)-e(k-1) \right] + K_i e(k) +K_d\left[e(k)-2e(k-1)+e(k-2) \right] \tag{3} Kp[e(k)e(k1)]+Kie(k)+Kd[e(k)2e(k1)+e(k2)](3)
    增量式PID只求取控制量的变化量,一旦确定了 KP、TI 、TD,只要使用前后三次测量值的偏差, 即可由公式求出控制增量,而得出的控制量▲u(k)对应的是近几次位置误差的增量,而不是对应与实际位置的偏差,因此没有误差累加,容易通过加权处理获得比较好的控制效果,并且在系统发生问题时,增量式不会严重影响系统的工作
    最后的输出要加上上一时刻的输出u(k-1),即:
    u ( k ) = Δ u ( k ) + u ( k − 1 ) (4) u(k)= \Delta u(k)+u(k-1)\tag{4} u(k)=Δu(k)+u(k1)(4)

    4.2 python程序

    #增量式PID系统
    class IncrementalPID:
        def __init__(self, P:float ,I:float ,D:float ):
            self.Kp = P
            self.Ki = I
            self.Kd = D
    
            self.PIDOutput =0.0         #PID控制器输出
            self.SystemOutput = 0.0     #系统输出值
            self.LastSystemOutput = 0.0 #系统的上一次输出
    
            self.Error = 0.0
            self.LastError = 0.0
            self.LastLastError = 0.0
    
        #设置PID控制器参数
        def SetStepSignal(self,StepSignal):
            self.Error = StepSignal - self.SystemOutput
            #计算增量
            IncrementalValue = self.Kp*(self.Error - self.LastError)\
                + self.Ki * self.Error +self.Kd *(self.Error -2*self.LastError +self.LastLastError)
            #计算输出
            self.PIDOutput += IncrementalValue
            self.LastLastError = self.LastError
            self.LastError = self.Error
    
        #以一阶惯性环节为例子演示控制效果
        def SetInertiaTime(self,IntertiaTime,SampleTime):
            self.SystemOutput = (IntertiaTime*self.LastSystemOutput + SampleTime *self.PIDOutput)/(SampleTime + IntertiaTime)
            self.LastSystemOutput = self.SystemOutput
    

    五、几种控制效果对比

    上图!图中红色为增量式PID,蓝色为位置式PID,黑色是不加控制器的效果。
    在这里插入图片描述

    展开全文
  • 此源代码为stm32直流电机控制—PID算法篇的工程代码。包涵STM32单片机对直流电机转速的PID控制算法。创作实属不易,所有才受一点点费用下载,请谅解。详细介绍说明可观看本博主的博客——“stm32直流电机控制—PID...
  • 增量式PID算法的MATLAB实现

    千次阅读 多人点赞 2019-06-22 13:27:19
    增量式PID的MATLAB实现PID控制的分类连续PID控制离散PID控制位置式PID控制增量式PID控制位置式PID与增量式PID的比较离散PID控制的MATLAB实现实现增量式PID算法绘制GUI界面,实时更改给定值 PID控制的分类 连续PID控制...

    pdf和代码的下载地址: 增量式PID算法的MATLAB实现(访问密码:3834)

    PID控制的分类

    连续PID控制

    对模拟信号进行的模拟PID控制,也可以称作连续PID控制,其表达式为
    u ( t ) = K p [ e ( t ) + 1 T i ∫ 0 t e ( t )   d t + T d d e ( t ) d t ] (1.1) u(t) = K_p \left[ e(t) + \frac{1}{T_i} \int_0^t e(t) \, dt + T_d \frac{de(t)}{dt} \right] \tag{1.1} u(t)=Kp[e(t)+Ti10te(t)dt+Tddtde(t)](1.1)
    上式中, K p K_p Kp为比例系数, T i T_i Ti为积分时间常数, T d T_d Td为微分时间常数.对上式进行拉氏变换得到
    U ( s ) = K p [ E ( s ) + E ( s ) T i s + T d s E ( s ) ] (1.2) U(s) = K_p \left[ E(s) + \frac{E(s)}{T_i s} + T_d s E(s)\right] \tag{1.2} U(s)=Kp[E(s)+TisE(s)+TdsE(s)](1.2)
    PID控制器的传递函数为
    D ( s ) = U ( s ) E ( s ) = K p ( 1 + 1 T i s + T d s ) (1.3) D(s) = \frac{U(s)}{E(s)} = K_p \left( 1 + \frac{1}{T_i s} + T_d s \right) \tag{1.3} D(s)=E(s)U(s)=Kp(1+Tis1+Tds)(1.3)

    离散PID控制

    要对数字信号进行控制,我们要将其离散化,并进行离散PID控制,本质上就是对数字信号进行采样. 离散式PID根据采样方式不同,分为位置式PID控制增量式PID控制.

    位置式PID控制

    对连续PID控制以一定离散化方法离散后就可以得到数字PID控制,离散的本质是采样,假设采样为周期采样,采样周期为T,离散自变量为n,则离散PID控制可以表示为:
    u [ n ] = K p { e [ n ] + T T i ∑ i = 0 n e [ i ] + T d T { e [ n ] − e [ n − 1 ] } } (2.1) u[n] = K_p \left\{ e[n] + \frac{T}{T_i} \sum_{i=0}^n e[i] + \frac{T_d}{T} \left\{ e[n] - e[n-1]\right\} \right\} \tag{2.1} u[n]=Kp{e[n]+TiTi=0ne[i]+TTd{e[n]e[n1]}}(2.1)
    上式即为位置式PID控制的表达式

    增量式PID控制

    位置式PID控制表达式做差分,写出n-1时刻的控制量:
    u [ n − 1 ] = K p { e [ n − 1 ] + T T i ∑ i = 0 n − 1 e [ i ] + T d T { e [ n − 1 ] − e [ n − 2 ] } } (2.2) u[n-1] = K_p \left\{ e[n-1] + \frac{T}{T_i} \sum_{i=0}^{n-1} e[i] + \frac{T_d}{T} \left\{ e[n-1] - e[n-2]\right\} \right\} \tag{2.2} u[n1]=Kp{e[n1]+TiTi=0n1e[i]+TTd{e[n1]e[n2]}}(2.2)
    将式 ( 2.1 ) (2.1) (2.1)与式 ( 2.2 ) (2.2) (2.2)相减,得到

    Δ u [ n ] = u [ n ] − u [ n − 1 ] = K p { e [ n ] − e [ n − 1 ] } + K p T T i e [ n ] + K p T d T { e [ n ] − 2 e [ n − 1 ] + e [ n − 2 ] } (2.3) \begin{aligned} \Delta u[n] & = u[n] - u[n-1] \\ & = K_p \left\{ e[n] - e[n-1] \right\}+ \frac{K_p T}{T_i} e[n] + \frac{K_p T_d}{T} \left\{ e[n] -2 e[n-1] + e[n-2]\right\} \end{aligned} \tag{2.3} Δu[n]=u[n]u[n1]=Kp{e[n]e[n1]}+TiKpTe[n]+TKpTd{e[n]2e[n1]+e[n2]}(2.3)

    K i = K p T T i K_i= K_p \frac{T}{T_i} Ki=KpTiT为积分系数, K d = K p T d T K_d = K_p \frac{T_d}{T} Kd=KpTTd为微分系数,可将上式简化为
    Δ u [ n ] = K p { e [ n ] − e [ n − 1 ] } + K i e [ n ] + K d { e [ n ] − 2 e [ n − 1 ] + e [ n − 2 ] } (2.4) \Delta u[n] = K_p \left\{ e[n] - e[n-1] \right\}+ K_i e[n] + K_d \left\{ e[n] -2 e[n-1] + e[n-2]\right\} \tag{2.4} Δu[n]=Kp{e[n]e[n1]}+Kie[n]+Kd{e[n]2e[n1]+e[n2]}(2.4)
    增量式PID控制主要是通过求出增量,将原先的积分环节的累积作用进行了替换,避免积分环节占用大量计算性能和存储空间.

    位置式PID与增量式PID的比较

    增量式PID控制的优点:

    1. 计算机每次只输出控制增量,即对应执行机构位置的变化量,故机器发生故障时影响范围小、不会严重影响生产过程
    2. 手动-自动切换时冲击小.当控制从手动向自动切换时,可以作到无扰动切换
    3. 不进行累加运算,增量仅与近三次 e ( n ) e(n) e(n)有关

    增量式PID控制的缺点:

    1. 由于增量式需要对控制量进行记忆,所以对于不带记忆装置的系统,只能使用位置式PID控制方式进行控制.

    离散PID控制的MATLAB实现

    实现增量式PID算法

    我们本次实现增量式PID控制

    curTime = 0; ts = 0.1;			% curTime记录当前时间,ts记录采样周期
    r = 1000;						% 初始化给定值,设定给定值为1500
    u_n1 = 0; u_n = 0;				% 输出,u_n表示u[n],u_n1表示u[n-1],初始时输出均为0
    e_n = 0; e_n1 = 0; e_n2 = 0;	% 输入(偏差),e_n表示e[n],e_n1表示e[n-1],e_n2表示e[n-2]
    while stop ~= true
    	curTime = curTime + ts;		% 刷新当前时间
    	% 计算阀门开度增量
    	delta1 = np * (e_n - e_n1)
    	delta2 = ni * e_n
    	delta3 = nd *(e_n - 2*e_n1 + e_n2)
    	delta_u = delta1 + delta2 + delta3;	
    	% 绘图
    	plot([curTime-ts, curTime], [u_n1, u_n], 'r'); hold on;	% 绘制给定值变化曲线
    	plot([curTime-ts, curTime], [r, r]); hold on;			% 绘制阀门开度变化曲线
        % 更新各个量
    	r = r;		% 更新给定值
    	u_n1 = u_n;			
    	e_n2 = e_n1; e_n1 = e_n; e_n = r - u_n;
    	pause(0.1);
    end;
    

    运行上述程序,得到图像结果如下:
    在这里插入图片描述

    绘制GUI界面,实时更改给定值

    绘制GUI界面如下
    在这里插入图片描述
    将上一步中编写的核心算法作为各按钮的回调函数,完成软件的编写,软件运行效果如下
    在这里插入图片描述

    源代码下载地址: 下载地址: https://download.csdn.net/download/ncepu_chen/11253423

    pdf和代码的下载地址: 增量式PID算法的MATLAB实现(访问密码:3834)

    展开全文
  • 一、PID控制算法概述 PID 实指“比例 proportional”、“积分 integral”、“微分 derivative”,这三项构 成 ...一、增量式PID 比例P : e(k)-e(k-1) 这次误差-上次误差 积分I : e(i) 误差 微分D : e(k) - 2e(k-1)+e(k

    一、PID控制算法概述
    PID 实指“比例 proportional”、“积分 integral”、“微分 derivative”,这三项构 成 PID 基本要素。每一项完成不同任务,对系统功能产生不同的影响。它的结构简单,参数易 于调整,是控制系统中经常采用的控制算法。
    PID:比例单元(P)、积分单元(I)和微分单元(D)组成
    在这里插入图片描述
    一、增量式PID
    在这里插入图片描述

    比例P : e(k)-e(k-1) 这次误差-上次误差
    积分I : e(i) 误差
    微分D : e(k) - 2e(k-1)+e(k-2) 这次误差-2*上次误差+上上次误差
             增量式PID根据公式可以很好地看出,一旦确定了 KP、TI 、TD,只要使用前后三次测量值的偏差, 即可由公式求出控制增量而得出的控制量▲u(k)对应的是近几次位置误差的增量,而不是对应与实际位置的偏差没有误差累加也就是说,增量式PID中不需要累加。控制增量Δu(k)的确定仅与最近3次的采样值有关,容易通过加权处理获得比较好的控制效果,并且在系统发生问题时,增量式不会严重影响系统的工作
             总结:增量型 PID,是对位置型 PID 取增量,这时控制器输出的是相邻两次采样时刻所计算的位置值
    之差,得到的结果是增量,即在上一次的控制量的基础上需要增加(负值意味减少)控制量。

    struct inc_pid_controller
    {
        struct controller   controller;
        
        float               kp;
        float               ki;
        float               kd;
    
        float               minimum;
        float               maximum;
    
        float               p_error;
        float               i_error;
        float               d_error;
    
        float               error;
        float               error_l;
        float               error_ll;
    
        float               last_out;
        rt_tick_t           last_time;
    };
    
    static rt_err_t inc_pid_controller_update(void *pid, float current_point)
    {
        inc_pid_controller_t inc_pid = (inc_pid_controller_t)pid;
        // TODO
        if((rt_tick_get() - inc_pid->last_time) < rt_tick_from_millisecond(inc_pid->controller.sample_time))
        {
            LOG_D("PID waiting ... ");
            return RT_EBUSY;
        }
        inc_pid->last_time = rt_tick_get();
    
        inc_pid->error = inc_pid->controller.target - current_point;
    
        inc_pid->p_error = inc_pid->kp * (inc_pid->error - inc_pid->error_l);
        inc_pid->i_error = inc_pid->ki * inc_pid->error;
        inc_pid->d_error = inc_pid->kd * (inc_pid->error - 2 * inc_pid->error_l + inc_pid->error_ll);
    
        inc_pid->last_out += inc_pid->p_error + inc_pid->i_error + inc_pid->d_error;
    
        if (inc_pid->last_out > inc_pid->maximum)
        {
            inc_pid->last_out = inc_pid->maximum;
        }
        if (inc_pid->last_out < inc_pid->minimum)
        {
            inc_pid->last_out = inc_pid->minimum;
        }
    
        inc_pid->error_ll = inc_pid->error_l;
        inc_pid->error_l = inc_pid->error;
    
        inc_pid->controller.output = inc_pid->last_out;
    
        return RT_EOK;
    }
    

    二、位置式PID
    在这里插入图片描述

    e(k): 用户设定的值(目标值) - 控制对象的当前的状态值
    比例P : e(k)
    积分I : ∑e(i) 误差的累加
    微分D : e(k) - e(k-1) 这次误差-上次误差
             也就是位置式PID是当前系统的实际位置,与你想要达到的预期位置的偏差,进行PID控制因为有误差积分 ∑e(i),一直累加,也就是当前的输出u(k)与过去的所有状态都有关系,用到了误差的累加值;(误差e会有误差累加),输出的u(k)对应的是执行机构的实际位置,,一旦控制输出出错(控制对象的当前的状态值出现问题 ),u(k)的大幅变化会引起系统的大幅变化并且位置式PID在积分项达到饱和时,误差仍然会在积分作用下继续累积,一旦误差开始反向变化,系统需要一定时间从饱和区退出,所以在u(k)达到最大和最小时,要停止积分作用,并且要有积分限幅和输出限幅
             所以在使用位置式PID时,一般我们直接使用PD控制
             而位置式 PID 适用于执行机构不带积分部件的对象,如舵机和平衡小车的直立和温控系统的控制

    struct pos_pid_controller
    {
        struct controller   controller;
        
        float               kp;
        float               ki;
        float               kd;
    
        float               minimum;
        float               maximum;
        float               anti_windup_value;
    
        float               p_error;
        float               i_error;
        float               d_error;
    
        float               integral;
        float               error;
        float               error_l;
    
        float               last_out;
        rt_tick_t           last_time;
    };
    
    static rt_err_t pos_pid_controller_update(void *pid, float current_point)
    {
        pos_pid_controller_t pos_pid = (pos_pid_controller_t)pid;
    
        if((rt_tick_get() - pos_pid->last_time) < rt_tick_from_millisecond(pos_pid->controller.sample_time))
        {
            LOG_D("PID waiting ... ");
            return RT_EBUSY;
        }
        pos_pid->last_time = rt_tick_get();
    
        pos_pid->error = pos_pid->controller.target - current_point;
    
        pos_pid->integral += pos_pid->ki * pos_pid->error;
    
        //Perform integral value capping to avoid internal PID state to blows up
        //when controllertuators saturate:
        if(pos_pid->integral > pos_pid->anti_windup_value) {
            pos_pid->integral = pos_pid->anti_windup_value;
        } else if (pos_pid->integral < -pos_pid->anti_windup_value) {
            pos_pid->integral = -pos_pid->anti_windup_value;
        }
    
        pos_pid->p_error = pos_pid->kp * pos_pid->error;
        pos_pid->i_error = pos_pid->integral;
        pos_pid->d_error = pos_pid->kd * (pos_pid->error - pos_pid->error_l);
    
        pos_pid->last_out = pos_pid->p_error + pos_pid->i_error + pos_pid->d_error;
        if (pos_pid->last_out > pos_pid->maximum)
        {
            pos_pid->last_out = pos_pid->maximum;
        }
        if (pos_pid->last_out < pos_pid->minimum)
        {
            pos_pid->last_out = pos_pid->minimum;
        }
    
        pos_pid->error_l = pos_pid->error;
    
        pos_pid->controller.output = pos_pid->last_out;
    
        return RT_EOK;
    }
    
    展开全文
  • C语言增量式PID 代码

    2013-03-27 16:42:50
    C语言 增量式 PID 代码 测试可用的 只需要调节KP KI KD即可
  • Matlab增量式PID算法仿真 ,包含m文件和simulink仿真文件,希望对大家有帮助
  • 因为课程设计,需要实现PID的控制器,想在网上寻求一下现成的代码发现都没有。 于是个人尝试了一些,刚开始学习PID控制算法,练习了一些代码,这个是我尝试的结果希望对大家有帮助。
  • 位置式PID与增量式PID区别浅析

    万次阅读 多人点赞 2019-04-26 08:55:12
    1PID控制算法 什么是PID PID 控制器以各种形式使用超过了 1 世纪,广泛应用在机械设备、气动设备 和电子设备.在工业应用中PID及其衍生算法是应用最广泛的算法之一,是当之无愧的万能算法 PID 实指“比例 ...

    1PID控制算法

    什么是PID

    PID 控制器以各种形式使用超过了 1 世纪,广泛应用在机械设备、气动设备 和电子设备.在工业应用中PID及其衍生算法是应用最广泛的算法之一,是当之无愧的万能算法

    PID 实指“比例 proportional”、“积分 integral”、“微分 derivative”,这三项构 成 PID 基本要素。每一项完成不同任务,对系统功能产生不同的影响。它的结构简单,参数易 于调整,是控制系统中经常采用的控制算法。

    PID:比例单元(P)、积分单元(I)和微分单元(D)组成

    PID控制公式

     

    其中:u(t)为控制器输出的控制量;(输出)

    e(t)为偏差信号,它等于给定量与输出量之差;(输入)

    KP 为比例系数;(对应参数 P)

    TI 为积分时间常数;(对应参数I)

    TD 为微分时间常数。(对应参数 D) 

     

    数字 PID 控制算法通常分为位置式 PID 控制算法和增量式 PID 控制算法。  

    位置式 PID 算法 :

    pid算法中位置型和增量型有什么区别,分析两者优缺点

     e(k): 用户设定的值(目标值) -  控制对象的当前的状态值 

    比例P :    e(k)

    积分I :   ∑e(i)     误差的累加

    微分D :  e(k) - e(k-1)  这次误差-上次误差

    也就是位置式PID是当前系统的实际位置,与你想要达到的预期位置的偏差,进行PID控制

    因为有误差积分 ∑e(i),一直累加,也就是当前的输出u(k)与过去的所有状态都有关系,用到了误差的累加值;(误差e会有误差累加),输出的u(k)对应的是执行机构的实际位置,,一旦控制输出出错(控制对象的当前的状态值出现问题 ),u(k)的大幅变化会引起系统的大幅变化

    并且位置式PID在积分项达到饱和时,误差仍然会在积分作用下继续累积,一旦误差开始反向变化,系统需要一定时间从饱和区退出,所以在u(k)达到最大和最小时,要停止积分作用,并且要有积分限幅输出限幅

    所以在使用位置式PID时,一般我们直接使用PD控制

    而位置式 PID 适用于执行机构不带积分部件的对象,如舵机和平衡小车的直立和温控系统的控制

     

    结合代码可以很好理解

    typedef struct PID
    { 
      float P,I,D,limit;
    }PID;
    
    typedef struct Error
    {
      float Current_Error;//当前误差
      float Last_Error;//上一次误差
      float Previous_Error;//上上次误差
    }Error;
    
    /*! 
     *  @brief      位置式PID
     *  @since      v1.0
     *  *sptr :误差参数
     *  *pid:  PID参数
     *  NowPlace:当前位置
     *  Point:   预期位置  
     */
    
    // 位置式PID控制
    float PID_Realize(Error *sptr,PID *pid, int32 NowPlace, float Point)
    {
    
    	int32 iError,	// 当前误差
    		 Realize;   //实际输出	
    
    	iError = Point - NowPlace;	// 计算当前误差
    	sptr->Current_Error += pid->I * iError;	// 误差积分
          sptr->Current_Error = sptr->Current_Error > pid->limit?pid->limit:sptr->Current_Error;//积分限幅
          sptr->Current_Error = sptr->Current_Error <-pid->limit?-pid->limit:sptr->Current_Error;
    	Realize = pid->P * iError       //比例P
                + sptr->Current_Error   //积分I
    			+ pid->D * (iError - sptr->Last_Error);  //微分D
    	sptr->Last_Error = iError;		  	// 更新上次误差
    	return Realize;	// 返回实际值
    }

    增量式PID

     

    pid算法中位置型和增量型有什么区别,分析两者优缺点

    比例P :    e(k)-e(k-1)   这次误差-上次误差

    积分I :   e(i)     误差   

    微分D :  e(k) - 2e(k-1)+e(k-2)   这次误差-2*上次误差+上上次误差

     增量式PID根据公式可以很好地看出,一旦确定了 KP、TI  、TD,只要使用前后三次测量值的偏差, 即可由公式求出控制增量

    而得出的控制量▲u(k)对应的是近几次位置误差的增量,而不是对应与实际位置的偏差     没有误差累加

    也就是说,增量式PID中不需要累加。控制增量Δu(k)的确定仅与最近3次的采样值有关,容易通过加权处理获得比较好的控制效果,并且在系统发生问题时,增量式不会严重影响系统的工作

    总结:增量型 PID,是对位置型 PID 取增量,这时控制器输出的是相邻两次采样时刻所计算的位置值
    之差,得到的结果是增量,即在上一次的控制量的基础上需要增加(负值意味减少)控制量。
     

    typedef struct PID
    { 
      float P,I,D,limit;
    }PID;
    typedef struct Error
    {
      float Current_Error;//当前误差
      float Last_Error;//上一次误差
      float Previous_Error;//上上次误差
    }Error;
    
    /*! 
     *  @brief      增量式PID
     *  @since      v1.0
     *  *sptr :误差参数
     *  *pid:  PID参数
     *  NowPlace:实际值
     *  Point:   期望值
     */
    // 增量式PID电机控制
    int32 PID_Increase(Error *sptr, PID *pid, int32 NowPlace, int32 Point)
    {
    
    	int32 iError,	//当前误差
    		Increase;	//最后得出的实际增量
    
    	iError = Point - NowPlace;	// 计算当前误差
    
    	Increase =  pid->P * (iError - sptr->Last_Error)   //比例P
    			  + pid->I * iError      //积分I
    			  + pid->D * (iError - 2 * sptr->Last_Error + sptr->Previous_Error);  //微分D
    	
    	sptr->Previous_Error = sptr->Last_Error;	// 更新前次误差
    	sptr->Last_Error = iError;		  	// 更新上次误差
    	
    	return Increase;	// 返回增量
    }
    

    增量式与位置式区别:

    1增量式算法不需要做累加,控制量增量的确定仅与最近几次偏差采样值有关,计算误差对控制 量计算的影响较小。而位置式算法要用到过去偏差的累加值,容易产生较大的累加误差。 

    2增量式算法得出的是控制量的增量,例如在阀门控制中,只输出阀门开度的变化部分,误动作 影响小,必要时还可通过逻辑判断限制或禁止本次输出,不会严重影响系统的工作。 而位置式的输出直接对应对象的输出,因此对系统影响较大

    3增量式PID控制输出的是控制量增量,并无积分作用,因此该方法适用于执行机构带积分部件的对象,如步进电机等,而位置式PID适用于执行机构不带积分部件的对象,如电液伺服阀。

    4在进行PID控制时,位置式PID需要有积分限幅输出限幅,而增量式PID只需输出限幅

    位置式PID优缺点:

    优点:

    ①位置式PID是一种非递推式算法,可直接控制执行机构(如平衡小车),u(k)的值和执行机构的实际位置(如小车当前角度)是一一对应的,因此在执行机构不带积分部件的对象中可以很好应用

    缺点:

    ①每次输出均与过去的状态有关,计算时要对e(k)进行累加,运算工作量大。

    增量式PID优缺点:

    优点:

    ①误动作时影响小,必要时可用逻辑判断的方法去掉出错数据。
    ②手动/自动切换时冲击小,便于实现无扰动切换。当计算机故障时,仍能保持原值。
    ③算式中不需要累加。控制增量Δu(k)的确定仅与最近3次的采样值有关。


    缺点:

    ①积分截断效应大,有稳态误差;

    ②溢出的影响大。有的被控对象用增量式则不太好;

     

    展开全文
  • matlab数字增量式pid简单程序,适合对PID不是很熟悉的人
  • void prpvtest::PID_Init(){ cout &lt;&lt; "PID_Init begin!" &lt;&lt; endl; pid.SetSpeed = 0; pid.ActualSpeed = 0; pid.Err = 0; pid.Err_last = 0; pid.Err_Next = 0; pid....
  • 增量式PID的两种计算方式及C代码

    万次阅读 2019-05-05 09:55:04
    最近笔者在项目中需要使用到增量式PID进行电机控制,参考网上增量式PID算法,发现有两类算法的代码,便产生疑惑,究竟是哪 一种算法是正确的?——最终发现两种表达方式均为正确的! 从原理出发,分析如下: 位置...
  • 增量式PID的算法

    2020-07-30 22:22:49
    最近做一个压力控制的设备需要用到PID算法,在网上找到一个增量式PID算法,注释比较详细,通俗易懂,但是有错漏。其实照着公式来写是没有什么问题的,下面给出修改后的代码
  • 代码是基于STM32F103ZET6和编码器直流电机编写的,模糊自整定增量式PID控制电机转动速度的程序。并且是基于正点原子代码格式编写的,相对于普通增量式PID来说控制效果更好,是很好的算法优化。对于初学者有重要的...
  • 对于增量式PID 代码实现的详细说明;应给可以给部分人解疑。
  • 位置式与增量式PID代码(C语言实现)
  • 这里个大家分享了一个增量式PID控制C语言的源代码
  • 增量式PID算法的C语言代码

    万次阅读 多人点赞 2015-07-30 20:43:04
    下面给出的可以说是一个最简单的PID代码了,然而麻雀虽小,五脏俱全。对于很多控制场合,用它已经足够了。我力求把代码写得简洁、清晰,而具体的PID算法推导我就不当搬运工了。 typedef struct{ float limit; //...
  • 这是之前做设计的时候存下来的代码,通过quartus使用verilog hdl实现的基本PID控制,做的不算好,只实现了基本的PID控制,精度不敢保证。 之前本来想在网上找,但是找不到不到只能自己学着写。 应付一下课程设计和...
  • STM32增量PID程序

    2015-03-18 10:32:34
    资源包括C文件与H文件,基于STM32实现增量PID控制PWM输出的功能,参数需要自己调节
  • 增量式PID控制算法.doc

    2020-07-26 19:49:46
    增量式PID算法 原理及实现方法 物理模型 软件算法流程图流程图 增量式PID算法的优点,对声音信标麦克纳姆轮pid的代码 写法有帮助,里面还有一个连接,附带代码,可以参考。搜集全网最实用资料。
  • function f(a,M) %a选则输入信号,M为输出图形的横坐标最大值; %单位阶跃f(1,1); %正弦波f(2,2) %三角波f(3,1) ts=0.001;%采样时间 G=tf(50,[0.125,7, 0]) Gd=c2d(G,ts,'z');...[num,den]=tfdata(Gd,'v') ...
  • 电机速度闭环控制(代码详细注释)stm32电机速度PID增量式闭环控制参考平衡小车之家
  • 增量式温控PID

    2015-07-29 11:50:08
    增量式温控PID代码,只需要自行添加头文件,
  • 直流减速电机增量式PID 通俗易懂版 对于我一个双非学校没上过自控的电子专业本科生而言,这个东西真的是太难了,之前研究了一个A4950驱动,价格便宜,驱动能力高,安全性高,便捷性高,一句话就是比L298N好用,我写完之后发...
  • PID算法及原理详解,包含增量式PID,位置型PID,梯度PID,专家PID,模糊算法等,从普通PID原型到专家PID逐步优化原理及代码,包含初级到高阶算法

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,578
精华内容 2,231
关键字:

增量式pid代码