Saturday, September 12, 2009

Setting CPU Fan Speed Linux

I recently assembled a new desktop system. I want it to as reasonably quiet as possible. The motheboard's cpu fan header is 4 pin. What these new four pin headers do is allow for a variable pwm to be applied to them, which varies the cpu fan's speed.

One issue is that the stock fan, while not that loud, was leaving my temps a bit too warm. It is a lower powered AMD 245 "regor", but my case is a SUGO S02 from Silverstone - very cramped. I upgraded to an aftermarket Zalman 7000cu fan. This thing is a giant copper beast, with a bigger fan, but still compact enough to fit in my case. I was hoping I could shave off a few degrees and quiet it up a bit.

The one issue is that this new fan has only a 3 pin header, supposedly no pwm. It came with a manual adjustment knob that can let me vary the voltage by hand, but that meant another thing sticking out of the back of the case, or filling up the insides.

So at first I used a tool called fancontrol. It is installed in Arch Linux by default, but I'm sure its in all the big distribution's repositories. Fancontrol is a bash script that runs as a daemon, monitoring a temp you specify, and at speeds you want. You have to go through some time playing with its configuration tool, "pwmconfig".

To my surprise, it manages to control the fan speed of my 3-pin fan. It worked well, eventually I got things pretty quiet. As my load increases, and thus CPU temperatures, the fan speed does as well. There is one issue with this.

For a given load, the CPU will heat up, along with fan increases, until things stabilize at a certain level of heat/rpm/temperature. If you are lucky, it stabilizes at a particular value. But usually it stabilizes at a cycle. The temp hits 37 degrees, fan 1250rpm for me, and this lets the cpu warm to 38 degrees, where the fan is then kicked up to 1350rpm, cooling the cpu back down to 37. This can be an irritating cycle. At either speed, the fan is relatively quiet, but to hear the speedup and slowdown every 30 seconds is distracting.

So let's just set it manually. Googling for how to do this was not immediately apparent, so I wanted to clarify. Linux detects and has support for hardware monitoring devices, which use the very low level i2c bus. It exports an interface at /sys/class/hwmon. For me, /sys/class/hwmon/hwmon0/device is the usable device interface, which has numerous values within.

"pwm1" is the fan control value that we can play with. It stores a value from 0-255, indicating the voltage driving the fan. A value of 0 means the fan wont spin, a value of 255 means it spins at full speed. However, a value of up to 28 for me has the fan not moving either, so each fan is probably different.

'cat fan1_input' will return the rpm of the first fan, the cpu fan for me.
'cat pwm1' returns the value 0 - 255 that the fan is being told to spin at.
I use lm_sensors to see cpu temp and fan speed, but this data is all controlled by this hwmon device.

To alter the fan speed, first 'echo 1 > pwm1_enable', this will let the 'pwm1' value control it. Then experiment. I have found that 'echo 150 > pwm1' sets the fan high enough to where it cools down to the low 30's, but is not too loud. 'echo 65 > pwm1' is silent, although the cpu temp rises to almost 40C.

The nice thing about this is that I set a single temp/rpm/noise volume, no irritating cycles. Another nice thing about just setting this manually is that my fan has certain regions that have additional vibration. 1250rpm and things get a slight buzz. 1200rpm and even 1300rpm are quieter. I like the finer manual control.

As for now, my rc.local has both "echo 1 > /sys/class/hwmon/hwmon0/device/pwm1_enable" and "echo 65 > /sys/class/hwmon/hwmon0/device/pwm1". I generally have a similar load on the system, and don't do anything that will tax it too much for too long, so I am comfortable with this setup.

I'm still curious as to what the fourth pin on a 4 pin cpu fan was for. Obviously motherboards can modulate the 12v line in the 3 pin, which is the same in the 4. I can only guess that this is a legacy issue. Certain fans may not work well with changing the 12v line, and certain motherboards may lack a hardware monitoring device. But basically, if you see a good cpu fan and it is only 3 pin, you can still have full automated or manual control.

Friday, March 6, 2009

Batch Renaming music files with single digit track numbers, to prepend with a 0, with a Bash script.

So, you have a collection of music... say... 120GB of flac, ripped from CDs.

This collection is important to you, and took you a while to rip. You don't want to do it again.

You chose a filename schema $artistname/$albumname/$trackname - $songname.$fileextension

You like this schema, and its organized well, but one problem. Tracks 1 - 9 for each album have a single digit track number, but tracks 10 and up are two.

Some music players and programs view track 10 and 11 and on before tracks 1 - 9. There has to be a simple way to rename these files to have two digit filenames.

There is. There are programs out there that rename files based on the id3 tag, but lets say you don't want to bother with that, you just want to do a simple batch rename. A one line bash command will do the trick:

for file in [1-9]' '*; do mv "$file" 0"$file"; done

As I am new to bash scripting I wanted to figure out how to do this, and it took a full 15 minutes to figure out how bash escapes characters. It will evaluate shell variables inside double quotes, but not single quotes. The above one line script finds all files that start with a number from 1 through 9, and are immediately followed by a space. Conveniently, my 120GB of flac has a lot of these, and no other non-music files are there.

I saved the above to a script,, chmod u+x, and ./ within the directory that needs to be renamed.

I have to do that once on each album though. Let me figure out how to do this recursively on my entire collection.