PC Fans: Difference between revisions

No edit summary
 
(7 intermediate revisions by the same user not shown)
Line 6: Line 6:
* Noctua's [https://noctua.at/pub/media/wysiwyg/Noctua_PWM_specifications_white_paper.pdf PWM Specification White Paper] (unknown date, but it references 1.3 <i>ibid</i>)
* Noctua's [https://noctua.at/pub/media/wysiwyg/Noctua_PWM_specifications_white_paper.pdf PWM Specification White Paper] (unknown date, but it references 1.3 <i>ibid</i>)
Almost all available fans are either 5V, 12V, or 24V, with 12V dominating personal computers:
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]]
* 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]]
* 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 <b>5V logical control</b> 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 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 <b>5V logical control</b> 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.
Line 31: Line 31:
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.
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.
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 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.
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.
Line 119: Line 119:


====On Linux====
====On Linux====
PWM fans are controlled through the [https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface <tt>hwmon</tt>] [[sysfs]] interface, using the "PWM" type (''not'' the "fan" type). This is dependent on your hardware controller (usually some SMBus-accessed [https://en.wikipedia.org/wiki/Super_I/O SuperIO] shadynasty on the motherboard) being supported and detected. You'll need set <tt>pwmX_enable</tt> to 1 for manual control, at which point you ought be able to write a value [0..255] to <tt>pwmX</tt>. When the PWM is under automatic control, you ought be able to read the current level by reading this latter file.
PWM fans are controlled through the [https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface <tt>hwmon</tt>] [[sysfs]] interface, using the "PWM" type (''not'' the "fan" type) via <tt>/sys/class/hwmon/*/pwm*</tt>. This is dependent on your hardware controller (usually some SMBus-accessed [https://en.wikipedia.org/wiki/Super_I/O SuperIO] shadynasty on the motherboard) being supported and detected. You'll need set <tt>pwmX_enable</tt> to 1 for manual control, at which point you ought be able to write a value [0..255] to <tt>pwmX</tt>. 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 [https://github.com/liquidctl/liquidctl liquidctl].
Some devices don't have a kernel driver, but are supported by userspace tools like [https://github.com/liquidctl/liquidctl liquidctl].
Line 130: Line 130:
** or, fed 3.3V: 680Ω (4.9mA)
** or, fed 3.3V: 680Ω (4.9mA)
* 24V: 3KΩ (6V, 2mA)
* 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 V<sub>CC</sub>, so this won't help you there). You'll then want an RC circuit going to ground, something like a 1nF ceramic capacitor and a 15kΩ resistor (this results in a [https://en.wikipedia.org/wiki/Low-pass_filter#RC_filter low-pass filter] at 10.6KHz (f = 1/2πRC); you could go lower). The tach will pull the signal low. It's best to detect this via hardware interrupts:
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 V<sub>CC</sub>, so this won't help you there). The tach will pull the signal low. It's best to detect this via hardware interrupts:
<syntaxhighlight lang="c">
<syntaxhighlight lang="c">
static volatile unsigned Pulses;
static _Atomic(uint32_t) LowerFanPulses, UpperFanPulses;


static void IRAM_ATTR rpm(void){
static void                                                                                                                        
   if(Pulses < UINT_MAX){ // saturate
pulse_isr(void* pulsecount){                                                                                                       
     ++Pulses;
  _Atomic(uint32_t)* pc = pulsecount;                                                                                                       
  ++*pc;                                                                                                                           
}   
 
static int
setup_intr(gpio_num_t pin, uint32_t* arg){
  if(gpio_set_input(pin)){
    return -1;
  }
  esp_err_t e = gpio_set_intr_type(pin, GPIO_INTR_NEGEDGE);
  if(e != ESP_OK){
    fprintf(stderr, "failure (%s) installing %d interrupt\n", esp_err_to_name(e), pin);
    return -1;
  }
  if((e = gpio_isr_handler_add(pin, pulse_isr, arg)) != ESP_OK){
    fprintf(stderr, "failure (%s) setting %d isr\n", esp_err_to_name(e), pin);
    return -1;
  }
   if((e = gpio_intr_enable(pin)) != ESP_OK){                                                                                      
     fprintf(stderr, "failure (%s) enabling %d interrupt\n", esp_err_to_name(e), pin);
    return -1;
   }
   }
  return 0;
}
}


static void setup_interrupt(int pin){
...
  pinMode(pin, INPUT_PULLUP);
if(setup_intr(lowertpin, &LowerFanPulses)){
  digitalWrite(pin, HIGH);
   return -1;
   attachInterrupt(digitalPinToInterrupt(pin), rpm, FALLING);
}
}
if(setup_intr(uppertpin, &UpperFanPulses)){
  return -1;
}
...


...
uint32_t up = UpperFanPulses;
unsigned p;
UpperFanPulses = 0;
noInterrupts();
uint32_t lp = LowerFanPulses;
p = Pulses;
LowerFanPulses = 0;
Pulses = 0;
interrupts();
...
...
</syntaxhighlight>
</syntaxhighlight>
<tt>p</tt> 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.
<tt>up</tt> and <tt>lp</tt> 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.
 
If there's noise contaminating the tachometer circuit, you might need to establish an RC circuit going to ground, yielding a [https://en.wikipedia.org/wiki/Low-pass_filter#RC_filter low-pass filter]. Given a time constant RC, a low-pass filter blocks signals over 1/2πRC. Pick something a fair amount above your expected frequency. Let's say your fan maxes out at 3000 RPM. That's 3000 / 60 = 50 RPS. The Hall sensor triggers twice per revolution so you're expecting 100 transitions per second. If you're using a 680Ω resistor on input, and want to pass signals below 500 Hz, a 470 nF capacitor will do the trick: 1/2πRC == 1/2π(.0003196) == 497.98 Hz. Note that this will make your transitions less sharp on the rising side, and only serves to reduce the voltage drastically when the frequency increases substantially. It's best to avoid their use.


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 [https://shop.aquacomputer.de/product_info.php?products_id=3832&language=en Aquacomputer OCTO] via USB).
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 [https://shop.aquacomputer.de/product_info.php?products_id=3832&language=en Aquacomputer OCTO] via USB).
Line 185: Line 209:


===Connector and wiring===
===Connector and wiring===
[[File:0470533000.jpeg|right|thumb|A Molex 47053-1000 4-pin header]]
Intel specifies UL1430 wire with a minimum AWG26, 300V capacity, with rating of at least 105℃.
Intel specifies UL1430 wire with a minimum AWG26, 300V capacity, with rating of at least 105℃.


Line 225: Line 250:
* Devices, often in 5.25" bay form factor, with knobs for manual control of connected fans. [[Counterforce|Manual control is lame]] so fuck that.
* Devices, often in 5.25" bay form factor, with knobs for manual control of connected fans. [[Counterforce|Manual control is lame]] so fuck that.
* Specialized ICs exist to drive fan PWM and read tach:
* Specialized ICs exist to drive fan PWM and read tach:
** Analog Devices [https://www.digikey.com/en/products/detail/analog-devices-inc/ADT7470ARQZ-REEL7/995575 ADT7470ARQZ-REEL7] (4 fans, SMT, [[SMBus]])
** Analog Devices [https://www.digikey.com/en/products/detail/analog-devices-inc/ADT7470ARQZ-REEL7/995575 ADT7470ARQZ-REEL7] (4 fans, SMT, [[SMBus]], temp sensor)
** OnSemi [https://www.onsemi.com/pdf/datasheet/adm1031-d.pdf ADM-1301] (2 fans, SMT, [[SMBus]])
** OnSemi [https://www.onsemi.com/pdf/datasheet/adm1031-d.pdf ADM-1301] (2 fans, SMT, [[SMBus]])
** OnSemi [https://www.onsemi.com/download/data-sheet/pdf/adt7460-d.pdf ADT7460] (2 fans, SMT, [[SMBus]])
** OnSemi [https://www.onsemi.com/download/data-sheet/pdf/adt7460-d.pdf ADT7460] (2 fans, SMT, [[SMBus]])
** Maxim Integrated [https://www.maximintegrated.com/en/products/interface/signal-integrity/MAX31790.html MAX31790] (6 fans, SMT, I<sup>2</sup>C)
** Maxim Integrated [https://www.maximintegrated.com/en/products/interface/signal-integrity/MAX31790.html MAX31790] (6 fans, SMT, I<sup>2</sup>C)
** Texas Instruments [https://www.ti.com/product/AMC6821 AMC6821] (1 fan, SMT, [[SMBus]])
** Texas Instruments [https://www.ti.com/product/AMC6821 AMC6821] (1 fan, SMT, [[SMBus]], temp sensor)
** Microchip [https://ww1.microchip.com/downloads/aemDocuments/documents/MSLD/ProductDocuments/DataSheets/EMC2301-2-3-5-Data-Sheet-DS20006532A.pdf EMC230x] (1, 2, 3, or 5 fans depending on model, SMT, [[SMBus]])
** Microchip [https://ww1.microchip.com/downloads/aemDocuments/documents/MSLD/ProductDocuments/DataSheets/EMC2301-2-3-5-Data-Sheet-DS20006532A.pdf EMC230x] (1, 2, 3, or 5 fans depending on model, SMT, [[SMBus]])
===LEDs===
===LEDs===