Skip to main content

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 /opt/raspi-fan-control/bin/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 commands:

# Restart after config changes
sudo /opt/raspi-fan-control/bin/raspi-fan-control-install

# View logs (follow them)
sudo journalctl -u raspi-fan-control -f

Metadata

Release files for raspi-fan-control 0.3.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for raspi-fan-control 0.3.1
File Size Uploaded Provenance
raspi_fan_control-0.3.1.tar.gz 19.9 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for raspi-fan-control 0.3.1
File Interpreter ABI Platform
raspi_fan_control-0.3.1-py3-none-any.whl Python 3 none any Details

Total release size: 43.7 kB

Release files / raspi_fan_control-0.3.1.tar.gz

Download URL raspi_fan_control-0.3.1.tar.gz
Size 19.9 kB
Tags Source
SHA-256 checksum
How to use checksums
fc1b89bc43b075438bff1e4d16c883890651950a117e45995170558dbfafc98c
BLAKE2b-256 checksum
How to use checksums
bc4ad34f6bee12c585b71a4c601ead561cf8057f8e37fd4d503d407974be62da
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.0

Release files / raspi_fan_control-0.3.1-py3-none-any.whl

Download URL raspi_fan_control-0.3.1-py3-none-any.whl
Size 23.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2675f5815b76cb061ef335a7705fa89c1ee9e57968aca2a769df40bd7bd7fa76
BLAKE2b-256 checksum
How to use checksums
ada0cb8774a79854dcdb2644c4c9ce8b4b05e0820dc7ed0713a5553d931c3353
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.0

Security for raspi-fan-control 0.3.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.3.1 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page