.. note::

    Ciao, benvenuto nella comunità di appassionati di SunFounder Raspberry Pi & Arduino & ESP32 su Facebook! Approfondisci Raspberry Pi, Arduino ed ESP32 insieme ad altri appassionati.

    **Perché unirsi a noi?**

    - **Supporto esperto**: Risolvi i problemi post-vendita e le sfide tecniche con l'aiuto della nostra comunità e del nostro team.
    - **Impara e condividi**: Scambia suggerimenti e tutorial per migliorare le tue competenze.
    - **Anteprime esclusive**: Ottieni accesso anticipato agli annunci di nuovi prodotti e alle anteprime esclusive.
    - **Sconti speciali**: Approfitta di sconti esclusivi sui nostri prodotti più recenti.
    - **Promozioni festive e concorsi**: Partecipa ai concorsi e alle promozioni festive.

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

.. _4.1.15_py_pi5:

4.1.12 Campanello d'Allarme
================================

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

In questo progetto realizzeremo un dispositivo di allarme manuale. 
Puoi sostituire l'interruttore a levetta con un termistore o un sensore 
fotosensibile per creare un allarme di temperatura o un allarme luminoso.

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

Per questo progetto, abbiamo bisogno dei seguenti componenti.

.. image:: ../python_pi5/img/4.1.15_alarm_bell_list.png
    :width: 800
    :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

    *   - DESCRIZIONE COMPONENTE
        - 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_buzzer`
        - |link_passive_buzzer_buy|
    *   - :ref:`cpn_slide_switch`
        - |link_slide_switch_buy|
    *   - :ref:`cpn_transistor`
        - |link_transistor_buy|
    *   - :ref:`cpn_capacitor`
        - |link_capacitor_buy|

Schema Circuitale
---------------------

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

.. image:: ../python_pi5/img/4.1.15_alarm_bell_schematic.png
    :width: 600
    :align: center

Procedura Sperimentale
--------------------------

**Fase 1**: Costruisci il circuito.

.. image:: ../python_pi5/img/4.1.15_alarm_bell_circuit.png

**Fase 2:** Cambia la directory.

.. raw:: html

   <run></run>

.. code-block::

    cd ~/raphael-kit/python-pi5

**Fase 3:** Esegui.

.. raw:: html

   <run></run>

.. code-block::

    sudo python3 4.1.15_AlarmBell_zero.py

Dopo l'avvio del programma, l'interruttore a levetta verrà spostato a 
destra e il cicalino emetterà suoni di allarme. Allo stesso tempo, i LED 
rosso e verde lampeggeranno a una certa frequenza.

.. warning::

    Se viene visualizzato l'errore ``RuntimeError: Cannot determine SOC peripheral base address``, fare riferimento a :ref:`faq_soc`. 

**Code**

.. note::
    Puoi **Modificare/Reimpostare/Copiare/Eseguire/Interrompere** il codice qui sotto. Tuttavia, prima devi andare nel percorso del codice sorgente come ``raphael-kit/python-pi5``.

.. raw:: html

    <run></run>

.. code-block:: python

    #!/usr/bin/env python3

    from gpiozero import LED, Button, TonalBuzzer
    import time
    import threading

    # Inizializza TonalBuzzer su GPIO pin 22
    BeepPin = TonalBuzzer(22)

    # Inizializza i LED su GPIO pin 17 e 27
    ALedPin = LED(17)
    BLedPin = LED(27)

    # Inizializza il pulsante su GPIO pin 18
    switchPin = Button(18)

    # Flag globale per controllare lo stato del cicalino e dei LED
    flag = 0

    def ledWork():
        """
        Control LED blinking pattern based on the flag state.
        When flag is set, alternately blink ALedPin and BLedPin.
        """
        while True:
            if flag:
                # Lampeggio alternato dei LED
                ALedPin.on()
                time.sleep(0.5)
                ALedPin.off()
                BLedPin.on()
                time.sleep(0.5)
                BLedPin.off()
            else:
                # Spegne entrambi i LED se il flag non è impostato
                ALedPin.off()
                BLedPin.off()

    # Definisce la melodia musicale come un elenco di note e le loro durate
    tune = [
        ('C4', 0.1), ('E4', 0.1), ('G4', 0.1), 
        (None, 0.1), 
        ('E4', 0.1), ('G4', 0.1), ('C5', 0.1), 
        (None, 0.1), 
        ('C5', 0.1), ('G4', 0.1), ('E4', 0.1), 
        (None, 0.1), 
        ('G4', 0.1), ('E4', 0.1), ('C4', 0.1), 
        (None, 0.1)
    ]

    def buzzerWork():
        """
        Play a tune using the buzzer based on the flag state.
        The tune is played only when the flag is set.
        """
        while True:
            for note, duration in tune:
                if flag == 0:
                    break
                print(note)  # Output della nota corrente nella console
                BeepPin.play(note)  # Suona la nota corrente
                time.sleep(duration)  # Pausa per la durata della nota
            BeepPin.stop()  # Interrompe il cicalino dopo aver suonato la melodia

    def main():
        """
        Monitor button press to update the flag state.
        Sets the flag when the button is pressed.
        """
        global flag
        while True:
            flag = 1 se switchPin.is_pressed else 0

    try:
        # Inizializza e avvia i thread per il controllo del cicalino e dei LED
        tBuzz = threading.Thread(target=buzzerWork)
        tBuzz.start()
        tLed = threading.Thread(target=ledWork)
        tLed.start()
        main()

    except KeyboardInterrupt:
        # Interrompe il cicalino e spegne i LED all'interruzione del programma
        BeepPin.stop()
        ALedPin.off()    
        BLedPin.off()

        
**Spiegazione del Codice**

#. Questo segmento include l'importazione delle librerie essenziali per implementare ritardi e threading. Importa inoltre le classi LED, Button e TonalBuzzer dalla libreria gpiozero, cruciali per il controllo dei dispositivi GPIO su un Raspberry Pi.

   .. code-block:: python

       #!/usr/bin/env python3

       from gpiozero import LED, Button, TonalBuzzer
       import time
       import threading

#. Configura un cicalino sul pin GPIO 22, due LED sui pin GPIO 17 e 27 e inizializza un pulsante sul pin GPIO 18. Viene anche definita una variabile globale "flag" per gestire lo stato del cicalino e dei LED.

   .. code-block:: python

       # Inizializza TonalBuzzer sul pin GPIO 22
       BeepPin = TonalBuzzer(22)

       # Inizializza i LED sui pin GPIO 17 e 27
       ALedPin = LED(17)
       BLedPin = LED(27)

       # Inizializza il pulsante sul pin GPIO 18
       switchPin = Button(18)

       # Flag globale per controllare lo stato del cicalino e dei LED
       flag = 0

#. Questa funzione controlla il lampeggiamento dei LED in base allo stato del flag. Se il flag è impostato (1), alterna tra l'accensione e lo spegnimento di ciascun LED. Se non è impostato (0), entrambi i LED vengono spenti.

   .. code-block:: python

       def ledWork():
           """
           Control LED blinking pattern based on the flag state.
           When flag is set, alternately blink ALedPin and BLedPin.
           """
           while True:
               if flag:
                   # Lampeggio alternato dei LED
                   ALedPin.on()
                   time.sleep(0.5)
                   ALedPin.off()
                   BLedPin.on()
                   time.sleep(0.5)
                   BLedPin.off()
               else:
                   # Spegne entrambi i LED se il flag non è impostato
                   ALedPin.off()
                   BLedPin.off()

#. La melodia è definita come una sequenza di note (frequenze) e durate (secondi).

   .. code-block:: python

       # Definisci la melodia musicale come un elenco di note e le loro durate
       tune = [
           ('C4', 0.1), ('E4', 0.1), ('G4', 0.1), 
           (None, 0.1), 
           ('E4', 0.1), ('G4', 0.1), ('C5', 0.1), 
           (None, 0.1), 
           ('C5', 0.1), ('G4', 0.1), ('E4', 0.1), 
           (None, 0.1), 
           ('G4', 0.1), ('E4', 0.1), ('C4', 0.1), 
           (None, 0.1)
       ]

#. Riproduce una melodia predefinita quando il flag è impostato. La melodia si interrompe se il flag viene disattivato durante la riproduzione.

   .. code-block:: python

       def buzzerWork():
           """
           Play a tune using the buzzer based on the flag state.
           The tune is played only when the flag is set.
           """
           while True:
               for note, duration in tune:
                   if flag == 0:
                       break
                   print(note)  # Stampa la nota corrente nella console
                   BeepPin.play(note)  # Suona la nota corrente
                   time.sleep(duration)  # Pausa per la durata della nota
               BeepPin.stop()  # Interrompe il cicalino dopo aver suonato la melodia

#. Controlla continuamente lo stato del pulsante per impostare o disattivare il flag.

   .. code-block:: python

       def main():
           """
           Monitor button press to update the flag state.
           Sets the flag when the button is pressed.
           """
           global flag
           while True:
               flag = 1 se switchPin.is_pressed else 0

#. I thread per ``buzzerWork`` e ``ledWork`` vengono avviati, consentendo loro di funzionare contemporaneamente alla funzione principale.

   .. code-block:: python

       try:
           # Inizializza e avvia i thread per il controllo del cicalino e dei LED
           tBuzz = threading.Thread(target=buzzerWork)
           tBuzz.start()
           tLed = threading.Thread(target=ledWork)
           tLed.start()
           main()

#. Interrompe il cicalino e spegne i LED quando il programma viene interrotto, garantendo un'uscita pulita.

   .. code-block:: python

       except KeyboardInterrupt:
           # Ferma il cicalino e spegne i LED all'interruzione del programma
           BeepPin.stop()
           ALedPin.off()    
           BLedPin.off()
