Skip to main content

Automated fan control for Raspberry Pi based on native temperature sensors and customizable fan curves

Project description

raspi-fan-control

Automated PWM fan control for Raspberry Pi. Reads temperature from the CPU thermal zone and drives one or more fans along a configurable curve.

Requirements

  • Raspberry Pi running a Debian-based OS (Raspberry Pi OS, Ubuntu, etc.)
  • Python 3.11+
  • A properly wired up PWM fan:
    • The fan's PWM pin should be wired to GPIO pin 18 (or any other pin that supports PWM)
    • The fan's RPM pin should be wired to GPIO pin 15.
    • The fan's power and ground pins connected to the power supply (technically the Raspberry Pi will power a fan, but it's not ideal and you'll be required to use a 5V fan)
  • Root access for installation

Note that the default configuration is set up for a Noctua PWM fan, so by using GPIO pins 18 and 15 this is basically plug and play! However, tweaking the configuration for other fans should be easy.

Installation

1. Create a virtual environment

sudo python3 -m venv /opt/raspi-fan-control

2. Install the package

Install directly from PyPI:

sudo /opt/raspi-fan-control/bin/pip install raspi-fan-control

3. Run the install script

The install script writes the systemd service file, enables it, and starts the service:

sudo /opt/raspi-fan-control/bin/raspi-fan-control-install

The service file is written to /etc/systemd/system/raspi-fan-control.service. Need to update something? No worries, make the change to the template (see Configuration below), then re-run the install script to apply changes.

Configuration

All configuration is supplied as Environment= entries in the systemd service file at /etc/systemd/system/raspi-fan-control.service. The prefix RFC__ maps to the top-level config, and double underscores (__) delimit nesting.

After editing the service file, apply changes with:

sudo raspi-fan-control-install

Top-level

Variable Description Example
RFC__POLLING_INTERVAL_MS How often to poll temperature sensors (ms) 1000

Fan (RFC__FANS__<index>__...)

Variable Description Example
RFC__FANS__0__ID Unique fan identifier primary
RFC__FANS__0__NAME Fan display name Noctua

PWM (RFC__FANS__<index>__PWM__...)

Variable Description Example
RFC__FANS__0__PWM__PIN__NUMBER GPIO pin number 18
RFC__FANS__0__PWM__PIN__MODE Pin numbering mode (gpio or wpi) gpio
RFC__FANS__0__PWM__FREQUENCY_HZ PWM frequency in Hz 25000
RFC__FANS__0__PWM__DATA_RANGE PWM value range 1024

RPM (RFC__FANS__<index>__RPM__...)

Variable Description Example
RFC__FANS__0__RPM__PIN__NUMBER Tachometer GPIO pin number 15
RFC__FANS__0__RPM__PIN__MODE Pin numbering mode (gpio or wpi) gpio
RFC__FANS__0__RPM__PIN__USE_INTERNAL_PULLDOWN Enable internal pull-down resistor true
RFC__FANS__0__RPM__RPM_MAX Maximum fan RPM 5000
RFC__FANS__0__RPM__PULSES_PER_REVOLUTION Tachometer pulses per revolution 2

Fan curve (RFC__FANS__<index>__CURVE__POINTS__<index>__...)

The curve maps a normalized temperature (0.0-1.0) to a normalized duty cycle (0.0-1.0). Add as many points as needed; they are interpolated linearly. By default it will use a simple linear fan curve from (0.0, 0.0) to (1.0, 1.0).

Variable Description Example
RFC__FANS__0__CURVE__POINTS__0__INPUT_X Normalized temperature input 0.0
RFC__FANS__0__CURVE__POINTS__0__OUTPUT_Y Normalized duty cycle output 0.0

Temperature sensor (RFC__TEMPERATURE_SENSORS__<index>__...)

Note that the ...__TEMPERATURE_MIN_C and ...__TEMPERATURE_MAX_C values define the upper and lower bounds that the fan curve will use when determining how fast to spin the fans. Currently the values are sensible defaults for the Raspberry Pi, but you may wish to tweak them for more complex (or non Raspberry Pi based) scenarios.

Variable Description Example
RFC__TEMPERATURE_SENSORS__0__ID Unique sensor identifier cpu
RFC__TEMPERATURE_SENSORS__0__FLAVOR Sensor type (currently cpu) cpu
RFC__TEMPERATURE_SENSORS__0__TEMPERATURE_MIN_C Temperature at 0% duty cycle (°C) 40
RFC__TEMPERATURE_SENSORS__0__TEMPERATURE_MAX_C Temperature at 100% duty cycle (°C) 80
RFC__TEMPERATURE_SENSORS__0__FANS__0 Fan ID to control primary

Example service file

Check out the systemd service file.

Managing the service

It's a systemd service so it can be managed via systemctl like any other, but here's a couple handy scripts:

# Restart after config changes
sudo raspi-fan-control-install

# View logs
sudo journalctl -u raspi-fan-control -f

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

raspi_fan_control-0.3.0.tar.gz (19.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

raspi_fan_control-0.3.0-py3-none-any.whl (23.5 kB view details)

Uploaded Python 3

File details

Details for the file raspi_fan_control-0.3.0.tar.gz.

File metadata

  • Download URL: raspi_fan_control-0.3.0.tar.gz
  • Upload date:
  • Size: 19.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.0

File hashes

Hashes for raspi_fan_control-0.3.0.tar.gz
Algorithm Hash digest
SHA256 1a5446161832376c03b12da4f3e714146a817e30694d7f2696ea8a7aa27b1425
MD5 ccd3ce1e8a58c72c434bce1d5e11b949
BLAKE2b-256 ea78c5237d32a41aa091f041308cbd660a0b5dbd63a079fdc6c2eeda625381bb

See more details on using hashes here.

File details

Details for the file raspi_fan_control-0.3.0-py3-none-any.whl.

File metadata

File hashes

Hashes for raspi_fan_control-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4a111694ddee09a5e42a7966171a906aaefa8496ce65d264cfe46523a1783115
MD5 4c4ca74d7de92835310c0ff71f617c3d
BLAKE2b-256 4fa7c4fc57bfa5110bd4bad4a9886d8ce4154a711194229304cef28e60088e58

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page