diff options
-rw-r--r-- | pid.py | 91 | ||||
-rw-r--r-- | rpi-temp-control.py | 60 |
2 files changed, 151 insertions, 0 deletions
@@ -0,0 +1,91 @@ +#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, Set_Point=0.0): + + 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=Set_Point + 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 diff --git a/rpi-temp-control.py b/rpi-temp-control.py new file mode 100644 index 0000000..d99824a --- /dev/null +++ b/rpi-temp-control.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python3 + +## +# rpi-temp-control +# +# +# +# Matt Kohls + +import subprocess +from gpiozero import Motor +from pid import PID +from time import sleep + +# Defaults +TEMP_TARGET = float(47.0) +FAN_PIN = 17 # Pin the fan control is tied to +DUMMY_PIN = 18 # Any unused pin. Used to setup Motor from gpiozero +MIN_FAN_SPEED = 80 / 100 + +## Grabs Temperature of GPU/CPU +# +# @return temperature of GPU/CPU +def grab_temp(): + try: + file = open("/sys/class/thermal/thermal_zone0/temp", "r") + val = int(file.readline()) / 1000 + file.close() + return val + except: + print("Error reading from thermal zone") + return 0 + +# Initial loop setup +ploop = PID(1, 1, .02, Integrator_max=100, Integrator_min=0, Set_Point=TEMP_TARGET) +cycle = 1 +fan = Motor(FAN_PIN, DUMMY_PIN) +fan.forward(cycle) +last_duty_cycle = 0 +last_temp = 0 + +while True: + sleep(1) + temp = grab_temp() + print(temp) + cycle_change = (ploop.update(temp)) * -1 + cycle = (100 + int(cycle_change)) / 100 # Since fan.forward() wants a number between 0 and 1 + + if cycle <= .2: + cycle = 0 + elif cycle > 1: + cycle = 1 + elif cycle < MIN_FAN_SPEED: + cycle = MIN_FAN_SPEED + + if cycle == 0: + fan.stop() + elif last_duty_cycle != cycle: + fan.forward(cycle) + last_duty_cycle = cycle
\ No newline at end of file |