aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pid.py91
-rw-r--r--rpi-temp-control.py60
2 files changed, 151 insertions, 0 deletions
diff --git a/pid.py b/pid.py
new file mode 100644
index 0000000..2923360
--- /dev/null
+++ b/pid.py
@@ -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