PHPackages                             dept-of-scrapyard-robotics/pwm-fan-control - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. dept-of-scrapyard-robotics/pwm-fan-control

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

dept-of-scrapyard-robotics/pwm-fan-control
==========================================

A Laravel package for controlling PWM-controlled fans.

0.2.0(6mo ago)061MITPHPPHP ^8.3

Since Oct 21Pushed 6mo agoCompare

[ Source](https://github.com/projectsaturnstudios/dosr_pwm-fan-control)[ Packagist](https://packagist.org/packages/dept-of-scrapyard-robotics/pwm-fan-control)[ RSS](/packages/dept-of-scrapyard-robotics-pwm-fan-control/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (2)Versions (2)Used By (1)

PWM Fan Control
===============

[](#pwm-fan-control)

A modern PHP 8.3+ library for controlling PWM-driven fans on embedded Linux devices. This package provides an elegant, object-oriented API with fluent method chaining, smooth ramping, temperature-based control, and coordinated effects.

Features
--------

[](#features)

- **Object-Oriented API**: Clean, fluent interface for fan control
- **Speed Control**: Precise percentage-based speed control (0-100%)
- **Smooth Effects**: Ramping, pulsing, and custom speed curves
- **Temperature Control**: Automatic fan speed adjustment based on CPU temperature
- **Speed Presets**: Convenient named speed levels (low, medium, high, full)
- **Type-Safe**: Full PHP 8.3+ type hints and return type declarations
- **Chainable Methods**: Fluent API for readable, expressive code
- **Comprehensive Testing**: Full Pest v4 test suite included

Requirements
------------

[](#requirements)

- PHP 8.3 or higher
- php-pwm extension installed
- Embedded Linux device with PWM support (Jetson Orin Nano, Raspberry Pi, etc.)
- PWM device nodes exported (e.g., `/sys/class/pwm/pwmchip3/pwm0`)

Installation
------------

[](#installation)

### Install via Composer

[](#install-via-composer)

```
composer require dept-of-scrapyard-robotics/pwm-fan-control

```

### Install php-pwm Extension

[](#install-php-pwm-extension)

Before using this library, you must install the php-pwm extension on your embedded Linux device. See the [php-pwm extension installation guide](https://github.com/dept-of-scrapyard-robotics/php-pwm) for complete instructions.

### Export PWM Device

[](#export-pwm-device)

Before first use, export the PWM device:

```
# Export PWM channel 0 on chip 3
echo 0 | sudo tee /sys/class/pwm/pwmchip3/export

# This creates /sys/class/pwm/pwmchip3/pwm0/

```

Core Concepts
-------------

[](#core-concepts)

### PWMFan

[](#pwmfan)

A `PWMFan` is an object-oriented wrapper around the php-pwm extension's `Pwm` class. It represents a single controllable fan connected to a specific PWM device path.

#### Basic Usage

[](#basic-usage)

```
use DeptOfScrapyardRobotics\PWM\Fans\PWMFan;

// Create a fan controller
$fan = new PWMFan('/sys/class/pwm/pwmchip3/pwm0');

// Set fan speed to 50%
$fan->setSpeed(50.0);

// Turn on at last known speed
$fan->on();

// Turn off
$fan->off();

// Check status
echo "Speed: " . $fan->getSpeed() . "%\n";
echo "Running: " . ($fan->isRunning() ? 'Yes' : 'No') . "\n";

```

API Reference
-------------

[](#api-reference)

### Construction

[](#construction)

```
public function __construct(string $pwm_device_path, int $frequency = 1000)

```

Creates a new PWMFan instance for the specified PWM device.

- **Parameters:**
    - `$pwm_device_path` - Path to PWM device (e.g., `/sys/class/pwm/pwmchip3/pwm0`)
    - `$frequency` - PWM frequency in Hz (default: 1000)

**Example:**

```
$fan = new PWMFan('/sys/class/pwm/pwmchip3/pwm0', 1000);

```

### Core Operations

[](#core-operations)

#### on()

[](#on)

```
public function on(): static

```

Turn the fan on at the last known speed (default 50%).

```
$fan->on();

```

#### off()

[](#off)

```
public function off(): static

```

Turn the fan off (disable PWM output).

```
$fan->off();

```

#### setSpeed()

[](#setspeed)

```
public function setSpeed(float $percent): static

```

Set the fan speed as a percentage.

- **Parameters:**
    - `$percent` - Speed percentage (0.0 - 100.0)
- **Returns:** `$this` for method chaining
- **Throws:** `InvalidArgumentException` if speed is out of range

```
$fan->setSpeed(75.0);  // Set to 75%

```

#### getSpeed()

[](#getspeed)

```
public function getSpeed(): float

```

Get the current fan speed percentage.

```
$speed = $fan->getSpeed();  // Returns 0.0 - 100.0

```

#### isRunning()

[](#isrunning)

```
public function isRunning(): bool

```

Check if the fan is currently running.

```
if ($fan->isRunning()) {
    echo "Fan is on\n";
}

```

#### getStatus()

[](#getstatus)

```
public function getStatus(): array

```

Get detailed fan status information.

- **Returns:** Array with keys:
    - `enabled` (bool)
    - `speed` (float) - Current speed percentage
    - `lastSpeed` (float) - Last known speed
    - `frequency` (int) - PWM frequency in Hz
    - `dutyCycle` (float) - Duty cycle percentage
    - `devicePath` (string) - PWM device path

```
$status = $fan->getStatus();
echo "Speed: {$status['speed']}%\n";
echo "Frequency: {$status['frequency']} Hz\n";

```

### Speed Presets

[](#speed-presets)

#### setPreset()

[](#setpreset)

```
public function setPreset(string $preset): static

```

Set fan speed using named presets.

- **Parameters:**
    - `$preset` - Preset name (case-insensitive): `'off'`, `'low'`, `'medium'`, `'high'`, `'full'`
- **Preset Speeds:**
    - `'off'` - 0%
    - `'low'` - 25%
    - `'medium'` - 50%
    - `'high'` - 75%
    - `'full'` - 100%

```
$fan->setPreset('low');     // 25%
$fan->setPreset('HIGH');    // 75% (case-insensitive)
$fan->setPreset('full');    // 100%

```

### Effects &amp; Animations

[](#effects--animations)

#### rampUp()

[](#rampup)

```
public function rampUp(float $targetSpeed = 100.0, int $duration_ms = 2000, int $steps = 20): static

```

Gradually increase fan speed from current speed to target speed.

- **Parameters:**
    - `$targetSpeed` - Target speed percentage (0.0 - 100.0)
    - `$duration_ms` - Duration in milliseconds
    - `$steps` - Number of intermediate steps

```
// Ramp from current speed to 100% over 3 seconds
$fan->rampUp(100.0, 3000, 30);

```

#### rampDown()

[](#rampdown)

```
public function rampDown(float $targetSpeed = 0.0, int $duration_ms = 2000, int $steps = 20): static

```

Gradually decrease fan speed to target speed.

```
// Ramp down to 25% over 2 seconds
$fan->rampDown(25.0, 2000, 20);

```

#### pulse()

[](#pulse)

```
public function pulse(float $lowSpeed = 30.0, float $highSpeed = 80.0, int $cycles = 3, int $duration_ms = 2000): static

```

Create a pulsing effect by ramping between two speeds.

- **Parameters:**
    - `$lowSpeed` - Low speed percentage
    - `$highSpeed` - High speed percentage
    - `$cycles` - Number of pulse cycles
    - `$duration_ms` - Duration per cycle

```
// Pulse between 30% and 80% three times
$fan->pulse(30.0, 80.0, 3, 2000);

```

### Temperature Control

[](#temperature-control)

#### autoControl()

[](#autocontrol)

```
public function autoControl(float $currentTemp, float $minTemp = 40.0, float $maxTemp = 80.0, float $minSpeed = 25.0): static

```

Automatically adjust fan speed based on temperature.

- **Parameters:**
    - `$currentTemp` - Current temperature in Celsius
    - `$minTemp` - Minimum temperature (fan off below this)
    - `$maxTemp` - Maximum temperature (fan at 100% above this)
    - `$minSpeed` - Minimum fan speed when active

**Behavior:**

- Temperature ≤ `$minTemp`: Fan off
- Temperature ≥ `$maxTemp`: Fan at 100%
- Between: Linear interpolation from `$minSpeed` to 100%

```
$temp = $fan->getCPUTemp();
$fan->autoControl($temp, 40.0, 80.0, 25.0);

```

#### getCPUTemp()

[](#getcputemp)

```
public function getCPUTemp(int $zone = 0): float

```

Read CPU temperature from thermal zone.

- **Parameters:**
    - `$zone` - Thermal zone number (default: 0)
- **Returns:** Temperature in Celsius

```
$temp = $fan->getCPUTemp(0);  // Read from thermal_zone0
echo "CPU Temperature: {$temp}°C\n";

```

Usage Examples
--------------

[](#usage-examples)

### Example 1: Basic Speed Control

[](#example-1-basic-speed-control)

```
use DeptOfScrapyardRobotics\PWM\Fans\PWMFan;

$fan = new PWMFan('/sys/class/pwm/pwmchip3/pwm0');

// Set various speeds
$fan->setSpeed(25.0);  // 25%
sleep(2);

$fan->setSpeed(50.0);  // 50%
sleep(2);

$fan->setSpeed(100.0); // 100%
sleep(2);

// Turn off
$fan->off();

```

### Example 2: Temperature-Based Control

[](#example-2-temperature-based-control)

```
use DeptOfScrapyardRobotics\PWM\Fans\PWMFan;

$fan = new PWMFan('/sys/class/pwm/pwmchip3/pwm0');

// Monitor and adjust fan speed based on temperature
while (true) {
    $temp = $fan->getCPUTemp();
    $fan->autoControl($temp, 40.0, 80.0, 25.0);

    echo "Temp: {$temp}°C, Fan: {$fan->getSpeed()}%\n";
    sleep(2);
}

```

### Example 3: Smooth Ramping Effect

[](#example-3-smooth-ramping-effect)

```
use DeptOfScrapyardRobotics\PWM\Fans\PWMFan;

$fan = new PWMFan('/sys/class/pwm/pwmchip3/pwm0');

// Smooth startup
$fan->rampUp(100.0, 3000, 30);  // Ramp to 100% over 3 seconds
sleep(5);

// Smooth shutdown
$fan->rampDown(0.0, 3000, 30);  // Ramp to 0% over 3 seconds

```

### Example 4: Pulsing Effect

[](#example-4-pulsing-effect)

```
use DeptOfScrapyardRobotics\PWM\Fans\PWMFan;

$fan = new PWMFan('/sys/class/pwm/pwmchip3/pwm0');

// Create breathing effect
$fan->pulse(30.0, 80.0, 5, 2000);  // 5 pulses, 2s each

```

### Example 5: Speed Presets

[](#example-5-speed-presets)

```
use DeptOfScrapyardRobotics\PWM\Fans\PWMFan;

$fan = new PWMFan('/sys/class/pwm/pwmchip3/pwm0');

$fan->setPreset('low');     // 25%
sleep(2);

$fan->setPreset('medium');  // 50%
sleep(2);

$fan->setPreset('high');    // 75%
sleep(2);

$fan->setPreset('full');    // 100%
sleep(2);

$fan->setPreset('off');     // 0%

```

Testing
-------

[](#testing)

The library includes a comprehensive Pest v4 test suite covering unit tests and integration tests.

### Running Tests

[](#running-tests)

```
# Run all tests
composer test

# Run tests quietly
composer test:quiet

# Run with coverage report
composer test:coverage

# Run specific test file
./vendor/bin/pest tests/Unit/PWMFanTest.php

```

### Test Structure

[](#test-structure)

```
tests/
├── Pest.php                          # Test configuration
└── Unit/
    └── PWMFanTest.php               # PWMFan unit tests

```

Included Examples
-----------------

[](#included-examples)

The package includes three comprehensive examples:

### Running Examples

[](#running-examples)

```
# Example 1: Basic usage
sudo php examples/01_basic_usage.php

# Example 2: Temperature-based control
sudo php examples/02_temperature_control.php

# Example 3: Advanced effects
sudo php examples/03_advanced_effects.php

```

### Example Overview

[](#example-overview)

**01\_basic\_usage.php**

- Basic on/off control
- Speed control and adjustment
- Speed presets
- Status information

**02\_temperature\_control.php**

- Reading CPU temperature
- Automatic speed adjustment
- Temperature monitoring loop
- Custom temperature scenarios

**03\_advanced\_effects.php**

- Smooth ramping (up and down)
- Pulsing effects
- Custom speed curves
- Coordinated effect sequences

Troubleshooting
---------------

[](#troubleshooting)

### Extension Not Found

[](#extension-not-found)

```
PHP Fatal error: Uncaught Error: Class 'Pwm\Pwm' not found

```

**Solution**: Install the [php-pwm extension](https://github.com/dept-of-scrapyard-robotics/php-pwm) first.

### PWM Device Not Found

[](#pwm-device-not-found)

```
RuntimeException: Device path does not exist

```

**Solution**:

- Export the PWM device: `echo 0 | sudo tee /sys/class/pwm/pwmchip3/export`
- Verify device exists: `ls /sys/class/pwm/pwmchip3/pwm0`
- Ensure proper permissions (add user to `gpio` group)

### Permission Denied

[](#permission-denied)

```
RuntimeException: Failed to write to file

```

**Solution**: Run with `sudo` or configure udev rules:

```
# /etc/udev/rules.d/99-pwm.rules
SUBSYSTEM=="pwm", KERNEL=="pwmchip*", ACTION=="add", RUN+="/bin/chgrp -R gpio /sys%p", RUN+="/bin/chmod -R g+w /sys%p"

# Reload rules
sudo udevadm control --reload-rules
sudo udevadm trigger

```

### Thermal Zone Not Found

[](#thermal-zone-not-found)

```
RuntimeException: Thermal zone 0 not found

```

**Solution**:

- Check available zones: `ls /sys/class/thermal/`
- Use correct zone number: `$fan->getCPUTemp(1)` for `thermal_zone1`

License
-------

[](#license)

MIT License. See LICENSE file for details.

Credits
-------

[](#credits)

This library wraps the [php-pwm extension](https://github.com/dept-of-scrapyard-robotics/php-pwm), which provides low-level PWM hardware control via Linux sysfs.

Contributing
------------

[](#contributing)

Contributions are welcome! When contributing:

- Follow PSR-12 coding standards
- Add tests for new features
- Update documentation as needed
- Ensure all tests pass before submitting pull requests

Support
-------

[](#support)

For issues related to:

- **This library**: Open an issue in this repository
- **php-pwm extension**: See the [php-pwm repository](https://github.com/dept-of-scrapyard-robotics/php-pwm)
- **Hardware setup**: Consult your device's PWM configuration documentation

###  Health Score

31

—

LowBetter than 68% of packages

Maintenance66

Regular maintenance activity

Popularity4

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity40

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

203d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/2169021b88d520bd58d9a37f51fa55058af7adbf7362c8cade65b261d644874c?d=identicon)[projectsaturnstudios](/maintainers/projectsaturnstudios)

---

Top Contributors

[![projectsaturnstudios](https://avatars.githubusercontent.com/u/10563160?v=4)](https://github.com/projectsaturnstudios "projectsaturnstudios (1 commits)")

###  Code Quality

TestsPest

### Embed Badge

![Health badge](/badges/dept-of-scrapyard-robotics-pwm-fan-control/health.svg)

```
[![Health](https://phpackages.com/badges/dept-of-scrapyard-robotics-pwm-fan-control/health.svg)](https://phpackages.com/packages/dept-of-scrapyard-robotics-pwm-fan-control)
```

###  Alternatives

[spatie/laravel-prefixed-ids

Friendly prefixed IDs for Laravel models

175177.5k1](/packages/spatie-laravel-prefixed-ids)[tapp/laravel-airtable

Laravel Airtable SDK

113229.1k](/packages/tapp-laravel-airtable)[codeigniter4/tasks

Task Scheduler for CodeIgniter 4

117149.1k1](/packages/codeigniter4-tasks)[napp/xray-laravel

AWS X-Ray for Laravel applications.

61407.3k](/packages/napp-xray-laravel)[derhansen/sf_event_mgt

Configurable event management and registration extension based on ExtBase and Fluid

64313.9k6](/packages/derhansen-sf-event-mgt)[superlatif/nova-tag-input

Tag input field for Laravel Nova.

13278.8k4](/packages/superlatif-nova-tag-input)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
