PID控制器概述及python实现PID控制算法

PID控制器简要分析

 

PID控制器概述

PID控制器是自动控制领域一种常见的控制器,其简单易设计的结构和良好的鲁棒性使得其在工业控制中较为常见。PID三个字母分别代表了比例(proportion)、积分(integration)和微分(differential)。

补充知识:

控制器是针对被控对象而言的,一个典型的开环控制系统可以用方框图表示如下:

典型开环控制系统
外界的输入通过系统内的控制器调整后,加到被控对象上,对被控对象造成影响后,被控对象产生输出。

在自动控制领域,我们往往将被控对象进行拉普拉斯变换后再进行研究,因此,无论是控制器还是被控对象,用方框图表示时,方框的内容都可以是拉氏变换后的方程。

PID控制器的分类

上文已经提到了开环控制系统,在介绍PID控制器之前,我们再介绍闭环控制系统:
典型闭环控制系统
闭环控制系统看起来与开环控制器相似,增加了一个“闭环”,通过这一条闭环将被控对象的输出反馈到输入端,并与输入端进行比较,以检测是否达到控制效果,同时与输入进行整合后作为控制器的“新一轮”输入,此“新一轮”的输入即包含了对“上一轮”输出结果的借鉴。通过不断的“输出——反馈”,最终使控制器将被控对象的输出控制到一个合理的范围。

本文讨论离散的数字PID。

位置式PID

位置式PID控制的输出与整个过去的状态有关,用到了误差的累加值,位置式PID适用于执行机构不带积分部件的对象。

# 位置式PID
class PID:
    def __init__(self, P=0.2, I=0.0, D=0.0):
        self.kp = P
        self.ki = I
        self.kd = D
        self.uPrevious = 0
        self.uCurent = 0
        self.setValue = 0
        self.lastErr = 0
        self.preLastErr = 0
        self.errSum = 0
        self.errSumLimit = 10
# 位置式PID
    def pidPosition(self, curValue):
        err = self.setValue - curValue
        dErr = err - self.lastErr
        self.preLastErr = self.lastErr
        self.lastErr = err
        self.errSum += err
        outPID = self.kp * err + (self.ki * self.errSum) + (self.kd * dErr)
        return outPID

增量式PID

增量式PID控制,数字PID控制算法的一种基本形式,是通过对控制量的增量(本次控制量和上次控制量的差值)进行PID控制的一种控制算法。是一种递推式的算法。

一般来讲,增量式PID采用递推的思想,每次只输出控制增量,即对应执行机构位置的变化量,故机器发生故障时影响范围小、不会严重影响生产过程。且式中不需要累加。

# 增量式PID
    def pidIncrease(self, curValue):
        self.uCurent = self.pidPosition(curValue)
        outPID = self.uCurent - self.uPrevious
        self.uPrevious = self.uCurent
        return outPID

代码实现

import time
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
from math import e
from scipy.interpolate import make_interp_spline as spline


class PID:
    def __init__(self, P=0.2, I=0.0, D=0.0):
        self.kp = P
        self.ki = I
        self.kd = D
        self.uPrevious = 0
        self.uCurent = 0
        self.setValue = 0
        self.lastErr = 0
        self.preLastErr = 0
        self.errSum = 0
        self.errSumLimit = 10
# 位置式PID
    def pidPosition(self, curValue):
        err = self.setValue - curValue
        dErr = err - self.lastErr
        self.preLastErr = self.lastErr
        self.lastErr = err
        self.errSum += err
        outPID = self.kp * err + (self.ki * self.errSum) + (self.kd * dErr)
        return outPID

# 增量式PID
    def pidIncrease(self, curValue):
        self.uCurent = self.pidPosition(curValue)
        outPID = self.uCurent - self.uPrevious
        self.uPrevious = self.uCurent
        return outPID


class BeControlled:
    def __init__(self):
        self.lastControlIn = 0
        self.preLastControlIn = 0
        self.lastControlOut = 0
        self.preLastControlOut = 0
# 被控对象的相关计算
    def beControlledDeal(self, outPID):
        # output = 2*self.lastControlOut - 1*self.preLastControlOut + \
        #     0.00005*self.lastControlIn + 0.00005*self.preLastControlIn

        # output为被控对象的输出,被控对象的方程此处直接采用了设计好的参数,并与PID控制器的输出进行计算,
        # 如果需要设计自己的被控对象,可以将实际被控对象的方程通过拉普拉斯变换后,再与控制器的输出进行计算。
        output = 0.00019346*self.preLastControlIn + 0.00019671e-04*self.lastControlIn + \
            1.9512*self.lastControlOut - 0.9512*self.preLastControlOut
        self.preLastControlIn = self.lastControlIn
        self.lastControlIn = outPID
        self.preLastControlOut = self.lastControlOut
        self.lastControlOut = output
        return output


def testPid(P=0.2, I=0.0, D=0.0, Len=1000):
    pid = PID(P, I, D)
    beControlled = BeControlled()
    pid.setValue = 1  # set end
    curValue = 0
    curValueList = []
    timeList = []
    setValueList = []
    PIDoutList = []
    curValueList.append(0)
    timeList.append(0)
    setValueList.append(pid.setValue)
    PIDoutList.append(0)

    for i in range(1, Len):
        #采用位置式PID去掉注释即可
        # outPID = pid.pidPosition(curValue)
        outPID = pid.pidIncrease(curValue)
        PIDoutList.append(outPID)
        curValue = beControlled.beControlledDeal(outPID)
        curValueList.append(curValue)
        setValueList.append(pid.setValue)
        timeList.append(i)

# 绘图
    timeSm = np.array(timeList)
    timeSmooth = np.linspace(timeSm.min(), timeSm.max(), 300)  # 将x轴300等分
    curValueSmooth = spline(timeList, curValueList)(timeSmooth)  # 插值.使原y轴数据平滑
    pidoutSmooth = spline(timeList, PIDoutList)(timeSmooth)  # 使PID控制器输出平滑
    plt.figure(0)
    #plt.xticks([-1, 3, 5])
    #plt.yticks([-1, 100, 10])
    plt.plot(timeSmooth, curValueSmooth)  # 画被控对象输出
    plt.plot(timeSmooth, pidoutSmooth)  # 画PID控制器输出
    plt.plot(timeList, setValueList)  # 画直线
    plt.xlim((0, Len))
    plt.ylim((min(curValueList)-0.5, max(curValueList)+0.5))
    plt.xlabel('time (s)')
    plt.ylabel('set value')
    plt.title('PID')
    plt.ylim((1-0.5, 1+0.5))
    plt.grid(True)
    plt.show()


if __name__ == "__main__":
    testPid(P=0, I=0.5, D=0, Len=5000)

得到增量式PID输出效果如下:
增量式PID效果图
将代码中注释删去,调整PID参数:

if __name__ == "__main__":
    testPid(P=0.5, I=0, D=0, Len=5000)

可以得到位置式PID输出效果如下:
位置式PID效果图

参数整定

PID控制器的原理较为简单,但在实际运行中,难点往往在于P、I、D参数的整定,合适的参数可以增加系统的鲁棒性,减小系统的响应时间。具体整定方法有:经验数据法、试凑法、临界比例度法。本文不再赘述。

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下是一个使用位置式PID控制算法Python代码示例: ```python class PID: def __init__(self, P=0.2, I=0.0, D=0.0): self.kp = P self.ki = I self.kd = D self.uPrevious = 0 self.uCurrent = 0 self.setValue = 0 self.lastErr = 0 self.preLastErr = 0 self.errSum = 0 self.errSumLimit = 10 def pidPosition(self, curValue): err = self.setValue - curValue dErr = err - self.lastErr self.preLastErr = self.lastErr self.lastErr = err self.errSum += err outPID = self.kp * err + self.ki * self.errSum + self.kd * dErr return outPID ``` 这个代码实现了一个简单的位置式PID控制。在初始化时,可以指定PID控制比例系数P、积分系数I和微分系数D。然后,通过调用`pidPosition`方法,传入当前值,即可计算出相应的PID输出值。该代码可供参考,可根据实际需求进行修改和扩展。123 #### 引用[.reference_title] - *1* [PID控制概述python实现PID控制算法](https://blog.csdn.net/peizhuo_liu/article/details/112058679)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}} ] [.reference_item] - *2* [使用python模拟实现PID控制算法](https://blog.csdn.net/weixin_43863487/article/details/124604299)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}} ] [.reference_item] - *3* [PID 控制算法原理与 Python 实现](https://blog.csdn.net/weixin_30230009/article/details/122505270)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值