Controlling Fan Speed with Temperature-Based Logic in Embedded Systems

In embedded systems, managing thermal performance is often critical for maintaining reliability and efficiency. One common strategy involves controlling the speed of cooling fans based on real-time temperature readings. This post explores a Rust module built by me, fan-speed-control, designed to handle this task effectively.

Overview

The fan-speed-control module is a lightweight, no_std library written in Rust. It provides a configurable controller for managing fan speed based on temperature thresholds. It is a Implementation of a linear fan speed controller.

Key Features

  1. Configurable Parameters: The module allows users to define minimum and maximum fan speeds, along with temperature thresholds for turning the fan on, off, and reaching full speed.
  2. Temperature-Based Control: Fan speed is adjusted linearly based on temperature readings between defined thresholds.
  3. Spin-Up Logic: The controller includes a spin-up phase where the fan runs at maximum speed for a specified duration to overcome initial inertia.

fan-speed-graph

Module Structure

The module consists of two main components: FanSpeedControlConfig and FanSpeedControl.

FanSpeedControlConfig

This struct holds the configuration parameters for the fan speed controller:

#[derive(Debug)]
pub struct FanSpeedControlConfig {
    pub min_speed: u32,
    pub max_speed: u32,
    pub temp_on: f32,
    pub temp_off: f32,
    pub temp_full: f32,
    pub spin_up_duration: embedded_time::duration::Seconds,
}
  • min_speed: Minimum fan speed.
  • max_speed: Maximum fan speed.
  • temp_on: Temperature to turn on the fan.
  • temp_off: Temperature to turn off the fan.
  • temp_full: Temperature for full fan speed.
  • spin_up_duration: Duration to spin up the fan at maximum fan speed in seconds.

Pro Tip: You can use pwm duty cycles for min_speed and max_speed

FanSpeedControl

This struct represents the fan speed controller and includes methods for stepping the controller state machine with temperature readings and current time.

Operation Modes

  1. Off Mode: The fan is stopped. When the temperature rises above temp_on, the controller transitions to SpinUp mode.
  2. SpinUp Mode: The fan runs at maximum speed for spin_up_duration seconds to overcome initial inertia. After this period, it transitions to Ramp mode.
  3. Ramp Mode: The fan speed varies linearly with temperature between min_speed at temp_on and max_speed at temp_full. If the temperature falls below temp_off, it returns to Off mode.
---
title: Fan controller states
---
stateDiagram-v2
    [*] --> Off

    Off --> SpinUp : Temperature is above on threshold
    SpinUp --> Ramp : Spin up time has passed
    Ramp --> Off : Temperature is below off threshold

The Math of Ramp mode

The linear speed algorithm employed in the fan-speed-control module is a straightforward yet effective method for adjusting fan speed based on temperature readings. This algorithm operates in the Ramp mode, where the fan speed increases linearly from a minimum speed at the temperature threshold for turning the fan on (temp_on) to a maximum speed at the temperature threshold for full speed (temp_full).

The algorithm calculates the fan speed using a linear equation of the form speed = m * temperature + b, where m is the slope and b is the intercept. Both m and b are calculated by the specified FanSpeedControlConfig:

let m = (max_speed - min_speed) / (temp_full - temp_on);
let b = min_speed - (m * temp_on);

This approach ensures a smooth and proportional response to temperature changes.

This linear approach provides a predictable and gradual adjustment of fan speed, helping to maintain stable thermal conditions without abrupt changes.

Example Usage

Here’s a simple example of how to use the FanSpeedControl:

use fan_speed_control::{FanSpeedControlConfig, FanSpeedControl};
use embedded_time::{duration::Seconds, Instant, Clock};
use std_embedded_time::StandardClock;

let config = FanSpeedControlConfig {
    min_speed: 20,
    max_speed: 100,
    temp_on: 40.0,
    temp_off: 35.0,
    temp_full: 60.0,
    spin_up_duration: Seconds(2),
};
let mut controller = FanSpeedControl::new(config);
let clock = StandardClock::default();
let speed = controller.step(45.0, clock.try_now().unwrap());

Conclusion

The fan-speed-control module provides a robust and flexible solution for controlling fan speed in embedded systems. Whether you're working on a microcontroller project or a larger embedded system, this module can help you maintain optimal cooling performance.

For more details, you can explore the full source code and contribute to its development.