├── LICENSE
├── README.md
├── automagic-fan.service
├── config.json
├── fanctl.py
├── install.sh
└── uninstall.sh
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Marc Uecker
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # jetson-fan-ctl
2 | Automagic fan control for the Nvidia Jetson Nano
3 |
4 | ## Requirements:
5 |
6 | ### Hardware
7 | You will need a 5V PWM fan for this to make any sense.
8 | I used the **Noctua nf-a4x20 5V PWM** fan.
9 |
10 | Additionally, I recommend you use the barrel jack with a 4A power supply.
11 |
12 | ### Software
13 | I will assume you use the standard image on your jetson nano.
14 |
15 | Python 3 should be pre-installed on the jetson nano.
16 | You can check this using python3 --version
17 | (3.5 or higher should be fine.)
18 | otherwise, you can install it with
19 |
20 | sudo apt install python3-dev
21 |
22 |
23 | ## How to install:
24 | run
25 |
26 | sudo ./install.sh
27 |
28 | The script will automatically run at boot time.
29 |
30 | It's a set-it-and-forget-it type thing, unless you want to mess with the fan speeds.
31 |
32 | ## How to customize:
33 | open /etc/automagic-fan/config.json with your favorite editor (I'm using nano):
34 |
35 | sudo nano /etc/automagic-fan/config.json
36 |
37 | you will find the following lines:
38 |
39 | {
40 | "FAN_OFF_TEMP":20,
41 | "FAN_MAX_TEMP":50,
42 | "UPDATE_INTERVAL":2,
43 | "MAX_PERF":1
44 | }
45 |
46 | FAN_OFF_TEMP
is the temperature (°C) below which the fan is turned off.
47 | FAN_MAX_TEMP
is the temperature (°C) above which the fan is at 100% speed.
48 | The script interpolates linearly between these two points.
49 |
50 | UPDATE_INTERVAL
tells the script how often to update the fan speed (in seconds).
51 | MAX_PERF
values greater than 0 maximize system performance by setting the CPU and GPU clock speeds to the maximum.
52 |
53 | You can use either integers (like 20) or floating point numbers (like 20.125) in each of these fields.
54 | The temperature precision of the thermal sensors is 0.5 (°C), so don't expect this to be too precise.
55 |
56 | Any changes in the script will be will be applied after the next reboot.
57 | You can run
58 |
59 | sudo service automagic-fan restart
60 |
61 | to apply changes immediately.
62 |
63 | If you suspect something went wrong, please check:
64 |
65 | sudo service automagic-fan status
66 |
67 | ## How to contribute:
68 | Feel Free to open Issues or Pull requests on this Repository.
69 |
70 | If you find this tool useful, you can buy me a coffe:
71 |
72 | [](https://paypal.me/pyrestone)
73 |
--------------------------------------------------------------------------------
/automagic-fan.service:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=Automagic fan control
3 |
4 | [Service]
5 | Type=simple
6 | ExecStartPre=/bin/sleep 5
7 | ExecStart=/usr/bin/python3 -u /usr/local/bin/automagic-fan/fanctl.py
8 | ExecStopPost=/bin/sh -c '/bin/echo 0 > /sys/devices/pwm-fan/target_pwm'
9 | User=root
10 | StandardOutput=journal+console
11 | Restart=always
12 |
13 | [Install]
14 | WantedBy=multi-user.target
15 |
--------------------------------------------------------------------------------
/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "FAN_OFF_TEMP":20,
3 | "FAN_MAX_TEMP":50,
4 | "UPDATE_INTERVAL":2,
5 | "MAX_PERF":1
6 | }
7 |
--------------------------------------------------------------------------------
/fanctl.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 |
3 | import time
4 | import json
5 | import subprocess as sp
6 |
7 | try:
8 | with open("/etc/automagic-fan/config.json","r") as file:
9 | config=json.load(file)
10 | FAN_OFF_TEMP=config["FAN_OFF_TEMP"]
11 | FAN_MAX_TEMP=config["FAN_MAX_TEMP"]
12 | UPDATE_INTERVAL=config["UPDATE_INTERVAL"]
13 | MAX_PERF=config["MAX_PERF"]
14 | except:
15 | print("error loading /etc/automagic-fan/config.json.\nPlease check your config file.\nProceeding with default settings.")
16 | FAN_OFF_TEMP=20
17 | FAN_MAX_TEMP=50
18 | UPDATE_INTERVAL=2
19 | MAX_PERF=0
20 |
21 | if MAX_PERF>0:
22 | print("Maximizing clock speeds with jetson_clocks")
23 | try:
24 | sp.call("jetson_clocks")
25 | except Exception as e:
26 | print(f"Error calling jetson_clocks: {repr(e)}")
27 |
28 |
29 | def read_temp():
30 | with open("/sys/devices/virtual/thermal/thermal_zone0/temp","r") as file:
31 | temp_raw=file.read()
32 | temp=int(temp_raw)/1000
33 | return temp
34 |
35 | def fan_curve(temp):
36 | spd=255*(temp-FAN_OFF_TEMP)/(FAN_MAX_TEMP-FAN_OFF_TEMP)
37 | return int(min(max(0,spd),255))
38 |
39 | def set_speed(spd):
40 | with open("/sys/devices/pwm-fan/target_pwm","w") as file:
41 | file.write(f"{spd}")
42 |
43 | print("Setup complete.\nRunning normally.")
44 | last_spd=-1
45 | while True:
46 | temp=read_temp()
47 | spd=fan_curve(temp)
48 | if spd!=last_spd:
49 | set_speed(spd)
50 | last_spd=spd
51 | time.sleep(UPDATE_INTERVAL)
52 |
53 |
54 |
--------------------------------------------------------------------------------
/install.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #Require sudo
4 | if [ $EUID != 0 ]; then
5 | sudo "$0" "$@"
6 | exit $?
7 | fi
8 |
9 | echo "settling to /usr/local/bin/automagic-fan/..."
10 | rm -r /usr/bin/automagic-fan/ 2>/dev/null
11 | mkdir -p /usr/local/bin/automagic-fan
12 | cp fanctl.py /usr/local/bin/automagic-fan/
13 | echo "done"
14 |
15 | echo "adding service to /lib/systemd/system/..."
16 | cp automagic-fan.service /lib/systemd/system/
17 | chmod 644 /lib/systemd/system/automagic-fan.service
18 | echo "done"
19 |
20 | echo "creating config at /etc/automagic-fan/"
21 | mkdir /etc/automagic-fan/
22 | cp config.json /etc/automagic-fan/
23 | chmod 664 /etc/automagic-fan/config.json
24 | echo "done"
25 |
26 | echo "starting and enabling service..."
27 | systemctl daemon-reload
28 | systemctl start automagic-fan
29 | systemctl enable automagic-fan
30 | echo "done"
31 |
32 | echo "automagic-fan installed sucessfully!"
33 | echo ""
34 | echo "To configure, edit /etc/automagic-fan/config.json (needs sudo)"
35 |
--------------------------------------------------------------------------------
/uninstall.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #Require sudo
4 | if [ $EUID != 0 ]; then
5 | sudo "$0" "$@"
6 | exit $?
7 | fi
8 |
9 | echo "removing service..."
10 | systemctl stop automagic-fan
11 | systemctl disable automagic-fan
12 | echo "done"
13 |
14 |
15 | echo "removing /usr/local/bin/automagic-fan/..."
16 | rm -r /usr/local/bin/automagic-fan
17 | rm -r /usr/bin/automagic-fan 2>/dev/null
18 | echo "done"
19 |
20 | echo "removing service from /lib/systemd/system/..."
21 | rm /lib/systemd/system/automagic-fan.service
22 | echo "done"
23 |
24 | echo "removing config at /etc/automagic-fan/"
25 | rm -r /etc/automagic-fan/
26 | echo "done"
27 |
28 | echo "reloading services"
29 | systemctl daemon-reload
30 | echo "done"
31 |
32 | echo "automagic-fan uninstalled sucessfully!"
33 | echo ""
34 | echo "If you are dissatisfied,"
35 | echo "please create an issue at the repo."
36 |
--------------------------------------------------------------------------------