-
Notifications
You must be signed in to change notification settings - Fork 0
/
fan_control_script
executable file
·162 lines (133 loc) · 6.04 KB
/
fan_control_script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#!/usr/bin/python3
# This script should run in the background on raspberry pi boot
# The second script should be used to view fan stats and to control the fan
import RPi.GPIO as GPIO
import subprocess
import time
import multiprocessing
import socket
# from multiprocessing import shared_memory as shm
FAN_PIN = 12 # pwm pin to which the fan control is connected, CHECK PIN NUMBERINGS CAREFULLY!
PWM_FREQ = 10 # pwm frequency, change this if the fan makes noise or if the fan misbehaves
ON_THRESHOLD = 65 # temperature above which the fan starts
OFF_THRESHOLD = 55 # temperature below which the fan stops
THROTTLE_THRESHOLD = 75 # temperature above which the fan should spin at maximum speed
# the lower limit on the duty cycle on the fan's pwm pin (The fan does not spin below this)
MIN_PWM = 20
SLEEP_INTERVAL = 5 # how often to check for a temperature change (in second)
PORT = 9099 # change this to the same number in both the scripts if the port clashes with some other port
GPIO.setwarnings(False) # do not display warnings
GPIO.setmode(GPIO.BOARD) # set pin numbering mode
GPIO.setup(FAN_PIN, GPIO.OUT) # set fan pin to output
fan = GPIO.PWM(FAN_PIN, PWM_FREQ) # fan pwm object
fan_on = False # a control variable to see if the fan is on or off
fan_speed = 0 # variable to store the fan speed as % duty cycle
# fan_ctl_speed_Value = shm
# This function taken from https://howchoo.com/g/ote2mjkzzta/control-raspberry-pi-fan-temperature-python
def get_temp():
"""Get the core temperature.
Run a shell script to get the core temp and parse the output.
Raises:
RuntimeError: if response cannot be parsed.
Returns:
float: The core temperature in degrees Celsius.
"""
output = subprocess.run(['vcgencmd', 'measure_temp'], capture_output=True)
temp_str = output.stdout.decode()
try:
return float(temp_str.split('=')[1].split('\'')[0])
except (IndexError, ValueError):
raise RuntimeError('Could not parse temperature output.')
def handle_server(server, shared_fan_speed, shared_fan_control):
while True:
# keep listening for incoming connections
server.listen()
# get client info and message
clientsocket,addr = server.accept()
# print("Got a connection from %s" % str(addr))
request = clientsocket.recv(1024)
request = request.decode('ascii')
msg = ""
if request == "status":
msg = "\nPi Fan Control:\n\nFan Active: "
if shared_fan_control.value == 1:
msg += "Yes"
elif shared_fan_control.value == 0:
msg += "No"
msg+="\nFan State: "
if shared_fan_speed.value == 0:
msg += "Off"
else:
msg += "On"
msg += "\n"
msg += "Fan Speed: "
msg += str(shared_fan_speed.value)
msg += "%\nCPU Temp: "
msg += str(round(get_temp()))
msg += "'C\n"
elif request == "toggle":
if shared_fan_control.value == 1:
shared_fan_control.value = 0
msg = "Fan is now Inactive!"
elif shared_fan_control.value == 0:
shared_fan_control.value = 1
msg = "Fan is now Active!"
else:
msg = "Error! Invalid command!"
clientsocket.send(msg.encode('ascii'))
clientsocket.close()
if __name__ == '__main__':
# Validate the on and off thresholds
if OFF_THRESHOLD >= ON_THRESHOLD:
raise RuntimeError('OFF_THRESHOLD must be less than ON_THRESHOLD')
# Initialise Socket Server
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = socket.gethostname()
port = PORT
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind((host, port))
shared_fan_speed = multiprocessing.Value('i') # shared variable to send fan speed to other thread
shared_fan_control = multiprocessing.Value('i') # shared variable to toggle the fan on or off
shared_fan_control.value=1 # set to on
# start process to respond to queries
p = multiprocessing.Process(target=handle_server, args=(server, shared_fan_speed, shared_fan_control))
p.start()
# infinite loop to adjust fans
while True:
temp = get_temp()
if shared_fan_control.value == 1: # do all this only if the shared variable is on
if temp > THROTTLE_THRESHOLD: # if the temperature goes above the throttle limit, run fan at full speed
if not fan_on:
fan_speed = 100
fan.start(fan_speed)
fan_on = True
elif fan_speed != 100:
fan_speed = 100
fan.ChangeDutyCycle(fan_speed)
elif temp > ON_THRESHOLD: # if the temperature goes above the ON Threshold, run the fans at a speed proportional to the temperature
fan_speed = (temp - OFF_THRESHOLD) / \
(THROTTLE_THRESHOLD - OFF_THRESHOLD)
fan_speed *= (100 - MIN_PWM)
fan_speed += MIN_PWM
fan_speed = round(fan_speed)
# fan_ctl_speed_shm.buf[0] = fan_speed # write fan_speed to shared memory
# print(fan_speed)
if not fan_on:
fan.start(fan_speed)
fan_on = True
else:
fan.ChangeDutyCycle(fan_speed)
elif temp < OFF_THRESHOLD: # if the temperature dips below the OFF Threshold, turn off the fan completely
if fan_on:
fan.stop()
fan_speed = 0
fan_on = False
elif shared_fan_control.value == 0: # stop the fan if the shared control variable is switched off
if fan_on:
fan.stop()
fan_speed=0
fan_on = False
# update shared value
shared_fan_speed.value = fan_speed
# sleep before sampling the temperature again
time.sleep(SLEEP_INTERVAL)