.. note::

    Ciao, benvenuto nella SunFounder Raspberry Pi & Arduino & ESP32 Enthusiasts Community su Facebook! Approfondisci le tue conoscenze su Raspberry Pi, Arduino ed ESP32 insieme ad altri appassionati.

    **Perché unirti a noi?**

    - **Supporto Esperto**: Risolvi problemi post-vendita e sfide tecniche con l'aiuto della nostra comunità e del nostro team.
    - **Impara & Condividi**: Scambia suggerimenti e tutorial per migliorare le tue abilità.
    - **Anteprime Esclusive**: Ottieni accesso anticipato a nuovi annunci di prodotti e anteprime speciali.
    - **Sconti Speciali**: Approfitta di sconti esclusivi sui nostri prodotti più recenti.
    - **Promozioni Festive e Omaggi**: Partecipa a concorsi e promozioni durante le festività.

    👉 Pronto a esplorare e creare con noi? Clicca su [|link_sf_facebook|] e unisciti oggi stesso!

.. _4.1.13_py:

4.1.13 Monitor Surriscaldamento
=====================================

Introduzione
----------------------

Potresti voler realizzare un dispositivo di monitoraggio del surriscaldamento 
che si adatta a diverse situazioni, ad esempio in fabbrica, per attivare un allarme 
e spegnere automaticamente la macchina quando un circuito si surriscalda. In questo 
progetto, utilizzeremo un termistore, un joystick, un buzzer, un LED e un LCD per 
creare un dispositivo intelligente di monitoraggio della temperatura con soglia regolabile.

Componenti Necessari
------------------------------

In questo progetto, avremo bisogno dei seguenti componenti.

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

È sicuramente conveniente acquistare un kit completo, ecco il link:

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

    *   - Nome
        - ELEMENTI IN QUESTO KIT
        - LINK
    *   - Kit Raphael
        - 337
        - |link_Raphael_kit|

Puoi anche acquistarli separatamente dai link sottostanti.

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

    *   - INTRODUZIONE AI COMPONENTI
        - LINK PER L'ACQUISTO

    *   - :ref:`cpn_gpio_extension_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`
        - \-

Schema Elettrico
--------------------------

============ ======== ======== ===
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

Procedure Sperimentali
-----------------------------

**Passo 1:** Costruisci il circuito.

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


**Passo 2:** Accedi alla cartella del codice.

.. raw:: html

   <run></run>

.. code-block:: 

    cd ~/raphael-kit/python/

**Passo 3:** Esegui il file eseguibile.

.. raw:: html

   <run></run>

.. code-block:: 

    sudo python3 4.1.13_OverheatMonitor.py

Durante l'esecuzione del codice, la temperatura corrente e la soglia di alta 
temperatura **40** vengono visualizzate su **I2C LCD1602**. Se la temperatura 
corrente supera la soglia, il buzzer e il LED si attivano per avvisarti.

Il **Joystick** viene utilizzato per regolare la soglia di alta temperatura. 
Muovendo il **Joystick** lungo l'asse X e Y puoi aumentare o diminuire la soglia 
di alta temperatura corrente. Premi nuovamente il **Joystick** per ripristinare 
la soglia al valore iniziale.

.. note::

    * Se ricevi l'errore ``FileNotFoundError: [Errno 2] No such file or directory: '/dev/i2c-1'``, fai riferimento a :ref:`i2c_config` per abilitare l'I2C.
    * Se ricevi l'errore ``ModuleNotFoundError: No module named 'smbus2'``, esegui ``sudo pip3 install smbus2``.
    * Se compare l'errore ``OSError: [Errno 121] Remote I/O error``, significa che il modulo è cablato in modo errato o è danneggiato.
    * Se il codice e il cablaggio sono corretti, ma l'LCD non mostra contenuti, puoi regolare il potenziometro sul retro per aumentare il contrasto.

**Codice**


.. note::
    Puoi **Modificare/Resettare/Copiare/Eseguire/Fermare** il codice qui sotto. Ma prima di farlo, devi accedere al percorso del codice sorgente come ``raphael-kit/python``. Dopo aver modificato il codice, puoi eseguirlo direttamente per vedere l'effetto.

.. 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__':     # Programma avviato da qui
        try:
            setup()
            while True:
                loop()
        except KeyboardInterrupt:   # Quando si preme 'Ctrl+C', viene eseguito destroy().
            destroy()

**Spiegazione del Codice**

.. 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

Questa funzione legge i valori di X e Y. Se **X>200**, restituisce **1**; 
se **X<50**, restituisce **-1**; se **Y>200**, restituisce **-10**; e se 
**Y<50**, restituisce **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)

Questa funzione serve a regolare la soglia e a visualizzarla su 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)

Questa funzione legge il valore analogico del **CH0** (termistore) di 
**ADC0834** e lo converte in valore di temperatura.

.. 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)

Quando il codice viene eseguito, la temperatura corrente e la soglia di 
alta temperatura **40** sono visualizzate su **I2C LCD1602**. Se la temperatura 
corrente supera la soglia, il buzzer e il LED si attivano per avvisarti.

.. 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()

La funzione ``main()`` contiene l'intero processo del programma come mostrato:

1) All'avvio del programma, il valore iniziale di **stage** è **0**, e la 
temperatura corrente e la soglia di alta temperatura **40** sono visualizzate 
su **I2C LCD1602**. Se la temperatura corrente è superiore alla soglia, il buzzer 
e il LED si attivano per avvisarti.

2) Premi il joystick, e **stage** diventa **1** permettendoti di regolare la soglia 
di alta temperatura. Muovendo il joystick lungo l'asse X e Y puoi regolare 
(aumentare o diminuire) la soglia di alta temperatura corrente. Premi nuovamente il 
joystick per ripristinare la soglia al valore iniziale.

Phenomenon Picture
-------------------------

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