├── 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://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](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 | --------------------------------------------------------------------------------