My motherboard comes equipped with a W83627EHF sensor chip, which is supported by Linux via the w83627ehf module. It was automatically detected and configured by lm-sensors. The chip has an adjustable PWM output that allows the user to control system fan speeds. The Linux kernel module exports these controls through pwm* files under /sys/class/hwmon/hwmon0/device/. Writing an integer in the 0-255 range to any of these files changes the PWM output of that fan, altering its rotation.
I usually don't bother with system fan speeds, but my current CPU fan produces a particularly annoying noise at ~3300 RPM and above. Sometimes I want to manually adjust it in order to reduce the noise.
I decided to create this widget for two reasons: to have a nice and easy way to adjust the CPU fan speed, without having to manually issue commands every time; and to have a quick look on how it is to develop Plasma widgets (Plasmoids), specially through its Python bindings.
I used the Python Plasmoid Example as a basis. In my case, I wanted a very simple control: a dial or slider to set the output, and a label to display the current value. In less than 30 minutes I had this:
#!/usr/bin/env python # Simple Fan Control, v0.0.1 (2009-08-09) class SimpleFanControl(plasmascript.Applet): pwmfile = "/sys/class/hwmon/hwmon0/device/pwm2" def __init__(self, parent, args=None): plasmascript.Applet.__init__(self, parent) def init(self): self.setHasConfigurationInterface(False) self.setAspectRatioMode(Plasma.IgnoreAspectRatio) self.setBackgroundHints(Plasma.Applet.DefaultBackground) self.layout = QGraphicsLinearLayout(Qt.Vertical, self.applet) self.layout.setContentsMargins(0, 0, 0, 0) self.layout.setSpacing(0) self.setLayout(self.layout) current = self.getCurrent() self.label = Plasma.Label(self.applet) self.label.setText(str(current)) self.layout.addItem(self.label) self.slider = Plasma.Slider(self.applet) self.slider.setRange(0, 255) self.slider.setValue(current) self.slider.nativeWidget().setTracking(False) QObject.connect(self.slider, SIGNAL("sliderMoved(int)"), self.sliderMoved) QObject.connect(self.slider, SIGNAL("valueChanged(int)"), self.valueChanged) self.layout.addItem(self.slider) def sliderMoved(self, value): self.label.setText(str(value)) def valueChanged(self, value): self.label.setText(str(value)) pwm = open(self.pwmfile, 'w') pwm.write(str(value)) pwm.close() def getCurrent(self): pwm = open(self.pwmfile, 'r') value = int(pwm.readline().strip()) pwm.close() return value def CreateApplet(parent): return SimpleFanControl(parent)
Like I said, it is really simple; the device controlled by the widget is hard-coded in the script, no configuration is provided. It was just a quick personal "proof-of-concept", and it worked!
I liked the simplicity. With about 50 lines of code it is possible to have a functional slider widget that controls some random system variable.
The current widget has many limitations, though:
Since I created it just to serve my own needs, I didn't test it with any other configurations and I don't intend to maintain it (my next motherboard may not have the same feature), I won't upload it to KDE. I'm just publishing it here for reference. Fell free to use or modify it, at your own risk.
Download: http://hg.juliano.info/simple-fan-control/ (Mercurial repository)
| Users are advised to be careful when manually controlling system fan speeds. Insufficient fan rotation may cause permanent hardware damage. |