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側)

あらかじめ、[この記事](https://qiita.com/shinido/items/f25f71fc782ea56f0a45)を参考にしてパスフレーズなしでSSHログインできるようにしておいてください。

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

```shell:~/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端子**を接続します。[この記事](https://qiita.com/gorohash/items/5e5fb1c9829d82232ed0)のようにSSH接続できるようにします。

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

```c: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ファンの中に入っています．

![kairozu.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427284/8c8e96f0-fddd-c633-c6aa-f8c31c3f2bdf.jpeg)


![rgb-mos-fet.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427284/7a477e0d-3ea6-8bad-8e1c-da3ed10b841e.jpeg)

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

# 参考

[シェルスクリプトからSSHログインして別端末で作業させるときの異常系に関するメモ](https://qiita.com/shinido/items/f25f71fc782ea56f0a45)

[Raspberry Pi ZeroにUSB経由でSSH接続する](https://qiita.com/gorohash/items/5e5fb1c9829d82232ed0)

[RaspberryPiZeroを使ってソフトウェアPWMで三色LEDを光らせる](https://qiita.com/milmilk/items/548fc6e5e4a48cd0d4f9)

[MOS FETによるスイッチングの基礎](https://www.marutsu.co.jp/pc/static/large_order/fet_3)