Check out my first novel, midnight's simulacra!

PC Fans

From dankwiki

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.

I have collected extensive specs for Noctua, Phanteks, EK-Vardar, and 140mm fans in general (140mm fans are in many ways optimal for a MORA3).

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. 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 requirement), 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 more-or-less 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?)

Controlling PWM

On microcontrollers

Controlling fans using a microcontroller has some complexity. The first difficulty is generating a 25KHz PWM signal. On Arduino UNOs and MEGAs, this is not available 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;
}

The relevant pin ought be placed into OUTPUT mode, and must be associated with timer 5 (say, Pin 44). No direct manipulation of the pins is necessary, and the PWM is handled in hardware.

The ESP32's ledc library can be harnessed to do this at a higher level, using hardware PWM. 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_channel_config_t conf;                                                                                                       
  memset(&conf, 0, sizeof(conf));                                                                                                   
  conf.gpio_num = pin;                                                                                                              
  conf.speed_mode = LEDC_HIGH_SPEED_MODE;                                                                                           
  conf.intr_type = LEDC_INTR_DISABLE;                                                                                               
  conf.timer_sel = FANPWM_TIMER;                                                                                                    
  conf.duty = FANPWM_BIT_NUM;                                                                                                       
  conf.channel = channel;                                                                                                           
  if(ledc_channel_config(&conf) != ESP_OK){                                                                                         
    return -1;                                                                                                                      
  }                                                                                                                                 
  ledc_timer_config_t ledc_timer;                                                                                                   
  memset(&ledc_timer, 0, sizeof(ledc_timer));                                                                                       
  ledc_timer.speed_mode = LEDC_HIGH_SPEED_MODE;                                                                                     
  ledc_timer.bit_num = FANPWM_BIT_NUM;                                                                                              
  ledc_timer.timer_num = FANPWM_TIMER;                                                                                              
  ledc_timer.freq_hz = freq;
  if(ledc_timer_config(&ledc_timer) != 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;                                                                                                                         
}

The ESP8266 requires a call to analogWriteFreq(25000); before using analogWrite() to set an 8-bit duty cycle. This is a global setting, and will affect any other analogWrite()s in your program. If you don't like it, you can always bitbang.

Note that 25KHz is beyond the capability of many general-purpose PWM ICs (e.g. TLC5940, PCA9685).

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.

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 is 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, 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). The tach will pull the signal low. It's best to detect this via hardware interrupts:

static volatile unsigned Pulses;

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

static void setup_interrupt(int pin){
  pinMode(pin, INPUT_PULLUP);
  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

Connector and wiring

Pinout (GND, power, tach, PWM).

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

FIXME

Parameters

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.

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₁₀(ρ₂ / ρ₁)

Accessories

  • Dewire from the Netherlands sells their Relay in various lengths, perfect for running down the side of a radiator or up the height of a full tower.
  • 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.
  • 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.

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.

External links

See also