• 【代码收藏夹】Python实现PID算法


    一、代码

    使用方法

    from pid import PID
    
    # p:比例系数,i:微分系数,d:积分系数,imax:积分限幅
    pid1 = PID(p=0.07, i=0.01, d=0.01, imax=90)
    while(True):
        # error:误差值, 误差值 = 目标值 - 测量值
        error = 50 
        # optput:PID的输出
        output = pid1.get_pid(error)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    1.1 Python3 版本

    from math import pi, isnan
    import time
    
    def millis():
        return int(time.time() * 1000)
     
    class PID:
        _kp = _ki = _kd = _integrator = _imax = 0
        _last_error = _last_derivative = _last_t = 0
        _RC = 1/(2 * pi * 20)
        def __init__(self, p=0, i=0, d=0, imax=0):
            self._kp = float(p)
            self._ki = float(i)
            self._kd = float(d)
            self._imax = abs(imax)
            self._last_derivative = float('nan')
     
        def get_pid(self, error, scaler=1):
            tnow = millis()
            dt = tnow - self._last_t
            output = 0
            if self._last_t == 0 or dt > 1000:
                dt = 0
                self.reset_I()
            self._last_t = tnow
            delta_time = float(dt) / float(1000)
            output += error * self._kp
            if abs(self._kd) > 0 and dt > 0:
                if isnan(self._last_derivative):
                    derivative = 0
                    self._last_derivative = 0
                else:
                    derivative = (error - self._last_error) / delta_time
                derivative = self._last_derivative + \
                                         ((delta_time / (self._RC + delta_time)) * \
                                            (derivative - self._last_derivative))
                self._last_error = error
                self._last_derivative = derivative
                output += self._kd * derivative
            output *= scaler
            if abs(self._ki) > 0 and dt > 0:
                self._integrator += (error * self._ki) * scaler * delta_time
                if self._integrator < -self._imax: self._integrator = -self._imax
                elif self._integrator > self._imax: self._integrator = self._imax
                output += self._integrator
            return output
    
        def reset_I(self):
            self._integrator = 0
            self._last_derivative = float('nan')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    1.2 MicroPython - OpenMV版本

    from pyb import millis
    from math import pi, isnan
    
    class PID:
        _kp = _ki = _kd = _integrator = _imax = 0
        _last_error = _last_derivative = _last_t = 0
        _RC = 1/(2 * pi * 20)
        def __init__(self, p=0, i=0, d=0, imax=0):
            self._kp = float(p)
            self._ki = float(i)
            self._kd = float(d)
            self._imax = abs(imax)
            self._last_derivative = float('nan')
     
        def get_pid(self, error, scaler=1):
            tnow = millis()
            dt = tnow - self._last_t
            output = 0
            if self._last_t == 0 or dt > 1000:
                dt = 0
                self.reset_I()
            self._last_t = tnow
            delta_time = float(dt) / float(1000)
            output += error * self._kp
            if abs(self._kd) > 0 and dt > 0:
                if isnan(self._last_derivative):
                    derivative = 0
                    self._last_derivative = 0
                else:
                    derivative = (error - self._last_error) / delta_time
                derivative = self._last_derivative + \
                                         ((delta_time / (self._RC + delta_time)) * \
                                            (derivative - self._last_derivative))
                self._last_error = error
                self._last_derivative = derivative
                output += self._kd * derivative
            output *= scaler
            if abs(self._ki) > 0 and dt > 0:
                self._integrator += (error * self._ki) * scaler * delta_time
                if self._integrator < -self._imax: self._integrator = -self._imax
                elif self._integrator > self._imax: self._integrator = self._imax
                output += self._integrator
            return output
        def reset_I(self):
            self._integrator = 0
            self._last_derivative = float('nan')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    1.3 MicroPython - K210版本

    from math import pi, isnan
    import utime
    
    def millis():
        return utime.ticks_ms()
     
    class PID:
        _kp = _ki = _kd = _integrator = _imax = 0
        _last_error = _last_derivative = _last_t = 0
        _RC = 1/(2 * pi * 20)
        def __init__(self, p=0, i=0, d=0, imax=0):
            self._kp = float(p)
            self._ki = float(i)
            self._kd = float(d)
            self._imax = abs(imax)
            self._last_derivative = float('nan')
     
        def get_pid(self, error, scaler=1):
            tnow = millis()
            dt = tnow - self._last_t
            output = 0
            if self._last_t == 0 or dt > 1000:
                dt = 0
                self.reset_I()
            self._last_t = tnow
            delta_time = float(dt) / float(1000)
            output += error * self._kp
            if abs(self._kd) > 0 and dt > 0:
                if isnan(self._last_derivative):
                    derivative = 0
                    self._last_derivative = 0
                else:
                    derivative = (error - self._last_error) / delta_time
                derivative = self._last_derivative + \
                                         ((delta_time / (self._RC + delta_time)) * \
                                            (derivative - self._last_derivative))
                self._last_error = error
                self._last_derivative = derivative
                output += self._kd * derivative
            output *= scaler
            if abs(self._ki) > 0 and dt > 0:
                self._integrator += (error * self._ki) * scaler * delta_time
                if self._integrator < -self._imax: self._integrator = -self._imax
                elif self._integrator > self._imax: self._integrator = self._imax
                output += self._integrator
            return output
    
        def reset_I(self):
            self._integrator = 0
            self._last_derivative = float('nan')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    二、说明

    原代码来自 OpenMV 官方的 PID 代码。因为不同平台的 MicroPython 的 API 有差异,所以移植需要重写 millis 函数。

    millis 函数用来获取系统开机后运行的时间长度,单位是毫秒。

    三、参考资料

  • 相关阅读:
    算法项目(9)—— 大模型实现PDF检索加QA
    Kubernetes学习(二)你不得不了解的K8s核心组件
    c++之类和对象
    PostgreSQL教程(三十一):服务器管理(十三)之监控数据库活动
    读取.nrrd和.dcm文件格式医学图片可视化与预处理
    【IoT毕设.上】STM32+机智云AIoT+实验室安全监控系统
    机器学习是什么?
    linux批量替换文件内容
    java设计模式学习笔记总结
    Spring5源码-事务的创建、回滚、提交
  • 原文地址:https://blog.csdn.net/qq_34802028/article/details/126266745