python实现两类PID编程

两类PID公式:

第一类:

import time

class PID:
#初始化P I D值,调用类可设置PID,也可通过下面函数单独设置某一个
    def __init__(self, P=0.2, I=0.0, D=0.0):

        self.Kp = P
        self.Ki = I
        self.Kd = D

        self.sample_time = 0.00 #采样时间
        self.current_time = time.time()#调用类时当前时间,相当于0
        self.last_time = self.current_time#上一次时间同上

        self.clear()#每次调用先清零上一次调用的计算值

    def clear(self):
        """Clears PID computations and coefficients"""
        self.SetPoint = 0.0#设定值

        self.PTerm = 0.0#比例值无Kp
        self.ITerm = 0.0#积分值无Ki
        self.DTerm = 0.0#微分值无Kd
        self.last_error = 0.0 #上一次误差

        # Windup Guard
        self.int_error = 0.0#初始误差为0,意义不大
        self.windup_guard = 20.0

        self.output = 0.0

    def update(self, feedback_value):

        error = self.SetPoint - feedback_value#设定值减去反馈值,误差

        self.current_time = time.time()#调用类函数时当前时间
        delta_time = self.current_time - self.last_time #微分中的两次时间差,如果只有一次,则lasttime=0
        delta_error = error - self.last_error #微分中误差值

        if (delta_time >= self.sample_time):#两次反馈值得时间间隔和采样时间如果相等
            self.PTerm = self.Kp * error#计算比例值部分
            self.ITerm += error * delta_time#计算积分部分
            #避免第一次温度升到100摄氏度过程中积分后产生过冲,将值设为20或-20,n次后,积分的各值有正负基本不会超过20.
            if (self.ITerm < -self.windup_guard):
                self.ITerm = -self.windup_guard
            elif (self.ITerm > self.windup_guard):
                self.ITerm = self.windup_guard

            self.DTerm = 0.0#应该不等于0也没问题,微分就是和后两次的误差和时间有关
            if delta_time > 0:
                self.DTerm = delta_error / delta_time#计算微分部分

            # 将本次的误差和时间设置成上一次的,为下次计算做准备
            self.last_time = self.current_time
            self.last_error = error

            #PID的输出值(加上Kp Ki Kd)
            self.output = self.PTerm + (self.Ki * self.ITerm) + (self.Kd * self.DTerm)

    def setKp(self, proportional_gain):#比例增益
        self.Kp = proportional_gain

    def setKi(self, integral_gain):#积分增益
        self.Ki = integral_gain

    def setKd(self, derivative_gain):#微分增益
        self.Kd = derivative_gain

    def setWindup(self, windup):#防止积分第一次出现过冲,设置积分最大值
        self.windup_guard = windup

    def setSampleTime(self, sample_time):#采样时间
       self.sample_time = sample_time

 

第二类:

#  PID控制一阶惯性系统测试程序

# *****************************************************************#
#                      位置式PID系统                              #
# *****************************************************************#
class PositionalPID:
    def __init__(self, P, I, D):
        self.Kp = P
        self.Ki = I
        self.Kd = D

        self.PidOutput = 0.0
        self.PIDErrADD = 0.0
        self.ErrLast = 0.0

        self.SystemOutput = 0.0
        self.LastSystemOutput = 0.0

    def SetStepSignal(self, StepSignal):
        Err = StepSignal - self.SystemOutput#设定值-反馈值=误差
        KpWork = self.Kp * Err#比例值
        self.PIDErrADD += Err
        KiWork = self.Ki * self.PIDErrADD#积分值
        KdWork = self.Kd * (Err - self.ErrLast)#微分值
        self.PidOutput = KpWork + KiWork + KdWork#PID输出值

        self.ErrLast = Err#本次误差值赋值成上一次

    def SetInertiaTime(self, InertiaTime, SampleTime):
        self.SystemOutput = (InertiaTime * self.LastSystemOutput + SampleTime * self.PIDOutput) / (
                    SampleTime + InertiaTime)
        self.LastSystemOutput = self.SystemOutput


# *****************************************************************#
#                      增量式PID系统                              #
# *****************************************************************#
class IncrementalPID:
    def __init__(self, P, I, D):
        self.Kp = P
        self.Ki = I
        self.Kd = D

        self.PIDOutput = 0.0  # PID控制器输出
        self.Error = 0.0  # 输出值与输入值的偏差
        self.LastError = 0.0
        self.LastLastError = 0.0

        self.SystemOutput = 0.0  # 系统输出值
        self.LastSystemOutput = 0.0  # 上次系统输出值

    # 设置PID控制器参数
    def SetStepSignal(self, StepSignal):
        self.Error = StepSignal - self.SystemOutput#误差值
        IncrementValue = self.Kp * (self.Error - self.LastError) + self.Ki * self.Error + self.Kd * (
                    self.Error - 2 * self.LastError + self.LastLastError)#增量值
        self.PIDOutput += IncrementValue

        self.LastLastError = self.LastError
        self.LastError = self.Error

    # 设置一阶惯性环节系统  其中InertiaTime为惯性时间常数
    def SetInertiaTime(self, InertiaTime, SampleTime):
        self.SystemOutput = (InertiaTime * self.LastSystemOutput + SampleTime * self.PIDOutput) / (
                    SampleTime + InertiaTime)
        self.LastSystemOutput = self.SystemOutput

调用pid:

import PID
import matplotlib.pyplot as plt#导入绘图库

plt.figure(1)  # 创建图表1
plt.figure(2)  # 创建图表2


# 测试PID程序
def TestPID(P, I, D):
    IncrementalPid = PID.IncrementalPID(P, I, D)
    PositionalPid = PID.PositionalPID(P, I, D)
    IncrementalXaxis = [0]
    IncrementalYaxis = [0]
    PositionalXaxis = [0]
    PositionalYaxis = [0]

    for i in range(1, 500):
        # 增量式
        IncrementalPid.SetStepSignal(100.2) #设置设定值
        IncrementalPid.SetInertiaTime(3, 0.1)#设置惰性时间和采样时间
        IncrementalYaxis.append(IncrementalPid.SystemOutput)#制作Y轴列表
        IncrementalXaxis.append(i)#x轴列表

        # 位置式
        PositionalPid.SetStepSignal(100.2)
        PositionalPid.SetInertiaTime(3, 0.1)
        PositionalYaxis.append(PositionalPid.SystemOutput)
        PositionalXaxis.append(i)

    plt.figure(1)  # 选择图表1
    plt.plot(IncrementalXaxis, IncrementalYaxis, 'r')#图标数值
    plt.xlim(0, 120)#X轴数值
    plt.ylim(0, 140)#Y轴数值
    plt.title("IncrementalPID")#设定标题

    plt.figure(2)  # 选择图表2
    plt.plot(PositionalXaxis, PositionalYaxis, 'b')
    plt.xlim(0, 120)
    plt.ylim(0, 140)
    plt.title("PositionalPID")

    plt.show() #图标显示


if __name__ == "__main__":
    TestPID(4.5, 0.5, 0.1)#设定PID值

 

  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值