.. note::

    こんにちは、SunFounderのRaspberry Pi & Arduino & ESP32愛好家コミュニティへようこそ！Facebook上でRaspberry Pi、Arduino、ESP32についてもっと深く掘り下げ、他の愛好家と交流しましょう。

    **参加する理由は？**

    - **エキスパートサポート**：コミュニティやチームの助けを借りて、販売後の問題や技術的な課題を解決します。
    - **学び＆共有**：ヒントやチュートリアルを交換してスキルを向上させましょう。
    - **独占的なプレビュー**：新製品の発表や先行プレビューに早期アクセスしましょう。
    - **特別割引**：最新製品の独占割引をお楽しみください。
    - **祭りのプロモーションとギフト**：ギフトや祝日のプロモーションに参加しましょう。

    👉 私たちと一緒に探索し、創造する準備はできていますか？[|link_sf_facebook|]をクリックして今すぐ参加しましょう！

.. _4.1.10_py_pi5:

4.1.7 スマートファン
=========================

はじめに
-----------------

このプロジェクトでは、モーター、ボタン、サーミスタを使用して、風速調節可能なマニュアル+自動スマートファンを作成します。

必要な部品
------------------------------

このプロジェクトには、次のコンポーネントが必要です。

.. image:: ../python_pi5/img/4.1.10_smart_fan_list.png
    :width: 800
    :align: center

一式を購入するのが便利です、こちらがリンクです： 

.. list-table::
    :widths: 20 20 20
    :header-rows: 1

    *   - 名前	
        - このキットのアイテム
        - リンク
    *   - Raphael Kit
        - 337
        - |link_Raphael_kit|

以下のリンクから別々に購入することもできます。

.. list-table::
    :widths: 30 20
    :header-rows: 1

    *   - コンポーネントの紹介
        - 購入リンク

    *   - :ref:`cpn_gpio_board`
        - |link_gpio_board_buy|
    *   - :ref:`cpn_breadboard`
        - |link_breadboard_buy|
    *   - :ref:`cpn_wires`
        - |link_wires_buy|
    *   - :ref:`cpn_resistor`
        - |link_resistor_buy|
    *   - :ref:`cpn_power_module`
        - \-
    *   - :ref:`cpn_thermistor`
        - |link_thermistor_buy|
    *   - :ref:`cpn_l293d`
        - \-
    *   - :ref:`cpn_adc0834`
        - \-
    *   - :ref:`cpn_button`
        - |link_button_buy|
    *   - :ref:`cpn_motor`
        - |link_motor_buy|
        
回路図
------------------------

============ ======== ======== ===
T-Board Name physical wiringPi BCM
GPIO17       Pin 11   0        17
GPIO18       Pin 12   1        18
GPIO27       Pin 13   2        27
GPIO22       Pin 15   3        22
GPIO5        Pin 29   21       5
GPIO6        Pin 31   22       6
GPIO13       Pin 33   23       13
============ ======== ======== ===

.. image:: ../python_pi5/img/4.1.10_smart_fan_schematic.png
   :align: center

実験手順
-----------------------------

**ステップ1:** 回路を組み立てます。

.. image:: ../python_pi5/img/4.1.10_smart_fan_circuit.png

.. note::
    電源モジュールにはキット内の9Vバッテリーと9Vバッテリーバックルを使用できます。電源モジュールのジャンパーキャップを、ブレッドボードの5Vバスストリップに挿入します。

.. image:: ../python_pi5/img/4.1.10_smart_fan_battery.jpeg
   :align: center

**ステップ2**: コードのフォルダに移動します。

.. raw:: html

   <run></run>

.. code-block:: 

    cd ~/raphael-kit/python-pi5

**ステップ3**: 実行します。

.. raw:: html

   <run></run>

.. code-block:: 

    sudo python3 3.1.4_SmartFan_zero.py

コードが実行されると、ボタンを押してファンを起動します。ボタンを押すたびに、風速が1段階上下に調節されます。風速は **0〜4** の **5つ** の段階があります。4番目の風速に設定されており、ボタンを押すと風速 **0** でファンが停止します。

温度が2℃以上上昇または下降すると、速度は自動的に1段階高くまたは低くなります。

コード
--------

.. note::
    以下のコードを **変更/リセット/コピー/実行/停止** することができます。ただし、変更する前に ``raphael-kit/python-pi5`` のようなソースコードのパスに移動する必要があります。コードを変更した後、効果を確認するために直接実行できます。

.. raw:: html

    <run></run>

.. code-block:: python

   #!/usr/bin/env python3

   from gpiozero import Motor, Button
   from time import sleep
   import ADC0834
   import math

   # Initialize GPIO pins for the button and motor control
   BtnPin = Button(22)
   motor = Motor(forward=5, backward=6, enable=13)

   # Initialize the ADC0834 module for temperature sensing
   ADC0834.setup()

   # Initialize variables to track the motor speed level and temperatures
   level = 0
   currentTemp = 0
   markTemp = 0

   def temperature():
       """
       Reads and calculates the current temperature from the sensor.
       Returns:
           float: The current temperature in Celsius.
       """
       # Read analog value from the ADC0834 module
       analogVal = ADC0834.getResult()
       # Convert analog value to voltage and then to resistance
       Vr = 5 * float(analogVal) / 255
       Rt = 10000 * Vr / (5 - Vr)
       # Calculate temperature in Celsius
       temp = 1 / (((math.log(Rt / 10000)) / 3950) + (1 / (273.15 + 25)))
       Cel = temp - 273.15
       return Cel

   def motor_run(level):
       """
       Adjusts the motor speed based on the specified level.
       Args:
           level (int): Desired motor speed level.
       Returns:
           int: Adjusted motor speed level.
       """
       # Stop the motor if the level is 0
       if level == 0:
           motor.stop()
           return 0
       # Cap the level at 4 for maximum speed
       if level >= 4:
           level = 4
       # Set the motor speed
       motor.forward(speed=float(level / 4))
       return level

   def changeLevel():
       """
       Changes the motor speed level when the button is pressed and updates the reference temperature.
       """
       global level, currentTemp, markTemp
       print("Button pressed")
       # Cycle through levels 0-4
       level = (level + 1) % 5
       # Update the reference temperature
       markTemp = currentTemp

   # Bind the button press event to changeLevel function
   BtnPin.when_pressed = changeLevel

   def main():
       """
       Main function to continuously monitor and respond to temperature changes.
       """
       global level, currentTemp, markTemp
       # Set initial reference temperature
       markTemp = temperature()
       while True:
           # Continuously read current temperature
           currentTemp = temperature()
           # Adjust motor level based on temperature difference
           if level != 0:
               if currentTemp - markTemp <= -2:
                   level -= 1
                   markTemp = currentTemp
               elif currentTemp - markTemp >= 2:
                   if level < 4:
                       level += 1
                   markTemp = currentTemp
           # Run the motor at the adjusted level
           level = motor_run(level)

   # Run the main function and handle KeyboardInterrupt
   try:
       main()
   except KeyboardInterrupt:
       # Stop the motor when the script is interrupted
       motor.stop()



コードの説明
---------------------

#. モーターやボタンの管理用クラス、一時停止を導入するための sleep 関数、温度センシングのための ADC0834 ライブラリ、数学的な計算のための math ライブラリをインポートします。

   .. code-block:: python

       #!/usr/bin/env python3

       from gpiozero import Motor, Button
       from time import sleep
       import ADC0834
       import math

#. ボタンを GPIO ピン 22 に設定し、モーターの制御に特定の GPIO ピンを設定します。温度測定用に ADC0834 モジュールを初期化します。また、モーター速度レベルと温度を監視するための変数を初期化します。

   .. code-block:: python

       # Initialize GPIO pins for the button and motor control
       BtnPin = Button(22)
       motor = Motor(forward=5, backward=6, enable=13)

       # Initialize the ADC0834 module for temperature sensing
       ADC0834.setup()

       # Initialize variables to track the motor speed level and temperatures
       level = 0
       currentTemp = 0
       markTemp = 0

#. センサーから温度を読み取り、摂氏に変換するための関数を定義します。

   .. code-block:: python

       def temperature():
           """
           Reads and calculates the current temperature from the sensor.
           Returns:
               float: The current temperature in Celsius.
           """
           # Read analog value from the ADC0834 module
           analogVal = ADC0834.getResult()
           # Convert analog value to voltage and then to resistance
           Vr = 5 * float(analogVal) / 255
           Rt = 10000 * Vr / (5 - Vr)
           # Calculate temperature in Celsius
           temp = 1 / (((math.log(Rt / 10000)) / 3950) + (1 / (273.15 + 25)))
           Cel = temp - 273.15
           return Cel

#. 指定したレベルに基づいてモーターの速度を調整する関数を実装します。

   .. code-block:: python

       def motor_run(level):
           """
           Adjusts the motor speed based on the specified level.
           Args:
               level (int): Desired motor speed level.
           Returns:
               int: Adjusted motor speed level.
           """
           # Stop the motor if the level is 0
           if level == 0:
               motor.stop()
               return 0
           # Cap the level at 4 for maximum speed
           if level >= 4:
               level = 4
           # Set the motor speed
           motor.forward(speed=float(level / 4))
           return level

#. ボタンを使用してモーターの速度レベルを手動で変更し、この関数をボタンのプレスイベントにバインドします。

   .. code-block:: python

       def changeLevel():
           """
           Changes the motor speed level when the button is pressed and updates the reference temperature.
           """
           global level, currentTemp, markTemp
           print("Button pressed")
           # Cycle through levels 0-4
           level = (level + 1) % 5
           # Update the reference temperature
           markTemp = currentTemp

       # Bind the button press event to changeLevel function
       BtnPin.when_pressed = changeLevel

#. 温度変化に応じてモーターの速度を連続的に調整するメイン関数を実装することが残っています。

   .. code-block:: python

       def main():
           """
           Main function to continuously monitor and respond to temperature changes.
           """
           global level, currentTemp, markTemp
           # Set initial reference temperature
           markTemp = temperature()
           while True:
               # Continuously read current temperature
               currentTemp = temperature()
               # Adjust motor level based on temperature difference
               if level != 0:
                   if currentTemp - markTemp <= -2:
                       level -= 1
                       markTemp = currentTemp
                   elif currentTemp - markTemp >= 2:
                       if level < 4:
                           level += 1
                       markTemp = currentTemp
               # Run the motor at the adjusted level
               level = motor_run(level)

#. メイン関数を実行し、スクリプトが中断された場合にモーターが停止することを保証する。

   .. code-block:: python

       # Run the main function and handle KeyboardInterrupt
       try:
           main()
       except KeyboardInterrupt:
           # Stop the motor when the script is interrupted
           motor.stop()

