.. include:: /index.rst :start-after: start_hello_message :end-before: end_hello_message .. _py_fun_fan: 4.7 スマートファン ========================= **はじめに** このプロジェクトでは、手動モードと自動モードの両方で動作する「スマートファン」を作成します。モーター、ボタン、サーミスタを組み合わせることで、ファンの風量を調整できるだけでなく、温度変化にも応答できるようになります。モーター制御、温度検知、GPIO の使い方を学ぶのに最適な実験です。 ---------------------------------------------- **必要なもの** このプロジェクトで必要なコンポーネントは以下のとおりです。 .. list-table:: :widths: 30 20 :header-rows: 1 * - COMPONENT INTRODUCTION - PURCHASE LINK * - :ref:`cpn_breadboard` - |link_breadboard_buy| * - :ref:`cpn_wires` - |link_wires_buy| * - :ref:`cpn_resistor` - |link_resistor_buy| * - :ref:`cpn_thermistor` - |link_thermistor_buy| * - :ref:`cpn_button` - |link_button_buy| * - :ref:`cpn_motor` - |link_motor_buy| * - :ref:`cpn_fusion_hat` - \- * - Raspberry Pi - \- ---------------------------------------------- **回路図** 以下の回路図は、サーミスタ、ボタン、モータードライバー、およびモーターの接続方法を示しています。 .. image:: img/fzz/4.1.7_sch.png :width: 100% :align: center ---------------------------------------------- **配線図** ブレッドボード上のレイアウトと配線接続は、以下の図を参照してください。 .. image:: img/fzz/4.1.7_bb.png :width: 80% :align: center ---------------------------------------------- **サンプルの実行** このチュートリアルで使用するすべてのサンプルコードは ``ai-lab-kit`` ディレクトリに含まれています。 以下の手順に従ってサンプルを実行してください。 .. raw:: html .. code-block:: shell cd ~/ai-lab-kit/python/ sudo python3 4.7_SmartFan.py ---------------------------------------------- **コード** 以下は、このプロジェクトで使用する Python スクリプトです。 .. raw:: html .. code-block:: python #!/usr/bin/env python3 from fusion_hat.motor import Motor from fusion_hat.pin import Pin, Mode, Pull from fusion_hat.adc import ADC from time import sleep, time import math BtnPin = Pin(22, mode=Mode.IN, pull=Pull.DOWN) motor = Motor("M0") thermistor = ADC("A3") level = 0 currentTemp = None markTemp = None PRINT_INTERVAL = 1.0 _last_print = 0.0 button_event = False # flag: button was pressed def temperature(samples=5, delay=0.01): """Read thermistor multiple times and return averaged Celsius (float) or None.""" vals = [] for _ in range(samples): analogVal = thermistor.read() Vr = 3.3 * float(analogVal) / 4095.0 if (3.3 - Vr) <= 0.1: return None Rt = 10000.0 * Vr / (3.3 - Vr) tempK = 1.0 / (((math.log(Rt / 10000.0)) / 3950.0) + (1.0 / (273.15 + 25.0))) vals.append(tempK - 273.15) sleep(delay) return sum(vals) / len(vals) def motor_run(lv): lv = max(0, min(4, lv)) motor.power(0 if lv == 0 else lv * 25) return lv def changeLevel(): """Button press: cycle level 0~4 and set a flag for main loop to print.""" global level, button_event level = (level + 1) % 5 button_event = True BtnPin.when_activated = changeLevel def main(): global level, currentTemp, markTemp, _last_print, button_event markTemp = temperature() while True: currentTemp = temperature() if currentTemp is None: print("Sensor read failed. Please check the sensor.") sleep(0.5) continue # Handle button event in main loop (stable timing) if button_event: button_event = False markTemp = currentTemp print(f"[Button] Level -> {level} | Temp: {currentTemp:.2f} °C | Mark: {markTemp:.2f} °C") # Periodic temperature print now = time() if now - _last_print >= PRINT_INTERVAL: if markTemp is None: markTemp = currentTemp print(f"Temp: {currentTemp:.2f} °C | Mark: {markTemp:.2f} °C | Level: {level}") _last_print = now # Auto adjust level based on ±5°C if markTemp is None: markTemp = currentTemp if level != 0: diff = currentTemp - markTemp if diff <= -5: level = max(0, level - 1) markTemp = currentTemp print(f"[Auto] Temp down -> Level {level} (Temp: {currentTemp:.2f} °C)") elif diff >= 5: level = min(4, level + 1) markTemp = currentTemp print(f"[Auto] Temp up -> Level {level} (Temp: {currentTemp:.2f} °C)") level = motor_run(level) sleep(0.5) try: main() except KeyboardInterrupt: print("\nExiting...") finally: motor.stop() sleep(0.1) この Python スクリプトは、モーター、ボタン、および温度センサーを組み合わせて、温度に応じて動作し、速度を調整できるファンシステムを作成します。実行すると、次のように動作します。 1. **温度の測定**: サーミスタを使用して現在の摂氏温度を読み取ります。 2. **手動での風量調整**: - GPIO22 に接続されたボタンにより、ユーザーは 5 段階の風量レベル(0~4)を順番に切り替えることができます。 - ボタンを押すたびに風量レベルが 1 段階上がり、モーターは対応する速度で動作します。レベル 0 ではモーターが停止します。 3. **自動風量制御**: システムは温度変化に応じてモーター速度を自動調整します。 - 温度が 5°C 以上上昇すると、風量レベルが 1 段階上がります(最大レベル 4)。 - 温度が 5°C 以上低下すると、風量レベルが 1 段階下がります(最小レベル 0)。 4. **継続的な監視**: システムは温度を継続的に監視し、それに応じてファン速度を調整します。 5. **安全な終了**: ``Ctrl+C`` を押すと、モーターを停止し、スクリプトは安全に終了します。 ---------------------------------------------- **コードの解説** 1. **温度の計算:** .. code-block:: python def temperature(samples=5, delay=0.01): """Read thermistor multiple times and return averaged Celsius (float) or None.""" vals = [] for _ in range(samples): analogVal = thermistor.read() Vr = 3.3 * float(analogVal) / 4095.0 if (3.3 - Vr) <= 0.1: return None Rt = 10000.0 * Vr / (3.3 - Vr) tempK = 1.0 / (((math.log(Rt / 10000.0)) / 3950.0) + (1.0 / (273.15 + 25.0))) vals.append(tempK - 273.15) sleep(delay) return sum(vals) / len(vals) ``temperature()`` 関数は、サーミスタのアナログ値を複数回読み取り、抵抗値へ変換し、数式を用いて対応する温度を計算します。 2. **モーター速度制御:** .. code-block:: python def motor_run(lv): lv = max(0, min(4, lv)) motor.power(0 if lv == 0 else lv * 25) return lv ``motor_run()`` 関数は、 ``level`` 変数に応じてモーター速度を調整します。速度は 0~4 の範囲に制限され、それに応じた出力が設定されます。 3. **手動での風量調整:** .. code-block:: python def changeLevel(): """Button press: cycle level 0~4 and set a flag for main loop to print.""" global level, button_event level = (level + 1) % 5 button_event = True BtnPin.when_activated = changeLevel ``changeLevel()`` 関数は、ボタンが押されるたびに風量レベルを 0~4 の範囲で順番に切り替えます。 4. **自動での風量調整:** .. code-block:: python def main(): global level, currentTemp, markTemp, _last_print, button_event markTemp = temperature() while True: currentTemp = temperature() if currentTemp is None: print("Sensor read failed. Please check the sensor.") sleep(0.5) continue ... ``main()`` 関数は温度を継続的に監視し、基準温度から 5°C 以上ずれた場合にファン速度を自動調整します。 ---------------------------------------------- **トラブルシューティング** 1. **モーターが動作しない** : - **原因** : 配線ミス、または電源不足。 - **対処方法** : - モーターが M0 に接続されていることを確認してください。 - モーターの電源が必要電圧を満たしていることを確認してください。 2. **温度読み取りが正しくない**: - **原因** : サーミスタの不具合。 - **対処方法**: - サーミスタの配線を確認し、仕様範囲内で使用されていることを確認してください。 3. **ボタン入力が検出されない** : - **原因** : ボタン配線または GPIO 設定の誤り。 - **対処方法** : - ボタンが GPIO22 と GND に接続されていることを確認してください。 - ボタン単体で、押したときに回路が閉じるかどうかをテストしてください。 4. **風量レベルが自動で変わらない**: - **原因** : 温度差の計算が正しくありません。 - **対処方法** : ``main()`` 関数内で ``currentTemp`` と ``markTemp`` が正しく更新されていることを確認してください。 ---------------------------------------------- **拡張アイデア** 1. **過熱アラート**: 温度が危険なしきい値を超えたときに、ブザーや LED で警告を出します。 .. code-block:: python if currentTemp > 50: buzzer.on() 2. **スマートボタン機能**: ボタンの長押しで風量レベルを 0 にリセットしたり、自動/手動モードを切り替えたりできるようにします。 ---------------------------------------------- **まとめ** スマートファンのプロジェクトでは、手動制御と自動制御を 1 つのシステムに統合する方法を学べます。これは、センサー、モーター、ユーザー操作を組み合わせた、実用的で効率的な設計例です。さらに機能を追加して、自分だけの温度制御システムへ発展させてみてください。