我想创建一个PID控制器。
作为输入,我有两个csv文件,一个具有我想要实现的所需行为,另一个具有直流电机的电流和电压的实际值。我可以读取csv文件上的数据,然后使用PID控制器(下面的代码)。
由于我刚开始使用Python,我想知道如何对csv文件的每个电流和电压值使用此类(PID)并绘制两个不同的轨迹(我的输入文件中的所需轨迹)以及PID控制器的实际轨迹。)
class PID:
"""
Discrete PID control
"""
def __init__(self, P=2.0, I=0.0, D=1.0, Derivator=0, Integrator=0, Integrator_max=500, Integrator_min=-500):
self.Kp=P
self.Ki=I
self.Kd=D
self.Derivator=Derivator
self.Integrator=Integrator
self.Integrator_max=Integrator_max
self.Integrator_min=Integrator_min
self.set_point=0.0
self.error=0.0
def update(self,current_value):
"""
Calculate PID output value for given reference input and feedback
"""
self.error = self.set_point - current_value
self.P_value = self.Kp * self.error
self.D_value = self.Kd * ( self.error - self.Derivator)
self.Derivator = self.error
self.Integrator = self.Integrator + self.error
if self.Integrator > self.Integrator_max:
self.Integrator = self.Integrator_max
elif self.Integrator < self.Integrator_min:
self.Integrator = self.Integrator_min
self.I_value = self.Integrator * self.Ki
PID = self.P_value + self.I_value + self.D_value
return PID
def setPoint(self,set_point):
"""
Initilize the setpoint of PID
"""
self.set_point = set_point
self.Integrator=0
self.Derivator=0
def setIntegrator(self, Integrator):
self.Integrator = Integrator
def setDerivator(self, Derivator):
self.Derivator = Derivator
def setKp(self,P):
self.Kp=P
def setKi(self,I):
self.Ki=I
def setKd(self,D):
self.Kd=D
def getPoint(self):
return self.set_point
def getError(self):
return self.error
def getIntegrator(self):
return self.Integrator
def getDerivator(self):
return self.Derivator
答案 0 :(得分:1)
我知道这是一个老问题,但我会尝试补充@ tom10的答案以供参考
如果你在Raspberry pi上尝试这个,我假设你想要一个Velocity PID控制器,你可以使用这个代码
你可以阅读Interrupts如何处理这个优秀的教程
http://raspi.tv/2013/how-to-use-interrupts-with-python-on-the-raspberry-pi-and-rpi-gpio-part-2
此外,您还可以在此链接上查看如何使用PWM类
https://sourceforge.net/p/raspberry-gpio-python/wiki/PWM/
import pid
import time
dc_pid = pid.PID(2.5, .1, 1.5)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(self.pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.add_event_detect(22, GPIO.FALLING, callback=self.interrupt_function,bouncetime=5) #GPIO where encoders signal is conected
def interrupt_function():
"""on this function you make calculations depending on what PID you are planning to use , for example if you are planning to do a Velocity PID , and the encoder signal is connected to a GPIO pin you should take time stamps and convert signal frecuency to velocity , save it as a variable and then update that value to the PID controller"""
error = dc_pid.update(velocity)
#once you get your error you actuate it to your DC motor , via PWM , previously mapped function depending on your dc motor voltage and velocity it has depending on the PWM's duty cycle
pwm.ChangeDutyCycle(error/15) # or whatever your convertion is
readings = [1, 3, 5, 7, 12, 15, 17, 19, 27, 24, 24, 26]
initial_time = time.time
for reading in readings:
dc_pid.setPoint(reading)
time.sleep(10)
在新文件上使用此代码,它将每隔10秒基于csv读数设置一个新的setPoint,并启动该速度,位置或您希望PID控制的任何内容,在引脚22上每次中断时更新其值
希望它有助于未来的人们想要知道如何使用python实现PID,
考虑到您应首先设计控制回路,定义PID输入以及如何管理输出
答案 1 :(得分:0)
基本上,看起来它设计为首先使用一些参数实例化它,然后重复调用update(val)
来运行。我想,就像这样:
readings = [1, 3, 5, 7, 12, 15, 17, 19, 27, 24, 24, 26]
x = PID(2.5, .1, 1.5, Integrator_min=-100)
for reading in readings:
current_pid = x.update(reading)
# if you want to know something else, like the error, you do
err = x.getError()
顺便说一下,它不是用很棒的Python风格编写的。例如,所有这些setter和getter方法都会分散注意力。