.. note::

    Ciao e benvenuto nella Community degli appassionati di SunFounder per Raspberry Pi, Arduino e ESP32 su Facebook! Esplora a fondo Raspberry Pi, Arduino e ESP32 con altri appassionati.

    **Perché unirsi?**

    - **Supporto Esperto**: Risolvi problemi post-vendita e sfide tecniche con l’aiuto della nostra comunità e del nostro team.
    - **Impara & Condividi**: Scambia consigli e tutorial per migliorare le tue competenze.
    - **Anteprime Esclusive**: Ottieni l'accesso anticipato agli annunci di nuovi prodotti e alle anteprime.
    - **Sconti Speciali**: Godi di sconti esclusivi sui nostri prodotti più recenti.
    - **Promozioni Festive e Giveaway**: Partecipa ai giveaway e alle promozioni per le festività.

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

.. _py_pi5_bell:

3.1.10 Campanello di 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, sono necessari i 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 qui sotto.

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

..     *   - INTRODUZIONE COMPONENTE
..         - LINK PER ACQUISTO

..     *   - :ref:`gpio_extension_board`
..         - |link_gpio_board_buy|
..     *   - :ref:`breadboard`
..         - |link_breadboard_buy|
..     *   - :ref:`wires`
..         - |link_wires_buy|
..     *   - :ref:`resistor`
..         - |link_resistor_buy|
..     *   - :ref:`led`
..         - |link_led_buy|
..     *   - :ref:`Buzzer`
..         - |link_passive_buzzer_buy|
..     *   - :ref:`slide_switch`
..         - |link_slide_switch_buy|
..     *   - :ref:`transistor`
..         - |link_transistor_buy|
..     *   - :ref:`capacitor`
..         - |link_capacitor_buy|

Schema di Collegamento
-------------------------

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

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

**Passo 1**: Costruisci il circuito.

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

**Passo 2:** Cambia directory.

.. raw:: html

   <run></run>

.. code-block::

    cd ~/davinci-kit-for-raspberry-pi/python-pi5

**Passo 3:** Esegui il programma.

.. raw:: html

   <run></run>

.. code-block::

    sudo python3 3.1.10_AlarmBell.py

Dopo l’avvio del programma, l’interruttore a levetta verrà spostato a 
destra, e il cicalino emetterà un suono di allarme. Contemporaneamente, 
i LED rosso e verde lampeggeranno a una certa frequenza.

.. warning::

    Se compare il messaggio di errore ``RuntimeError: Cannot determine SOC peripheral base address``, fai riferimento a :ref:`faq_soc`

**Codice**

.. note::
    Puoi **Modificare/Reimpostare/Copiare/Eseguire/Interrompere** il codice qui sotto. Tuttavia, prima di eseguire queste azioni, devi accedere al percorso sorgente del codice, ad esempio ``davinci-kit-for-raspberry-pi/python-pi5``.

.. raw:: html

    <run></run>

.. code-block:: python

    #!/usr/bin/env python3

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

    # Inizializzazione del TonalBuzzer sul pin GPIO 22
    BeepPin = TonalBuzzer(22)

    # Inizializzazione dei LED sui pin GPIO 17 e 27
    ALedPin = LED(17)
    BLedPin = LED(27)

    # Inizializzazione del pulsante sul pin GPIO 18
    switchPin = Button(18)

    # Flag globale per controllare lo stato del buzzer 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 è attivo
                ALedPin.off()
                BLedPin.off()

    # Definisce una melodia come una lista di note e delle rispettive 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)  # Visualizza la nota corrente nella console
                BeepPin.play(note)  # Riproduce la nota corrente
                time.sleep(duration)  # Pausa per la durata della nota
            BeepPin.stop()  # Ferma il buzzer dopo aver riprodotto 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 if switchPin.is_pressed else 0

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

    except KeyboardInterrupt:
        # Ferma il buzzer e spegne i LED in caso di interruzione del programma
        BeepPin.stop()
        ALedPin.off()    
        BLedPin.off()


**Spiegazione del Codice**

#. Questa sezione include l'importazione delle librerie essenziali per implementare ritardi e threading. Vengono anche importate le classi LED, Button e TonalBuzzer dalla libreria gpiozero, indispensabili per controllare i 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 buzzer sul pin GPIO 22, due LED sui pin GPIO 17 e 27 e inizializza un pulsante sul pin GPIO 18. Inoltre, viene definito un flag globale per gestire lo stato del buzzer e dei LED.

   .. code-block:: python

       # Inizializza il 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 buzzer e dei LED
       flag = 0

#. Questa funzione controlla il lampeggio dei LED in base allo stato del flag. Se il flag è impostato (1), i LED si alternano accendendosi e spegnendosi. Se non impostato (0), entrambi i LED sono 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 (frequenza) e durate (secondi).

   .. code-block:: python

       # Definisce la melodia come una lista di note e delle rispettive 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)  # Mostra la nota corrente nella console
                   BeepPin.play(note)  # Riproduce la nota corrente
                   time.sleep(duration)  # Pausa per la durata della nota
               BeepPin.stop()  # Ferma il buzzer dopo aver riprodotto 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 if switchPin.is_pressed else 0

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

   .. code-block:: python

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

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

   .. code-block:: python

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