0
#The recipe gives simple implementation of a Discrete Proportional-Integral-Derivative (PID) controller. PID controller gives output value for error between desired reference input and measurement feedback to minimize error value.
#More information: http://en.wikipedia.org/wiki/PID_controller
#
#cnr437@gmail.com
#
####### Example #########
#
#p=PID(3.0,0.4,1.2)
#p.setPoint(5.0)
#while True:
#     pid = p.update(measurement_value)
#
#


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 want to use this code to control temperature of tank with hot water. The input is the actual temperature of the water and the output sholud be just information for the gas stove to heat or to do nothing (1 or 0). But executing this file I receive the pid value. For example the setpoint is 20 degrees and the measurment of 15 degress gives the answer of 23 degrees. Now How should I interpret the asnwer. Just heat? till the next measurment? obviolsuly when the temperature will reach 20 degrees and above the pid value will be below 0 i.e = -5. and obviolusly it means stop heating. But Does the output result give me anything more than if >0 heat, if =<0 dont heat.

Jonas
  • 121,568
  • 97
  • 310
  • 388
6y3e
  • 1
  • 1

1 Answers1

0

It really depends on how you want to control your gas valve? Some use PIDs to control the proportion of a duty cycle. If your tank is large and slow to heat up, you might want something like a 10 minute fire/no fire cycle with the fire time constrained between 10 seconds and a full 600 second continuous burn, and adjusted by the PID.

If you were controlling it by hand, how fast would you want to cycle turning the flame on and off? And how close to the target temp would you start tapering off? For instance, if at full burn, the tank increases at 0.5C/minute, and takes 10 minutes to stabilize after you turn it off, you might sample/update PID every 60 seconds, and start tapering off 20 minutes or 10C away from your setpoint.

For that I'd sample that slow (60 secs?) and use the PID to make the decisions as to how many seconds to run the fire during the burn cycle. For example: dt=60sec, kP = 60sec/10degC=6s/degC_error, kI= 0.6 seconds/integrated_degC_error, kD=0.

Dave X
  • 4,831
  • 4
  • 31
  • 42