Raspberry PiでFANをPWM制御する。(自作ライブラリ版)

前回投稿で利用したpigpiodのCPU使用率が高過ぎて気になったので自作ライブラリに切り替えたら5℃前後も温度が下がってしまった。

Raspberry PiでFANをPWM制御する。

しかし、温度を下げるためのプログラムが逆に温度を上げてしまうなんて本末転倒もいいところかも。(-_-;)

【ファンが回ってるところ】
ファンは吸気方向で取り付けるようになっていたがそれだと掃除機のごとくゴミ溜めになってしまうのが気になるのとそんなに高負荷をかける使い方もしないのでファンをひっくり返して排気方向になるよう取り付けてみた。PWMを50℃(0%)~60℃(100%)で無段階調整する設定にしていると軽負荷ではユルユルと回り始めほぼ無音状態(耳を近づけてなんとか聞こえるレベル)で安定する。

作成したライブラリは全てのRaspberry Piで動作するよう努力したつもりではあるが試したのは4B/400/02W/0のみで他のモデルは動作するか不明。実行にはROOT権限が必要なことに注意しよう。

モデル判定のために利用したbcm_host.h/bcm_host.cについては下記公式サイトで紹介されているライブラリの一部であり余分なファイルがなくてもコンパイルできるよう一部をコメントアウトしてある。

Raspberry Pi Hardware

ちなみに、おまけで作ったライブラリのdigitalWrite()の速度を試してみたら約12MHzも出る。想定外に早い...かも。

それとPWM用のクロックソースはPLLDを使用しているがモデルにより500MHzと750MHzの2種類があるのでどちらでも割り切れてPWM規定の100MHz以下の50MHzをPWMクロックとしてみた。試しに250MHzでやってみたら見事に誤動作してしまったが125MHzならいけるかも。

割り切れない周波数であってもMASHで分周するので周波数的には問題なさそうなものの補正がかかるたびにPWMクロックのエッジ・タイミングが微妙にズレてしまうので注意すべし。参考まで。

【Download】
pwmfan.zip

※/opt/pwmfan等の適当なディレクトリに展開コピーし、sudo ./make.shした後、sudo ./install.shするとsystemdに登録してくれる。

【Update】
2024-09-27
最近世の中が暑くなってきているのでもっと冷えそうなファン付きケースに交換したのはいいがファンが2線式のブラシレスモーターだったのでPWM制御できなくなってしまった。3線式のモーターに変えようかなとも思ったが合うものがなかなか見つからない。ファンは静かなので回しっぱなしでもいいけれど耐久性を考えるとやっぱり温度制御したいところだ。ただラズパイ標準のGPIOファン制御は60℃から...もっと低い温度からオンオフ制御(0% or 100%)できるよう最低温度と最高温度の設定を同じにできるようにプログラムを少し変更してみた。
例: pwmfan -c 50 -h 50
ちなみに2線式のモータを制御するには下図のようにN-MOSなどを使った簡単なモータードライバー回路が必要となる。

このケースは肉厚があって重くていい感じ。温度の上がり方がゆっくりで軽負荷ならファンが回ることはなく室温28℃のとき44℃前後で安定する。但し、ファンは2線式なので制御するには上図のような外部回路が必要となる。
GeeekPi Raspberry Pi 4アーマーケース

Flircのケースより肉厚で重いのは良いがCPU以外のチップの放熱用突起がないのとファンがないので室温の高い部屋など環境により長時間稼働には向かなさそう。
Raspberry Pi 4B 専用 ヒートシンクケース(ブラック)【RPH-4B-H-B】

このケースが一番肉厚が薄くて温度が上がりやすい。CPU以外のチップの放熱用突起もない。長時間稼働向きではない。
Flirc ラズベリーパイ4ケース シルバー

この投稿とは関係ないけど、Pi5のケースなら次のが超お勧め。低負荷だとファンは回らないし普通サイズのNVME-SSDが使えるしSSDの放熱対策もバッチリなので安心して使える。少しお値段は高いけど満足度は高い。NVME-SSDからの起動は約6秒と爆速なのでお試しあれ。
Argon NEO 5 M.2 NVME PCIEハウジング

2022-07-31
pinmode.hの修正。他のライブラリとの互換性のためだけの修正なので動作には影響なし。

2022-07-28
pinmode.hを追加。

2022-07-21
アプリ側とライブラリ内部で同じようなPWMデューティサイクル計算が必要で二度手間だったのを解消しアプリのコードがより簡単にかけるようにanalogWrite()の引数にデューティサイクルの範囲(range)を追加。

2022-07-20
モデルにより異なるクリスタルやPLLDクロック、GPIOタイプを指定して初期化できるように改良。この改良により自動設定が対応できないモデルが出てきたとしてもアプリ側でパラメタを指定して使うことが可能となる。begin()の第一引数(xosc_freq)を省略(ゼロ指定)すると自動設定、ゼロ以外を指定すると手動設定となる。xosc_freq/plld_freqは間違った指定をするとPWMの周波数が不正になり、gpio_typeは自動判定できないときにのみ参照されるが間違った指定をするとGPIOのプルアップ/プルダウン設定が誤動作する。

int begin(uint32_t xosc_freq = 0, uint32_t plld_freq = 0, uint32_t gpio_type = 0);
xosc_freq … クリスタルクロック(Hz)
plld_freq … PLLDクロック(Hz)
gpio_type … 0=BCM2835互換仕様, 1=BCM2711(pi4)互換仕様。

2022-07-19
CPU判別がうまく動作しないせいで誤動作するモデルがあるのでCPUではなくモデルで判定するように修正。それとクリスタルの周波数を取得する方法を見つけたのでそれを元にPLLDクロックを決定するように修正。

【PWM-FAN制御プログラム】

【ライブラリ】