Cover Image

Faking the Fans:

Controlling PWM server fans for quiet operation

Intro

This writeup was created as a result of numerous requests from people struggling with excessive fan noise in their in-home server equipment. It is simply a documentation of a quick project I completed, and is not meant to be a guide to those looking to do the same. I am not responsible for whatever you do with this information: modifying your equipment in this way could cause serious damage. Remember that these loud fans have a purpose - suppressing them could expose your server to higher temperatures and could reduce it's effective lifetime, and will almost definitely void any warranty you might have. With that said, I hope that someone finds the following useful in making their server equipment more bearable to keep inside.

If you've worked with enterprise-grade servers and networking hardware, you know that they can often be too loud to be comfortably used at home. Recently I purchased a used HP Ml350e gen8, a 5u tower with full-size 120mm fans, with the thought that it would be substantially quieter than the 1u rack servers I have owned in the past. At first, it was totally quiet, however after installing a non-HP-recognized device into one of the PCI-e slots, the server would constantly run at 40% fan speed regardless of temperature. This is apparently a failsafe measure by the internal fan controller. Neither the system BIOS nor HP's remote management interface (iLO) have any low-level fan control. The only remaining option was to control the fans myself - trick both the fan and the fan controller.

Fooling the Server

The first step was to figure out the connector itself. After reading the HP documentation and with the help of some of the responses in a forum for the HP Microserver, the 5-pin connector pinout is as follows:

Cable Pinout Cable Back

Tricking the fan controller was as simple as grounding pin 4 the ground pins (5 and 6) on the server end. I did this by simply snipping the yellow wire near the back of the connector and soldering (the server end) to the ground loop: The fan-end of the yellow wire can simply be left to dangle - you could cover it with e-tape to be safe. So why does grounding the fan speed wire trick the server? As far as I can tell, it's simply there to check for an open (unconnected) wire. I tested this by grounding the yellow wire and leaving the blue wire hanging, meaning the fan was completely stopped, yet the iLO claimed the fan speed was a steady 40%. With that out of the way, the only thing left is controlling the fan itself.

Fan Control: Diagnosis

Replicating the fan control signal requires two bits of knowledge - the acceptable range of frequencies, and the relationship between fan speed and duty cycle. The first can generally be found with the documentation for the particular fan. In my case, the signal was somewhere around 30kHz, but had a pretty wide range of acceptable frequencies. I ended up choosing 25kHz.

Understanding the relationship between the PWM signal and the fan speed was a bit more work. The official documentation on this is sparse. I decided to try to 'sniff' the signal with a cheap USB logic analyzer under different fan speed conditions. The tests looked something like this:

You can see the fan control signal on channel 2. This was captured while there was no PCI device inserted - a slow ~15% speed. What I found was that my particular fan was essentially active-low: the lower the duty cycle, the higher the speed. At zero duty cycle (effectively disconnecting the signal wire) the fan would spin at 100%, and at 100% duty cycle (constant 25kHz PWM signal) the fan would stop. While it did not seem like there was a 1-to-1 ratio of duty cycle to fan speed, I later found an 82% duty cycle (potentially 18% fan speed?) to be a good compromise of sound and airflow.

Fan Control: Signal Generation

To generate the PWM signal to control the fan I opted to use an Arduino Nano, as its tiny form factor and dedicated PWM pins made it a quick and simple hack. With both of the fan's blue wires soldered to the PWM pin, and 5V power and GND through a nearby internal header on the motherboard to power the Arduino, it makes for an easy solution. With the PWM signal set for 82%, I booted the server back up (with the non-HP PCI device still inserted), and sure enough the fans run at a steady, quiet rate. I have been monitoring temperatures (through the remote management console) for a few weeks now and the temperatures are still well within a reasonable range, only now at a much more reasonable volume.

The Arduino code is posted here on my GitHub. Feel free to comment there if you have any questions.