Python中的PID库
@(树莓派学习笔记)
PID
加入了条件积分抗积分饱和,加入了一阶低通滤波滤除高频噪声。
链接:https://github.com/EduardoNigro/Things-DAQ-Code/blob/main/Digital-PID/gpiozero_extended.py
simple_pid(连续PID)
API文档:
https://simple-pid.readthedocs.io/en/latest/simple_pid.html#module-simple_pid.PID
源码文档:
https://simple-pid.readthedocs.io/en/latest/_modules/simple_pid/PID.html#PID.
call
介绍
class simple_pid.PID.PID(Kp=1.0, Ki=0.0, Kd=0.0, setpoint=0, sample_time=0.01, output_limits=(None, None), auto_mode=True, proportional_on_measurement=False, error_map=None)
Parameters:
Kp
:比例增益 Kp 的值
Ki
: 积分增益 Ki 的值
Kd
:导数增益 Kd 的值
setpoint
:PID 将尝试达到的初始设定值
sample_time
:控制器在生成新输出值之前应等待的时间(以秒为单位)。PID在不断调用时(例如在循环期间)效果最佳,但设置了采样时间,以便每次更新之间的时间差(接近)恒定。如果设置为“None”,则 PID 将在每次调用时计算新的输出值。
output_limits
:要使用的初始输出限制,以具有 2 个元素的可迭代形式给出,例如:(下部、上部)。输出永远不会低于下限或高于上限。也可以将任一限制设置为“None”,以在该方向上没有限制。设置输出限值还可以避免积分饱和,因为积分项永远不会超过极限。
auto_mode
:是否应启用控制器(自动模式)或不使用控制器(手动模式)
proportional_on_measurement
:是否应直接在输入上计算比例项,而不是在误差上计算(这是传统方法)。使用按比例测量可避免某些类型系统的过冲。
error_map
:将错误值转换为另一个受约束值的函数。
reset()
:重置 PID 控制器内部。
这会将每个项设置为 0,并清除积分、最后一个输出和最后一个输入(导数计算)。
set_auto_mode(enabled, last_output=None)
:启用或禁用 PID 控制器,可选择设置最后一个输出值。如果某些系统已被手动控制并且PID应该接管,这将非常有用。在这种情况下,通过将自动模式设置为 False 来禁用 PID,稍后当 PID 应重新打开时,传递最后一个输出变量(控制变量),当 PID 设置为自动模式时,它将被设置为起始 项。
tunings
:控制器用作元组的调优:(Kp,Ki,Kd)。
from simple_pid import PID
pid = PID(1, 0.1, 0.05, setpoint=1)
v = controlled_system.update(0)
while True:
control = pid(v)
v = controlled_system.update(control)
示例
import time
import matplotlib.pyplot as plt
from simple_pid import PID
class WaterBoiler:
"""
Simple simulation of a water boiler which can heat up water
and where the heat dissipates slowly over time
"""
def __init__(self):
self.water_temp = 20
def update(self, boiler_power, dt):
if boiler_power > 0:
# Boiler can only produce heat, not cold
self.water_temp += 1 * boiler_power * dt
# Some heat dissipation
self.water_temp -= 0.02 * dt
return self.water_temp
if __name__ == '__main__':
boiler = WaterBoiler()
water_temp = boiler.water_temp
pid = PID(5, 0.01, 0.1, setpoint=water_temp)
pid.output_limits = (0, 100)
start_time = time.time()
last_time = start_time
# Keep track of values for plotting
setpoint, y, x = [], [], []
while time.time() - start_time < 10:
current_time = time.time()
dt = current_time - last_time
power = pid(water_temp)
water_temp = boiler.update(power, dt)
x += [current_time - start_time]
y += [water_temp]
setpoint += [pid.setpoint]
if current_time - start_time > 1:
pid.setpoint = 100
last_time = current_time
plt.plot(x, y, label='measured')
plt.plot(x, setpoint, label='target')
plt.xlabel('time')
plt.ylabel('temperature')
plt.legend()
plt.show()
pyPID(离散PID)
链接:https://github.com/egrissino/pyPID
ivPID(连续PID)
链接:https://github.com/ivmech/ivPID