Check out my first novel, midnight's simulacra!

PC Fans

From dankwiki
Revision as of 20:29, 14 November 2024 by Dank (talk | contribs) (→‎On ESP32)
Pinout (GND, power, tach, PWM).

Fans, an active cooling element, move air in a system. Heat must be removed from the site of its production, and from the system as a whole. A fan increases heat convection with surrounding air via airflow. Air is at its highest pressure immediately in front of the fan, and at lowest pressure immediately behind it.

Fans for personal computers are governed by specifications from Intel and Noctua:

Almost all available fans are either 5V, 12V, or 24V, with 12V dominating personal computers:

  • there is no readily-available 24V source from an ATX power supply, but you'll see 24V in e.g. 3D printers
  • 5V fans are seen in conjunction with MCUs such as Raspberry Pi

Fans operating at higher voltages will require less current for the same work. Two-pin fans offer neither feedback nor dedicated PWM control. Three-pin fans typically offer a tachometer signal on the third wire. Four-pin fans add a PWM control on the fourth wire. PWM is a 5V logical control that does not modify supplied power. In the absence of PWM support, some control can be effected by varying voltage (voltage ought be held constant for a PWM fan), but since a minimum voltage is necessary to avoid stalling, only the higher-speed range is available. "Low-frequency PWM" applies PWM to the power wire itself, but suffers from audible commutation noise, and must apply pulse stretching to the tachometer.

Fans can be run at less than their maximum duty to reduce acoustic noise, consume less power, and potentially extend their lifetimes.

Recommendations

I have collected extensive specs for Noctua, Phanteks, EK-Vardar, 80mm fans, and 140mm fans in general (9x 140mm fans are in many ways optimal for a MORA3-420). Assuming you don't need lighting, and want to optimize for both cooling efficiency and quietness, go with:

  • (120mm) Phanteks T-30 in a 3-pack if you can fit a 30mm-deep fan, the Noctua NF-A12x25 otherwise
  • (140mm) Noctua NF-A14

For other sizes, Noctua's never a bad bet, but will cost a premium. To optimize for maximum cooling capacity, go with (loud) Deltas. To optimize for price without buying garbage, pick up a multipack of Arctic F12s or F14s. To optimize for LEDs, get a Lian Li Infinity or SL V2, and be prepared to pay far out the ass for it. To optimize for LEDs on a budget, multipacks of Arctic P12s and P14s are the way.

Power draw

Intel's spec mandates 12V±5% (11.4–12.6V). A fan in its steady state operating in freestream (V) conditions ought not draw more than 1.5A (this would be a maximum of 18.9W; most consumer fans draw far less). During startup, 2.2A of inrush current may be drawn for a period of no more than 1s (27.72W).

Note that the powerful (and bracingly loud) Noctua iPPC-3000 is speced at 3.6W, i.e. 0.3 amps, just 20% of the allowed draw. On the other hand, truly industrial fans exist: Delta's PFC1212DE 5500RPM behemoth draws 4A for an out-of-spec 48W. At this point, system designers really must begin considering heat added to the system by the fan:

If the supply fan is downstream of the cooling coil in a draw-through configuration, the fan heat increases the supply air temperature, increasing the supply air volume required to meet a given space load. If the fan is upstream of the coil in a blow-through configuration, the fan heat is absorbed directly by the coil. In either case, the fan heat adds to the cooling coil load. —James S. Elleson, Cold Air Distribution (1996)

Most motherboard fan headers (always 12V) are rated for between one and two amps. More current than this can be drawn from independently-powered fan controllers. One hears a rule of thumb that more than three consumer fans ought not be hooked up to a single header, but just add the damn amps and check the motherboard manual.

PWM

Pulse width modulation controls the power delivered by dividing time up into quanta, and supplying current only during part of each quantum. The signal is characterized by the quantum length (∝ 1/frequency); the level can then be varied from none to the entirety of the quantum. 100% PWM is equivalent to constant current supply, while 0% PWM is equivalent to no supply.

PC fans are ideally controlled via 25KHz PWM, though the range 21KHz to 28KHz is deemed acceptable (why 21KHz? so that you can't hear it (more precisely, so that you can't hear the commutation noise from switching the drive coils on and off): children hear up to about 20KHz, adults 17). The PWM high signal ought be 5V with an absolute maximum of 5.25V. The absolute max current drawn is 5mA (as an example, the ESP32 specs 40mA on each GPIO pin). The maximum value of logic low is 0.8V. In the absence of a valid signal, the fan ought run at maximum speed. Intel's document puts fairly strict requirements on the PWM-RPM relationship: the fan speed shall be a "continuous and monotonic function of the duty cycle" (a reasonable if almost redundant requirement, see below), and furthermore that the effected speed, as a percentage of maximum speed, should match the PWM duty cycle to within ±10%. If the PWM duty cycle is e.g. 50%, and the fan's max speed is 1900 RPM, conformance requires fan speed of 760–1140 RPM. The response curve must thus be linear in the large.

Fans have a minimum rotation speed, corresponding to some minimum PWM duty cycle; duty cycles below this minimum result in the the fan running at less than or equal to the minimum speed (perhaps not running at all). The fan will never *start* spinning at less than the minimum rotation speed. The minimum rotation speed must not be more than 30% of the maximum speed.

an aside about Intel terminology: a "Type A" fan never shuts down, a "Type B" fan shuts down at 0% PWM, and a "Type C" fan shuts down at all PWM duty cycles below some threshold; one would think it sufficient to specify a "maximum PWM for shutdown" and simply specify -1 for "Type A" fans, but who knows? regarding "continuous and monotonic": any monotonic function is continuous except for possible jump discontinuities, which would be odd in a fan.

Controlling PWM

Many motherboards will allow their fan headers to be configured in the BIOS/UEFI. This typically involves defining some function mapping some motherboard temperature sensor to a PWM level for each fan. Rarely is this more flexible than allowing some pairs of this function to be specified, with the firmware interpolating between these points.

If you want to use a more complex algorithm, or inputs that aren't on the motherboard, you'll need some extra controller.

Note that 25KHz is beyond the capability of many general-purpose PWM ICs (e.g. TLC5940, PCA9685), though I list several suitable special-purpose ICs below.

On ATmega-based Arduino

Generating a 25KHz PWM signal on Arduino Unos and MEGAs is not possible via the standard libraries, and the hardware must be programmed directly. Here's a sample implementation for the MEGA, providing eight-bit resolution (PWM values [0..255]), and using timer 5 for a PWM signal:

static void setup_timers(int freq){      
  TCCR5A = 0;                                                                                                                       
  TCCR5B = 0;                                                                                                                       
  TCNT5 = 0;                                                                                                                       
  // Mode 10: phase correct PWM with ICR5 as Top (phase-correct needs a                                                             
  // factor of 2 in division below). OCR5C as Non-Inverted PWM output.                                                               
  // 16MHz / (25KHz * 2) == 320 cycles per interrupt.                                                                               
  ICR5 = F_CPU / freq / 2;                                                                                                 
  TCCR5A = _BV(COM5C1) | _BV(WGM51);                                                                                                
  TCCR5B = _BV(WGM53) | _BV(CS50);                                                                                                  
}

static void set_pwm(unsigned pwm){
  OCR5C = ICR5 * pwm / 255;
}

To use a different timer, replace all '5's above with the desired timer number. The relevant pin ought be placed into OUTPUT mode, and must be associated with the configured timer (say, Pin 44 for Timer 5). No direct manipulation of the pins is necessary, and the PWM is handled in hardware.

On RA4M1-based Arduino

Things are simpler on the Renesas RA4M1 driving the UNO R4. Use pwm.h's PwmOut class on one of the numerous pins capable of hardware PWM, initializing it to 25Khz:

static const int PWM_PIN = D3;   // we'll use D3
PwmOut pwmd3(PWM_PIN);
pinMode(PWM_PIN, OUTPUT);
pwmd3.begin(25000.0f, 0.0f); // start with a PWM of 0
pwmd3.pulse_perc(pwm);

On ESP32

The ESP32's ledc library can be harnessed to do this at a high level, while still using hardware PWM. You might need step up the voltage to 5V via one mechanism or another (failure to do can, in my experience, result in devices running at lower speeds than expected). A level shifter will do nicely. Supply a chosen channel (of 8) and an OUTPUT pin, together with a freq of 25000, to e.g.:

static int initialize_pwm(ledc_channel_t channel, int pin, int freq, ledc_timer_t timer){
  ledc_timer_config_t ledc_timer;
  memset(&ledc_timer, 0, sizeof(ledc_timer));
  ledc_timer.speed_mode = LEDC_LOW_SPEED_MODE; // no high-speed on ESP32-S3
  ledc_timer.duty_resolution = LEDC_TIMER_8_BIT; // used to be "bit_num"
  ledc_timer.timer_num = timer;
  ledc_timer.freq_hz = freq;
  if(ledc_timer_config(&ledc_timer) != ESP_OK){
    return -1;
  }
  ledc_channel_config_t conf;                                                                                                       
  memset(&conf, 0, sizeof(conf));                                                                                                   
  conf.gpio_num = pin;                                                                                                              
  conf.speed_mode = ledc_timer.speed_mode;  
  conf.intr_type = LEDC_INTR_DISABLE;                                                                                               
  conf.timer_sel = timer;
  conf.duty = LEDC_TIMER_8_BIT;
  conf.channel = channel;
  if(ledc_channel_config(&conf) != ESP_OK){
    return -1;
  }
  return 0;
}

and then set the PWM duty cycle by calling on that same channel:

static int set_pwm(ledc_channel_t channel, unsigned p){                                                                                                     
  if(ledc_set_duty(LEDC_HIGH_SPEED_MODE, channel, p) != ESP_OK){                                                                 
    return -1;                                                                                                                      
  }
  if(ledc_update_duty(LEDC_HIGH_SPEED_MODE, channel) != ESP_OK){                                                           
    return -1;                                                                                                                      
  }                                                                                                                                 
  return 0;                                                                                                                         
}

On Linux

PWM fans are controlled through the hwmon sysfs interface, using the "PWM" type (not the "fan" type). This is dependent on your hardware controller (usually some SMBus-accessed SuperIO shadynasty on the motherboard) being supported and detected. You'll need set pwmX_enable to 1 for manual control, at which point you ought be able to write a value [0..255] to pwmX. When the PWM is under automatic control, you ought be able to read the current level by reading this latter file.

Some devices don't have a kernel driver, but are supported by userspace tools like liquidctl.

Tachometer

Two pulses (momentarily closed circuit) per revolution on an open collector. Maximum current is 5mA for 5V and 12V fans, and 2mA for 24V fans. VCC ought be 13V for 12V fans (so claims Noctua. Other places, and my experience, suggest that 5V and even 3.3V are sufficient), and 6V for 5V and 24V fans, necessitating at least the following pullup resistors:

  • 5V: 1.2KΩ (6V, 5mA)
  • 12V: 2.6KΩ (13V, 5mA) (or 1KΩ assuming 5V / 680Ω at 3.3V, see above)
  • 24V: 3KΩ (6V, 2mA)

Arduino 5V internal pullup resistors are several tens of thousands of ohms, so they can be used to simplify the circuit (on a 3.3V MCU, you'll need hook up the tachometers to at least a 5V VCC, so this won't help you there). You'll then want an RC circuit going to ground, something like 1nF and 15kΩ for a 12V fan (this results in a low-pass filter at 10.6KHz; you could go lower). The tach will pull the signal low. It's best to detect this via hardware interrupts:

static volatile unsigned Pulses;

static void IRAM_ATTR rpm(void){
  if(Pulses < UINT_MAX){ // saturate
    ++Pulses;
  }
}

static void setup_interrupt(int pin){
  pinMode(pin, INPUT_PULLUP);
  digitalWrite(pin, HIGH);
  attachInterrupt(digitalPinToInterrupt(pin), rpm, FALLING);
}

...
unsigned p;
noInterrupts();
p = Pulses;
Pulses = 0;
interrupts();
...

p can then be used to calculate RPM. Remember to divide by 2 due to two pulses per revolution. The pin must be associated with some hardware interrupt.

A junction must propagate only one tachometer signal, i.e. if three fans are connected to a splitter, only one tach value is reported. Whether this is a maximum, or an average, or something else is undefined, but every junction I've ever seen, from passive splitters to active controllers, simply connects only one tachometer to the wire (controllers using a side channel in addition to the fan connector might of course report multiple tach signals, as does the Aquacomputer OCTO via USB).

Physical

Fan size (mm) Typical hole spacing (mm)
40 32
50 40
60 50
70 60
80 71.5
92 82.5
120 105
140 124.5
200 154
220 170

Connector and wiring

Intel specifies UL1430 wire with a minimum AWG26, 300V capacity, with rating of at least 105℃.

The fan wire ought be terminated with a four-pin housing (Wieson 2510C888-001, Molex 47054-1000, or equivalent).

The intended mating header ought be housed in Wieson 2366C888-007, Molex 47053-1000, Foxconn HF27040-M1, Tyco 1470947-1, or equivalent.

Pinout: GND (black), Power (yellow), Tach (green), PWM (blue)

Both connectors ought employ a polarizing rib between the third and fourth pin to ensure correct connection. The absence of such does not preclude mating with a ribbed connector; an offset connection is almost certain to blow the tachometer circuit if the device is externally powered.

Form factor

The fans seen most often in personal computers are 120mm square by 25mm deep (this is the only size specified in the Intel reference). Almost all radiators intended for computer watercooling are built around some number of 120mm or 140mm fans. A larger fan will typically require less power and generate less noise (due to a lower rotational speed) to move the same amount of air.

Common depths include 10mm, 15mm, 25mm, and 38mm, but these are (beyond 25mm) less standardized. As of late 2022, perhaps the best general-purpose fan on the market is the Phanteks T-30, a 120x120x30mm fan.

Parameters

variable when speed changes when density changes
flow flow₂ = flow₁(rpm₂ / rpm₁) flow₂ = flow₁(ρ₂ / ρ₁)
pressure P₂ = P₁(rpm₂ / rpm₁)² P₂ = P₁(ρ₂ / ρ₁)
power W₂ = W₁(rpm₂ / rpm₁)³ W₂ = W₁(ρ₂ / ρ₁)
noise N₂ = N₁ + 50log₁₀(rpm₂ / rpm₁) N₂ = N₁ + 20log₁₀(ρ₂ / ρ₁)

Static pressure is the pressure created in front of the fan within an enclosure. Airflow is the volume of air moved per unit time. A fan's output is characterized in terms of maximum static pressure and maximum airflow, but it does not hit both maxima at once. Maximum airflow is achieved when completely unobstructed. As the amount of obstruction increases, airflow is reduced, and static pressure increases. At a given level of output, airflow is roughly inversely proportional to the square root of static pressure. Each fan has a performance curve relating airflow to static pressure (technically, a curve per PWM level). The environment defines the impedance curve, and the real pressure and airflow are specified where these two intersect.

This is of great relevance when putting fans on radiators, and to a lesser extent behind screens/filters. A fan optimized for static pressure might be able to push more flow through such obstacles than one designed purely to maximize unimpeded airflow.

Accessories

  • Aquacomputer from Germany sells the QUADRO and OCTO for four and eight fans, respectively, with independent tach and PWM on all. It's controlled by USB.
  • Any number of fan hubs, generally powered by Molex or SATA (requiring only the 12V line on each) and with a two-wire cable for tach+PWM. Some arbitrary header will be connected to tach; PWM will be distributed to all headers.
    • Dewire from the Netherlands sells their firm Relay in various lengths, perfect for running down the side of a radiator or up the height of a full tower.
  • Any number of fan extenders/splitters, taking their power from the motherboard header. Same deal as a fan hub, except with fewer amps available.
  • Devices, often in 5.25" bay form factor, with knobs for manual control of connected fans. Manual control is lame so fuck that.
  • Specialized ICs exist to drive fan PWM and read tach:

LEDs

Fans are well-represented in modern workstation lightshows. Look for daisy-chaining capabilities in an LED-enabled fan, as there will usually be twice the total cabling. 5V can't be daisy-chained as far as 12V due to voltage drop.

Fans typically have either 12V RGB or 5V ARGB LEDs. The 12V four-pin SMD5050 LEDs can be set in toto to a single color formed by varying the voltages of R, G, and B signals (via lower-frequency PWM). 5V WS2811 addressable LEDs can be individually controlled via a digital protocol. You'll need a controller either way: for 5V, I like Gelid's CODI6 and the FastLED library. For 12V, just emit (native frequency) PWM from three pins of any MCU through three appropriate MOSFETs (the IRLB8721 is a fine choice), easy-peasy.

LEDs can be added to an arbitrary 120mm fan via frames such as Phanteks Halos.

Other crap using the fan header

Pumps will use the fan header for tach and PWM, though not power nor ground (these will be externally supplied by some other source).

Some flowmeters use a two- or three-pin connector, for power and optionally tach.

I've seen some lighting run off the fan header's PWM, but 1A isn't generally sufficient for very significant lighting.

External links

See also