RaspberryPiZeroを使ってPCを負荷に応じて光らせる


はじめに

自作PCに光るファンを付けてみたけど、ただ光るだけじゃつまらないですね。どうせならPCの負荷によって光り方を変えてみましょう

マザーボードにLEDの端子があるものもありますが、私のマザボにはありませんでした。そこで、RaspberryPiのGPIOピンを使ってファンのLEDを光らせました。

概要

PCのCPU使用率を一定時間ごとに監視して、SSHでRaspberryPiZeroに送信します。RaspberryPiZeroでは受信した値をもとにLEDをPWM制御します。MOS-FETを使って昇圧してファンのLEDを光らせます。

環境

Ubuntu 18.04.3 LTS
Raspberry Pi Zero WH
Raspbian 10.0
NchパワーMOSFET 2SK4017(Q)

負荷を監視してRaspberryPiZeroに送信(PC側)

あらかじめ、この記事を参考にしてパスフレーズなしでSSHログインできるようにしておいてください。

vmstatでCPU使用率を監視しSSHで送信するシェルスクリプトを、適当な場所に置きます。今回はホームディレクトリに置きます。

~/led.sh
#!/bin/bash

idl=$(vmstat | tail -n 1 | awk '{print $15}')
f='~/ledValue.txt'
ssh -t raspberrypi "echo ${idl} > ${f}"

cronで上記のシェルスクリプトを定期実行するようにします。/etc/cron.d/my_cronを作成します。1分ごとに負荷をCPU使用率を調べる場合は以下のように記述します。

/etc/cron.d/my_cron
# m h dom mon dow user  command
* * * * *   user_name /home/user_name/led.sh
#

これでRaspberryPiZeroの~/ledValue.txtが1分ごとに書き換わります。

PWM制御(RaspberryPiZero側)

パソコンのUSB端子RaspberryPiZeroのmicroUSB端子を接続します。この記事のようにSSH接続できるようにします。

PWM制御については以下の記事に書きました。
RaspberryPiZeroを使ってソフトウェアPWMで三色LEDを光らせる
ファイルはホームディレクトリに配置します。また、ledmain.cは以下のようにしました。value変数にPCのCPU使用率(%)が格納されるので、好きなように編集してください。

ledmain.c
#include <stdio.h>
#include <pigpio.h>
#include "ledgpio.h"

/**
 * @fn
 * HSV形式をRGB形式に変換する.
 * @param (h) 色相
 * @param (s) 彩度
 * @param (v) 明度
 * @param (rgb) 出力
 */
void hsv2rgb(double h, double s, double v, double rgb[3]){
    rgb[0] = v;
    rgb[1] = v;
    rgb[2] = v;
    int i;
    double f;
    if (s > 0.0) {
        h *= 6.0;
        i = (int) h;
        f = h - (double) i;
        switch (i) {
            default:
            case 0:
                rgb[1] *= 1 - s * (1 - f);
                rgb[2] *= 1 - s;
                break;
            case 1:
                rgb[0] *= 1 - s * f;
                rgb[2] *= 1 - s;
                break;
            case 2:
                rgb[0] *= 1 - s;
                rgb[2] *= 1 - s * (1 - f);
                break;
            case 3:
                rgb[0] *= 1 - s;
                rgb[1] *= 1 - s * f;
                break;
            case 4:
                rgb[0] *= 1 - s * (1 - f);
                rgb[1] *= 1 - s;
                break;
            case 5:
                rgb[1] *= 1 - s;
                rgb[2] *= 1 - s * f;
                break;
        }
    }
}

int main(void){
    FILE *fp;
    char fname[] = "ledValue.txt"; // CPU使用率が格納されたファイル
    double hue, rgb[3];
    long usec;
    int value; // CPU使用率(%)
    int pin[3] = {17, 18, 19}; // RaspberryPiのGPIOピン番号

    // 初期化
    if(gpioInitialise() < 0) return 1;
    pinInitialise(pin);

    while(1){
        // ファイルからCPU使用率を読み込む
        if((fp = fopen(fname, "r")) == NULL) return 1;
        fscanf(fp, "%d", &value);
        fclose(fp);

        // LEDを光らせる
        hue = (double)value * 0.00666;
        hsv2rgb(hue, 1.0, 1.0, rgb);
        usec = 500000 + 15000 * value;
        colorLed(rgb[0], rgb[1], rgb[2], usec, pin); // usecマイクロ秒だけ点灯する
        colorLed(0.0   , 0.0   , 0.0   , usec, pin); // usecマイクロ秒だけ消灯する
    }

    // ファイナライズ
    pinTerminate(pin);
    gpioTerminate();
    return 0;
}

昇圧する

RaspberryPiZeroの出力電圧は3.3Vです。ファンのLEDを光らせるためには12Vに昇圧する必要があります。

12V電源とGNDはPCの電源ユニットから取ります。LEDのアノードを12Vに接続します。

  • 12V → LEDのアノード

MOS-FETにはゲート(G)、ソース(S)、ドレイン(D)があります。以下のように繋ぎます。

  • ゲート(G) → RaspberryPiZeroのGPIOピン
  • ソース(S) → GND
  • ドレイン(D) → LED

RGBそれぞれについて上記のように繋ぎます。つまり、MOS-FETは3つ必要です。

回路図は以下のようになります.おそらく,抵抗とLEDはRGBファンの中に入っています.

おわりに

RaspberryPiZeroを経由するぶん作業量が多くなってしまいました。これで「私のPCは無駄にチカチカ光ってるわけじゃないんだ」と言い張れるようになりました。

参考

シェルスクリプトからSSHログインして別端末で作業させるときの異常系に関するメモ

Raspberry Pi ZeroにUSB経由でSSH接続する

RaspberryPiZeroを使ってソフトウェアPWMで三色LEDを光らせる

MOS FETによるスイッチングの基礎