RaspberryPIとPythonによるLED制御(下のリンクの記事です)で自信をつけましたので、いよいよCPUファンの制御に挑戦したいと思います。Pythonの知識のほか、電子回路の知識を独学で習得しなければならなかったので、準備に時間がかかってしまいました。
なお、使用しているのはRaspberryPI_4Bです。
今回の目標
外部電源を使用する強力なCPUクーラーを動かすのではありません。
普通にラズパイからの給電で使用できる5.0VのCPUファンを使用して、ラズベリーパイの5.0V電源に直結した場合は常に全開で回転し、ノイズが大きく不快です。
目標としましては、「せめてCPU温度が低いときは回転を弱めたい」という考えです。
回路図 -CPUファン制御-
今回考えた回路図はこちらです。電子回路を考えたのも今回が初めてで、書籍などを見ながら作成しました。もしかしたら、なにか間違いがあるかもしれませんが、回路図通りに製作した回路はちゃんと動作しています。
回路図の説明
今回私が考えた回路図について説明していきます。
トランジスタ
トランジスタは通販で入手可能でさらに梱包数が少なく安く手に入るものを選定しました。みつみつ見つけたのはNPN型トランジスタ「2SC-1815-GR」という品で、10個入り送料込みで290円でした。TOSHIBAのデータシートがついていましたので、東芝製と思われます。
増幅倍率は温度その他条件により変わると思いますが標準値の「hEF=200」(200倍)として計算します。
B(ベース)に流した電流の200倍の電流がC(コレクタ)・E(エミッタ)間に流れるとして、計算を進めます。
ベース電流
ベース電流はRaspberryPI_4Bの3.3V電源を使用することとします。また、使用したいCPUファンの定格電流は5.0v、200mAでトランジスタの倍率はhEF=200のため必要なベース電流は1.0mAとします。
ベース電流は3.3vでコレクタ電流が5.0vの場合の計算方法が不明で迷ってしまいましたが、書籍などで調べたところ、電流(A)の開放値のみが関係していて特に電圧(v)は関係ないようです。(トランジスタの性能の範疇であれば、vは関係なしに計算できる)
抵抗(RB)の計算
ベース電流を3.3V、1.0mAとするために抵抗が必要です。抵抗の計算にはオームの法則を使用しますが、トランジスタの場合は少し工夫が必要のようです。
VBEは一般に0.7Vとすれば良さそうですので、この計算から抵抗RB=2,600Ω(2.6kΩ)とすることがわかります。
コレクタ電流
コレクタ電流はベース電流によって制御されますが、誤って流れすぎてしまわないよう抵抗を設置して、CPUファンの定格電流の値200mA以上の電流が流れないように調節します。
抵抗(RC)の計算
普通にオームの法則を使い算出し、抵抗(RC)は25Ωとしました。
ベース・エミッタ間の抵抗
ベースエミッタ間抵抗については正直理解度が足りていませんが、コレクタ遮断電流による誤作動を防ぐためとされているようです。
抵抗(RBE)の計算
必要な抵抗(R)は、トランジスタについていたデータシートから、コレクタ遮断電流は0.1μAとわかります。また、トランジスタが動作する最低の電圧は不明のため、VBEの0.7vとして計算しました。
7kΩより小さい数字でよいので、5kΩの抵抗としました。
完成した回路
完成した回路(ブレッドボード使用)がこちらです。抵抗については、ちょうど良いものはありませんでした。並列つなぎで丁度良い数値にしても良かったのですが、複雑になるので少し低めの抵抗をつけることにしました。
- RB = 2.2kΩ (計算値は2.6kΩ)
- RC = 22Ω (計算値は25Ω)
- RBE = 4.7kΩ (計算値は5kΩ)
次のページで、CPU温度によりCPUファンの回転を制御するPythonプログラムについて、紹介していきます。
Pythonプログラム -CPUファンの制御-
回路ができましたので、CPUファンを動かすプログラムを作成していきます。ここでは、シンプルにCPUファンを動かすだけの簡単なプログラムとします。今後は、このプログラムをベースにデーモン化してバックグラウンドで動かすなど、改良していきたいと思います。
プログラム(全様)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
import RPi.GPIO as GPIO import time import subprocess GPIO.setmode(GPIO.BCM) # PIN番号にするときは(GPIO.BOARD) pin = 18 # BCMの番号 GPIO.setup(pin, GPIO.OUT) #入力にする場合は(GPIO.IN) pwm = GPIO.PWM(pin,100) cut = 0 while cut < 8640: #Ends after 24 hours cut = cut + 1 args = ['cat','/sys/class/thermal/thermal_zone0/temp'] temp = subprocess.run(args,stdout=subprocess.PIPE,encoding='utf8') temp = round(int(temp.stdout)/1000,1) if temp < 50: dt = 50 elif temp < 70: dt = 75 else: dt = 100 pwm.start(dt) time.sleep(10) else: pwm.stop() GPIO.cleanup() |
プログラムの説明
プログラムについて簡単に説明します。間違いや、お気づきの点がありましたらご連絡いただけると嬉しいです。
1~3行目 ・・・ ライブラリのインポート
1 2 3 |
import RPi.GPIO as GPIO import time import subprocess |
GPIOを制御する「RPi.GPIO」、時間を扱う「time」、ラズベリーパイのコマンドを使用するための「subprocess」の3つを呼び出します。
5~10行名 ・・・ ピン番号の指定
5 |
GPIO.setmode(GPIO.BCM) # PIN番号にするときは(GPIO.BOARD) |
GPIOの番号指定方法をBCM番号に指定します。PIN番号とどちらか使いやすいほうでよいと思います。
7 8 |
pin = 18 # BCMの番号 GPIO.setup(pin, GPIO.OUT) #入力にする場合は(GPIO.IN) |
変数「pin」にBCM番号の18を入力、今回は電流の出力なので「GPIO.OUT」とします。使用するピンについては、ラズベリーパイ購入時の説明書についていたピン配列図からPWM制御ができそうな18番(ピン番号ですと12)を使用します。
10 |
pwm = GPIO.PWM(pin,100) |
PWM制御をするための周波数を指定しています。(最適値がわからなかったため、とりあえず100Hzとしました)
18~30行目 ・・・ CPU温度の取得とDuty比の設定
while文についての説明は省略しますが、24時間経過後にループから抜ける設定としています。
18 19 20 |
args = ['cat','/sys/class/thermal/thermal_zone0/temp'] temp = subprocess.run(args,stdout=subprocess.PIPE,encoding='utf8') temp = round(int(temp.stdout)/1000,1) |
「cat」を利用して温度を取得し、取得した数字を1/1000として温度を算出しています。詳しい解説は下記のリンクをご確認ください。
22 23 24 25 26 27 |
if temp < 50: dt = 50 elif temp < 70: dt = 75 else: dt = 100 |
典型的なIF文です。CPU温度が50℃未満であれば、dtに50を格納。50℃を超えて70度未満であれば、dtに75を格納。それ以外はdtに100を格納しています。
29 30 |
pwm.start(dt) time.sleep(10) |
先ほど取得したdtについては、「pwm.start(dt)」で Duty比として使用しています。dt=50であれば、50%の出力です。「time.sleep(10)」で10秒経過した後、while文により繰り返し処理が実行されます。
33行目 ・・・ ループからの離脱
33 |
pwm.stop() |
24時間経過後にループから抜けますので、「pwm.stop()」により出力を停止させます。
動作テスト
私のラズパイは、気温25℃前後の環境下でCPUファンを使用しなかった場合の温度は60℃前後で推移していました。今回のプログラム起動後数分で温度は50℃以下となり、その後50℃前後で落ち着くことがわかりました。
今回のプログラムは50℃以下でDuty比50%としているため、このような動きとなったともいます。数字についてはいろいろと調整して、ノイズ音を発生させない最適な回転速度を見つけていけばよいと思います。
CPU温度を連続取得するプログラムは下記リンクの記事で紹介しています。
今回使用したもの
ブレッドボード・ジャンパワイヤ
ブレッドボードは小さいもので大丈夫です。
ジャンパワイヤ(オス-オス)(メス-メス)(オス-メス)のセットが便利です。
抵抗など
抵抗(セット)は耐久性が高いとされている金属皮膜のものを使用しましたが、青ですと色が読みにくい場合があります。
目に自信がない方は炭素皮膜のほうが良いかもしれません。
LED(発光ダイオード)
ファンの動きに合わせてLEDを発光させる工夫を加える場合はこちらのセットが便利です。