.. note::

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

    **Perché unirti?**

    - **Supporto esperto**: Risolvi i problemi post-vendita e le sfide tecniche con l'aiuto della nostra community 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.
    - **Sconti speciali**: Goditi sconti esclusivi sui nostri prodotti più recenti.
    - **Promozioni festive e omaggi**: Partecipa a concorsi e promozioni festive.

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

.. _3.1.9_c_pi5:

3.1.9 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 di luce.

Componenti necessari
-------------------------------

In questo progetto, abbiamo bisogno dei seguenti componenti.

.. image:: ../img/list_Alarm_Bell.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 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 elettrico
----------------------

============ ======== ======== ===
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:: ../img/Schematic_three_one10.png
   :align: center

Procedure sperimentali
-----------------------------

**Passo 1**: Costruisci il circuito.

.. image:: ../img/image266.png

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

.. raw:: html

   <run></run>

.. code-block:: 

    cd ~/raphael-kit/c/3.1.9/

**Passo 3**: Compila.

.. raw:: html

   <run></run>

.. code-block::

    gcc 3.1.9_AlarmBell.c -lwiringPi -lpthread

**Passo 4**: Esegui.

.. raw:: html

   <run></run>

.. code-block::

    sudo ./a.out

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

.. note::

    Se il programma non funziona dopo l'esecuzione o compare il messaggio di errore: "wiringPi.h: No such file or directory", consulta :ref:`install_wiringpi`.


Spiegazione del codice
-------------------------

.. code-block:: c

    #include <pthread.h>

In questo codice, utilizzerai una nuova libreria, ``pthread.h``, che è un insieme di librerie di thread comuni e può realizzare il multithreading. Aggiungiamo il parametro ``-lpthread`` al momento della compilazione per consentire il funzionamento indipendente del LED e del cicalino.

.. code-block:: c

    void *ledWork(void *arg){       
        while(1)    
        {   
            if(flag==0){
                pthread_exit(NULL);
            }
            digitalWrite(ALedPin,HIGH);
            delay(500);
            digitalWrite(ALedPin,LOW);
            digitalWrite(BLedPin,HIGH);
            delay(500);
            digitalWrite(BLedPin,LOW);
        }
    }

La funzione ``ledWork()`` aiuta a impostare lo stato di funzionamento di 
questi 2 LED: mantiene il LED verde acceso per 0,5 secondi, quindi lo 
spegne; allo stesso modo, mantiene il LED rosso acceso per 0,5 secondi, 
quindi lo spegne.

.. code-block:: c

    void *buzzWork(void *arg){
        while(1)
        {
            if(flag==0){
                pthread_exit(NULL);
            }
            if((note>=800)||(note<=130)){
                pitch = -pitch;
            }
            note=note+pitch;
            softToneWrite(BeepPin,note);
            delay(10);
        }
    }

La funzione ``buzzWork()`` viene utilizzata per impostare lo stato di funzionamento 
del cicalino. Qui impostiamo la frequenza tra 130 e 800, per accumulare o decrescere 
a intervalli di 20.

.. code-block:: c

    void on(){
        flag = 1;
        if(softToneCreate(BeepPin) == -1){
            printf("setup softTone failed !");
            return; 
        }    
        pthread_t tLed;     
        pthread_create(&tLed,NULL,ledWork,NULL);    
        pthread_t tBuzz;  
        pthread_create(&tBuzz,NULL,buzzWork,NULL);      
    }

Nella funzione on():

1) Definisci il flag ``flag=1``, che indica la terminazione del thread di controllo.

2) Crea un pin per il tono controllato dal software ``BeepPin``.

3) Crea due thread separati in modo che il LED e il cicalino possano funzionare contemporaneamente.

* ``pthread_t tLed``: Dichiara un thread ``tLed``.
* ``pthread_create(&tLed,NULL,ledWork,NULL)``: Crea il thread e il suo prototipo è il seguente:

.. code-block:: 

    int pthread_create(pthread_t *restrict tidp,const pthread_attr_t*restrict_attr,void*（*start_rtn)(void*),void *restrict arg);

Se ha successo, restituisce 0; altrimenti restituisce il numero di errore -1.

* Il primo parametro è un puntatore all'identificatore del thread.
* Il secondo parametro serve per impostare l'attributo del thread.
* Il terzo parametro è l'indirizzo di partenza della funzione di esecuzione del thread.
* L'ultimo parametro è quello che esegue la funzione.

.. code-block:: c

    void off(){
        flag = 0;
        softToneStop(BeepPin);
        digitalWrite(ALedPin,LOW);
        digitalWrite(BLedPin,LOW);
    }


La funzione ``off()`` definisce ``flag=0`` per uscire dai thread 
**ledWork** e **buzzWork** e poi spegnere il cicalino e i LED.

.. code-block:: c

    int main(){       
        setup(); 
        int lastState = 0;
        while(1){
            int currentState = digitalRead(switchPin);
            if ((currentState == 1)&&(lastState==0)){
                on();
            }
            else if((currentState == 0)&&(lastState==1)){
                off();
            }
            lastState=currentState;
        }
        return 0;
    }

Main() contiene l'intero processo del programma: innanzitutto legge il valore 
dell'interruttore a levetta; se l'interruttore viene spostato verso destra 
(lettura 1), viene chiamata la funzione ``on()``, il cicalino viene attivato 
per emettere suoni e i LED rosso e verde lampeggiano. In caso contrario, il 
cicalino e i LED non funzionano.

Immagine del fenomeno
--------------------------

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