.. note::

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

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

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

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

.. _4.1.13_py:

4.1.13 過熱モニター
================================

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

工場など、さまざまな状況で過熱監視装置を作成したい場合があります。例えば、回路が過熱した場合に警報を鳴らし、機械をタイムリーに自動的にオフにしたい場合などです。このプロジェクトでは、サーミスタ、ジョイスティック、ブザー、LED、LCDを使用して、しきい値が調整可能なスマートな温度監視装置を作成します。

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

このプロジェクトで必要なコンポーネントは以下の通りです。

.. image:: ../img/list_Overheat_Monitor.png
    :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_led`
        - |link_led_buy|
    *   - :ref:`cpn_joystick`
        - \-
    *   - :ref:`cpn_adc0834`
        - \-
    *   - :ref:`cpn_transistor`
        - |link_transistor_buy|
    *   - :ref:`cpn_i2c_lcd`
        - |link_i2clcd1602_buy|
    *   - :ref:`cpn_thermistor`
        - |link_thermistor_buy|
    *   - :ref:`cpn_buzzer`
        - \-

回路図
--------------------------

============ ======== ======== ===
T-Board Name physical wiringPi BCM
GPIO17       Pin 11   0        17
GPIO18       Pin 12   1        18
GPIO27       Pin 13   2        27
GPIO22       Pin15    3        22
GPIO23       Pin16    4        23
GPIO24       Pin18    5        24
SDA1         Pin 3             
SCL1         Pin 5              
============ ======== ======== ===

.. image:: ../img/Schematic_three_one8.png
   :align: center

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

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

.. image:: ../img/image258.png


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

.. raw:: html

   <run></run>

.. code-block:: 

    cd ~/raphael-kit/python/

**ステップ3**: 実行可能ファイルを実行します。

.. raw:: html

   <run></run>

.. code-block:: 

    sudo python3 4.1.13_OverheatMonitor.py

コードが実行されると、現在の温度と高温閾値 **40** が **I2C LCD1602** に表示されます。現在の温度がしきい値を超えると、ブザーとLEDが警告として起動します。

ここでの **ジョイスティック** は、高温の閾値を調整するためのものです。X軸とY軸の方向に **ジョイスティック** を切り替えることで、現在の高温閾値を調整（上げるか下げるか）できます。 **ジョイスティック** をもう一度押すと、しきい値が初期値にリセットされます。

.. note::

    * エラー ``FileNotFoundError: [Errno 2] No such file or directory: '/dev/i2c-1'`` が発生した場合、 :ref:`i2c_config` を参照してI2Cを有効にする必要があります。
    * エラー ``ModuleNotFoundError: No module named 'smbus2'`` が発生した場合、 ``sudo pip3 install smbus2`` を実行してください。
    * エラー ``OSError: [Errno 121] Remote I/O error`` が表示される場合、モジュールの配線が間違っているか、モジュールが壊れている可能性があります。
    * コードと配線が正しいにもかかわらず、LCDに内容が表示されない場合、背面のポテンショメータを回してコントラストを上げてみてください。

**コード**

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


.. raw:: html

    <run></run>

.. code-block:: python

    #!/usr/bin/env python3

    import LCD1602
    import RPi.GPIO as GPIO
    import ADC0834
    import time
    import math

    Joy_BtnPin = 22
    buzzPin = 23
    ledPin = 24

    upperTem = 40

    def setup():
        ADC0834.setup()
        GPIO.setmode(GPIO.BCM)
        GPIO.setup(ledPin, GPIO.OUT, initial=GPIO.LOW)
        GPIO.setup(buzzPin, GPIO.OUT, initial=GPIO.LOW)
        GPIO.setup(Joy_BtnPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
        LCD1602.init(0x27, 1)

    def get_joystick_value():
        x_val = ADC0834.getResult(1)
        y_val = ADC0834.getResult(2)
        if(x_val > 200):
            return 1
        elif(x_val < 50):
            return -1
        elif(y_val > 200):
            return -10
        elif(y_val < 50):
            return 10
        else:
            return 0

    def upper_tem_setting():
        global upperTem
        LCD1602.write(0, 0, 'Upper Adjust: ')
        change = int(get_joystick_value())
        upperTem = upperTem + change
        strUpperTem = str(upperTem)
        LCD1602.write(0, 1, strUpperTem)
        LCD1602.write(len(strUpperTem),1, '              ')
        time.sleep(0.1)

    def temperature():
        analogVal = ADC0834.getResult()
        Vr = 5 * float(analogVal) / 255
        Rt = 10000 * Vr / (5 - Vr)
        temp = 1/(((math.log(Rt / 10000)) / 3950) + (1 / (273.15+25)))
        Cel = temp - 273.15
        Fah = Cel * 1.8 + 32
        return round(Cel,2)

    def monitoring_temp():
        global upperTem
        Cel=temperature()
        LCD1602.write(0, 0, 'Temp: ')
        LCD1602.write(0, 1, 'Upper: ')
        LCD1602.write(6, 0, str(Cel))
        LCD1602.write(7, 1, str(upperTem))
        time.sleep(0.1)
        if Cel >= upperTem:
            GPIO.output(buzzPin, GPIO.HIGH)
            GPIO.output(ledPin, GPIO.HIGH)
        else:
            GPIO.output(buzzPin, GPIO.LOW)
            GPIO.output(ledPin, GPIO.LOW)       

    def loop():
        lastState=1
        stage=0
        while True:
            currentState=GPIO.input(Joy_BtnPin)
            if currentState==1 and lastState ==0:
                stage=(stage+1)%2
                time.sleep(0.1)    
                LCD1602.clear()
            lastState=currentState
            if stage == 1:
                upper_tem_setting()
            else:
                monitoring_temp()
        
    def destroy():
        LCD1602.clear() 
        ADC0834.destroy()
        GPIO.cleanup()

    if __name__ == '__main__':     # Program start from here
        try:
            setup()
            while True:
                loop()
        except KeyboardInterrupt:   # When 'Ctrl+C' is pressed, the program destroy() will be executed.
            destroy()

**コード説明**

.. code-block:: python

    def get_joystick_value():
        x_val = ADC0834.getResult(1)
        y_val = ADC0834.getResult(2)
        if(x_val > 200):
            return 1
        elif(x_val < 50):
            return -1
        elif(y_val > 200):
            return -10
        elif(y_val < 50):
            return 10
        else:
            return 0

この関数は X と Y の値を読み取ります。 **X>200** の場合、「\ **1**\ 」が返されます。 **X<50**、「\ **-1**\ 」を返します。 **y>200** の場合は「\ **-10**\ 」を返し、**y<50** の場合は「\ **10**\ 」を返します。

.. code-block:: python

    def upper_tem_setting():
        global upperTem
        LCD1602.write(0, 0, 'Upper Adjust: ')
        change = int(get_joystick_value())
        upperTem = upperTem + change
        LCD1602.write(0, 1, str(upperTem))
        LCD1602.write(len(strUpperTem),1, '              ')
        time.sleep(0.1)

この関数は、しきい値を調整し、I2C LCD1602に表示するためのものです。

.. code-block:: python

    def temperature():
        analogVal = ADC0834.getResult()
        Vr = 5 * float(analogVal) / 255
        Rt = 10000 * Vr / (5 - Vr)
        temp = 1/(((math.log(Rt / 10000)) / 3950) + (1 / (273.15+25)))
        Cel = temp - 273.15
        Fah = Cel * 1.8 + 32
        return round(Cel,2)

**ADC0834** の **CH0** （サーミスタ）のアナログ値を読み取り、温度値に変換します。

.. code-block:: python

    def monitoring_temp():
        global upperTem
        Cel=temperature()
        LCD1602.write(0, 0, 'Temp: ')
        LCD1602.write(0, 1, 'Upper: ')
        LCD1602.write(6, 0, str(Cel))
        LCD1602.write(7, 1, str(upperTem))
        time.sleep(0.1)
        if Cel >= upperTem:
            GPIO.output(buzzPin, GPIO.HIGH)
            GPIO.output(ledPin, GPIO.HIGH)
        else:
            GPIO.output(buzzPin, GPIO.LOW)
            GPIO.output(ledPin, GPIO.LOW)

コードが実行されると、現在の温度と高温閾値 **40** が **I2C LCD1602** に表示されます。現在の温度が閾値を超えると、ブザーとLEDが警告のために起動します。

.. code-block:: python

    def loop():
        lastState=1
        stage=0
        while True:
            currentState=GPIO.input(Joy_BtnPin)
            if currentState==1 and lastState ==0:
                stage=(stage+1)%2
                time.sleep(0.1)    
                LCD1602.clear()
            lastState=currentState
            if stage == 1:
                upper_tem_setting()
            else:
                monitoring_temp()

``main()`` 関数には、以下に示すプログラムプロセスが含まれています：

1) プログラムが開始されると、 **stage** の初期値は **0** で、現在の温度と高温閾値 **40** が **I2C LCD1602** に表示されます。現在の温度がしきい値を超えると、ブザーとLEDが警告のために起動します。

2) ジョイスティックを押すと、 **stage** は **1** になり、高温のしきい値を調整できます。X軸とY軸の方向にジョイスティックを切り替えると、現在の高温閾値を調整（上げるか下げるか）できます。ジョイスティックを再度押すと、しきい値が初期値にリセットされます。

現象の画像
-------------------------

.. image:: ../img/image259.jpeg
   :align: center