简体   繁体   English

直流电机PID控制器

[英]PID controller for DC motor

I want to create a PID controller.我想创建一个PID控制器。

As input, I have two csv files, one with my desired behavior I want to achieve and the other with the actual values of current and voltage of a DC motor.作为输入,我有两个 csv 文件,一个是我想要实现的期望行为,另一个是直流电机的电流和电压的实际值。 I can read the data on the csv files and then use a PID controller (with the code below).我可以读取 csv 文件上的数据,然后使用 PID 控制器(使用下面的代码)。

Since I just start using Python, I would like to know how to use this class (PID) for each value of current and voltage of the csv files and plot the two different trajectories (the desired trajectory from one of my input files along with the actual trajectory with the PID controller).由于我刚刚开始使用 Python,我想知道如何将此类 (PID) 用于 csv 文件的每个电流和电压值,并绘制两个不同的轨迹(来自我的一个输入文件的所需轨迹以及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

I know this is an old question , but I will try to complement @tom10 answer for reference我知道这是一个老问题,但我会尝试补充@tom10 的答案以供参考

If you are trying this on a Raspberry pi , I'm assuming you want a Velocity PID controller , you could use this code如果您在 Raspberry pi 上尝试此操作,我假设您想要一个 Velocity PID 控制器,您可以使用此代码

you can read how Interrupts work on this excelent tutorial你可以在这个优秀的教程中阅读中断是如何工作的

http://raspi.tv/2013/how-to-use-interrupts-with-python-on-the-raspberry-pi-and-rpi-gpio-part-2 http://raspi.tv/2013/how-to-use-interrupts-with-python-on-the-raspberry-pi-and-rpi-gpio-part-2

Also you can see how to use PWM class on this link您还可以在此链接上看到如何使用 PWM 类

https://sourceforge.net/p/raspberry-gpio-python/wiki/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)

Using this code on a new file , it will set a new setPoint based on csv readings every 10 seconds , and actuating that velocity , or position , or whatever you want your PID to control , updating its values every interruption on pin 22在新文件上使用此代码,它将每 10 秒根据 csv 读数设置一个新的 setPoint,并启动该速度、或位置或您希望 PID 控制的任何内容,在引脚 22 上的每次中断时更新其值。

hope it helps future people wanting to know how to implement a PID using python ,希望它可以帮助未来想要知道如何使用 python 实现 PID 的人,

Taking in count that you should first design your control loop , defining your PID inputs , and how to manage outputs考虑到您应该首先设计您的控制回路,定义您的 PID 输入,以及如何管理输出。

Basically, it looks like it's designed to be run by first instantiating it with some parameters, and then calling update(val) repeatedly.基本上,它看起来像是通过首先使用一些参数实例化它,然后重复调用update(val)来运行的。 I think, something like this:我想,是这样的:

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()

By the way, it's not written in great Python style.顺便说一句,它不是用伟大的 Python 风格编写的。 For example, all these setter and getter methods are distracting.例如,所有这些 setter 和 getter 方法都让人分心。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM