.. note::

    Ciao, benvenuto nella Community su Facebook per gli appassionati di SunFounder Raspberry Pi, Arduino ed ESP32! Esplora più a fondo Raspberry Pi, Arduino ed ESP32 insieme ad altri appassionati.

    **Perché unirsi?**

    - **Supporto Esperto**: Risolvi problemi post-vendita e 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 dei nuovi prodotti e anticipazioni.
    - **Sconti Speciali**: Approfitta di sconti esclusivi sui nostri prodotti più recenti.
    - **Promozioni Festive e Giveaway**: Partecipa a giveaway e promozioni festive.

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

.. _py_pi5_welcome:

3.1.2 Benvenuto
=====================================

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

In questo progetto, utilizzeremo un sensore PIR per rilevare il movimento 
dei passanti, e useremo un servo, un LED e un buzzer per simulare il 
funzionamento della porta automatica di un negozio. Quando un passante entra 
nel raggio di rilevamento del PIR, la luce di indicazione si accenderà, la 
porta si aprirà e il buzzer riprodurrà il suono del campanello d’apertura.

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

In questo progetto, ci servono i seguenti componenti.

.. image:: ../python_pi5/img/4.1.8_welcome_list.png
    :width: 800
    :align: center

.. È certamente 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 singolarmente dai link qui sotto.

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

..     *   - INTRODUZIONE COMPONENTE
..         - LINK DI ACQUISTO

..     *   - :ref:`scheda_estensione_gpio`
..         - |link_gpio_board_buy|
..     *   - :ref:`breadboard`
..         - |link_breadboard_buy|
..     *   - :ref:`fili`
..         - |link_wires_buy|
..     *   - :ref:`resistenza`
..         - |link_resistor_buy|
..     *   - :ref:`led`
..         - |link_led_buy|
..     *   - :ref:`pir`
..         - \-
..     *   - :ref:`servo`
..         - |link_servo_buy|
..     *   - :ref:`Buzzer`
..         - |link_passive_buzzer_buy|
..     *   - :ref:`transistor`
..         - |link_transistor_buy|

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

============ ======== ======== ===
T-Board Name physical wiringPi BCM
GPIO18       Pin 12   1        18
GPIO17       Pin 11   0        17
GPIO27       Pin 13   2        27
GPIO22       Pin 15   3        22
============ ======== ======== ===

.. image:: ../python_pi5/img/4.1.8_welcome_schematic.png
   :align: center

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

**Passo 1:** Monta il circuito.

.. image:: ../python_pi5/img/4.1.8_welcome_circuit.png
    :align: center

**Passo 2:** Cambia directory.

.. raw:: html

   <run></run>

.. code-block::

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

**Passo 3:** Esegui il file.

.. raw:: html

   <run></run>

.. code-block::

    sudo python3 3.1.2_Welcome.py

Dopo aver eseguito il codice, se il sensore PIR rileva una persona in 
avvicinamento, la porta si aprirà automaticamente (simulata dal servo), 
accenderà l’indicatore luminoso e suonerà il campanello d’ingresso. 
Al termine del suono del campanello, il sistema chiuderà automaticamente 
la porta e spegnerà la luce indicatrice, attendendo il passaggio successivo.

Sul modulo PIR ci sono due potenziometri: uno per regolare la sensibilità e 
l'altro per regolare la distanza di rilevamento. Per far funzionare meglio il 
modulo PIR, è consigliabile ruotarli entrambi in senso antiorario fino alla fine.

.. image:: ../python_pi5/img/4.1.8_PIR_TTE.png
    :width: 400
    :align: center

.. warning::

    Se compare un errore con il messaggio ``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. Prima di procedere, assicurati di essere nel percorso sorgente, ad esempio ``davinci-kit-for-raspberry-pi/python-pi5``. Dopo aver modificato il codice, puoi eseguirlo direttamente per vedere l’effetto.

.. raw:: html

    <run></run>

.. code-block:: python

   #!/usr/bin/env python3

   from gpiozero import LED, MotionSensor, Servo, TonalBuzzer
   import time

   # Configurazione dei pin GPIO per LED, sensore di movimento (PIR) e buzzer
   ledPin = LED(6)
   pirPin = MotionSensor(21)
   buzPin = TonalBuzzer(27)

   # Fattore di correzione per larghezza impulso del servo e calcolo
   myCorrection = 0.45
   maxPW = (2.0 + myCorrection) / 1000  # Larghezza massima impulso
   minPW = (1.0 - myCorrection) / 1000  # Larghezza minima impulso

   # Inizializza servo con larghezze impulso personalizzate
   servoPin = Servo(25, min_pulse_width=minPW, max_pulse_width=maxPW)

   # Melodia per il buzzer, con note e durate
   tune = [('C#4', 0.2), ('D4', 0.2), (None, 0.2),
           ('Eb4', 0.2), ('E4', 0.2), (None, 0.6),
           ('F#4', 0.2), ('G4', 0.2), (None, 0.6),
           ('Eb4', 0.2), ('E4', 0.2), (None, 0.2),
           ('F#4', 0.2), ('G4', 0.2), (None, 0.2),
           ('C4', 0.2), ('B4', 0.2), (None, 0.2),
           ('F#4', 0.2), ('G4', 0.2), (None, 0.2),
           ('B4', 0.2), ('Bb4', 0.5), (None, 0.6),
           ('A4', 0.2), ('G4', 0.2), ('E4', 0.2), 
           ('D4', 0.2), ('E4', 0.2)]

   def setAngle(angle):
       """
       Move the servo to a specified angle.
       :param angle: Angle in degrees (0-180).
       """
       value = float(angle / 180)  # Converte l'angolo in valore per il servo
       servoPin.value = value      # Imposta la posizione del servo
       time.sleep(0.001)           # Breve pausa per il movimento del servo

   def doorbell():
       """
       Play a musical tune using the buzzer.
       """
       for note, duration in tune:
           buzPin.play(note)       # Riproduce la nota
           time.sleep(float(duration))  # Durata della nota
       buzPin.stop()               # Ferma il buzzer dopo la melodia

   def closedoor():
       # Spegne il LED e muove il servo per chiudere la porta
       ledPin.off()
       for i in range(180, -1, -1):
           setAngle(i)             # Muove il servo da 180 a 0 gradi
           time.sleep(0.001)       # Breve pausa per movimento fluido
       time.sleep(1)               # Attesa dopo la chiusura della porta

   def opendoor():
       # Accende il LED, apre la porta (muove il servo), riproduce la melodia e chiude la porta
       ledPin.on()
       for i in range(0, 181):
           setAngle(i)             # Muove il servo da 0 a 180 gradi
           time.sleep(0.001)       # Breve pausa per movimento fluido
       time.sleep(1)               # Attesa prima di riprodurre la melodia
       doorbell()                  # Riproduce la melodia del campanello
       closedoor()                 # Chiude la porta dopo la melodia

   def loop():
       # Loop principale per controllare il movimento e operare la porta
       while True:
           if pirPin.motion_detected:
               opendoor()               # Apre la porta se viene rilevato movimento
           time.sleep(0.1)              # Breve pausa nel loop

   try:
       loop()
   except KeyboardInterrupt:
       # Pulisce i GPIO in caso di interruzione (es. Ctrl+C)
       buzPin.stop()
       ledPin.off()


**Spiegazione del Codice**

#. Lo script inizia importando i moduli necessari. La libreria ``gpiozero`` è utilizzata per interfacciarsi con il LED, il sensore di movimento, il motore servo e il buzzer tonale. Il modulo ``time`` è impiegato per gestire le funzioni legate al timing.

   .. code-block:: python

       #!/usr/bin/env python3
       from gpiozero import LED, MotionSensor, Servo, TonalBuzzer
       import time

#. Inizializza il LED, il sensore di movimento PIR e il buzzer tonale sui rispettivi pin GPIO.

   .. code-block:: python

       # Configurazione dei pin GPIO per LED, sensore di movimento (PIR) e buzzer
       ledPin = LED(6)
       pirPin = MotionSensor(21)
       buzPin = TonalBuzzer(27)

#. Calcola la larghezza degli impulsi massima e minima per il motore servo, incorporando un fattore di correzione per una regolazione più precisa.

   .. code-block:: python

       # Fattore di correzione per la larghezza degli impulsi del servo
       myCorrection = 0.45
       maxPW = (2.0 + myCorrection) / 1000  # Larghezza massima dell'impulso
       minPW = (1.0 - myCorrection) / 1000  # Larghezza minima dell'impulso

#. Inizializza il motore servo sul pin GPIO 25 con le larghezze di impulso personalizzate per un posizionamento accurato.

   .. code-block:: python

       # Inizializzazione del servo con larghezze di impulso personalizzate
       servoPin = Servo(25, min_pulse_width=minPW, max_pulse_width=maxPW)

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

   .. code-block:: python

       # Melodia per il buzzer, con note e durate
       tune = [('C#4', 0.2), ('D4', 0.2), (None, 0.2),
               ('Eb4', 0.2), ('E4', 0.2), (None, 0.6),
               ('F#4', 0.2), ('G4', 0.2), (None, 0.6),
               ('Eb4', 0.2), ('E4', 0.2), (None, 0.2),
               ('F#4', 0.2), ('G4', 0.2), (None, 0.2),
               ('C4', 0.2), ('B4', 0.2), (None, 0.2),
               ('F#4', 0.2), ('G4', 0.2), (None, 0.2),
               ('B4', 0.2), ('Bb4', 0.5), (None, 0.6),
               ('A4', 0.2), ('G4', 0.2), ('E4', 0.2), 
               ('D4', 0.2), ('E4', 0.2)]

#. Funzione per muovere il servo a un angolo specificato. Converte l'angolo in un valore tra 0 e 1 per il servo.

   .. code-block:: python

       def setAngle(angle):
           """
           Move the servo to a specified angle.
           :param angle: Angle in degrees (0-180).
           """
           value = float(angle / 180)  # Converte l'angolo in valore per il servo
           servoPin.value = value      # Imposta la posizione del servo
           time.sleep(0.001)           # Breve pausa per il movimento del servo

#. Funzione per riprodurre una melodia usando il buzzer. Scorre la lista ``tune`` riproducendo ciascuna nota per la durata specificata.

   .. code-block:: python

       def doorbell():
           """
           Play a musical tune using the buzzer.
           """
           for note, duration in tune:
               buzPin.play(note)       # Riproduce la nota
               time.sleep(float(duration))  # Durata della nota
           buzPin.stop()               # Ferma il buzzer dopo la melodia

#. Funzioni per aprire e chiudere la porta usando il motore servo. La funzione ``opendoor`` accende il LED, apre la porta, riproduce la melodia e poi chiude la porta.

   .. code-block:: python

       def closedoor():
           # Spegne il LED e muove il servo per chiudere la porta
           ledPin.off()
           for i in range(180, -1, -1):
               setAngle(i)             # Muove il servo da 180 a 0 gradi
               time.sleep(0.001)       # Breve pausa per movimento fluido
           time.sleep(1)               # Attesa dopo la chiusura della porta

       def opendoor():
           # Accende il LED, apre la porta (muove il servo), riproduce la melodia, chiude la porta
           ledPin.on()
           for i in range(0, 181):
               setAngle(i)             # Muove il servo da 0 a 180 gradi
               time.sleep(0.001)       # Breve pausa per movimento fluido
           time.sleep(1)               # Attesa prima della melodia
           doorbell()                  # Riproduce la melodia del campanello
           closedoor()                 # Chiude la porta dopo la melodia

#. Loop principale che controlla costantemente il rilevamento di movimento. Quando viene rilevato movimento, attiva la funzione ``opendoor``.

   .. code-block:: python

       def loop():
           # Loop principale per verificare movimento e operare la porta
           while True:
               if pirPin.motion_detected:
                   opendoor()               # Apre la porta se rileva movimento
               time.sleep(0.1)              # Breve pausa nel loop

#. Esegue il loop principale e garantisce che lo script possa essere interrotto con un comando di tastiera (Ctrl+C), spegnendo il buzzer e il LED per un’uscita pulita.

   .. code-block:: python

       try:
           loop()
       except KeyboardInterrupt:
           # Pulisce i GPIO in caso di interruzione (es. Ctrl+C)
           buzPin.stop()
           ledPin.off()

