.. note::

    ¡Hola! Bienvenido a la comunidad de entusiastas de SunFounder Raspberry Pi & Arduino & ESP32 en Facebook. Sumérgete más en Raspberry Pi, Arduino y ESP32 con otros entusiastas.

    **¿Por qué unirse?**

    - **Soporte Experto**: Resuelve problemas postventa y desafíos técnicos con la ayuda de nuestra comunidad y equipo.
    - **Aprende y Comparte**: Intercambia consejos y tutoriales para mejorar tus habilidades.
    - **Preestrenos Exclusivos**: Obtén acceso anticipado a anuncios de nuevos productos y avances exclusivos.
    - **Descuentos Especiales**: Disfruta de descuentos exclusivos en nuestros productos más recientes.
    - **Promociones y Sorteos Festivos**: Participa en sorteos y promociones de temporada.

    👉 ¿Listo para explorar y crear con nosotros? Haz clic en [|link_sf_facebook|] y únete hoy mismo!

.. _4.1.15_py_pi5:

4.1.12 Alarma
=======================

Introducción
-------------------

En este proyecto, haremos un dispositivo de alarma manual. Puedes reemplazar 
el interruptor de palanca con un termistor o un sensor fotosensible para hacer 
una alarma de temperatura o de luz.

Componentes Necesarios
------------------------------

En este proyecto, necesitamos los siguientes componentes.

.. image:: ../python_pi5/img/4.1.15_alarm_bell_list.png
    :width: 800
    :align: center

Es definitivamente conveniente comprar un kit completo, aquí está el enlace: 

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

    *   - Nombre	
        - ARTÍCULOS EN ESTE KIT
        - ENLACE
    *   - Kit Raphael
        - 337
        - |link_Raphael_kit|

También puedes comprarlos por separado en los enlaces a continuación.

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

    *   - INTRODUCCIÓN DEL COMPONENTE
        - ENLACE DE COMPRA

    *   - :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|

Diagrama Esquemático
-------------------------

============== ====== ======== ===
Nombre T-Board física 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

Procedimientos Experimentales
-------------------------------------

**Paso 1**: Construye el circuito.

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

**Paso 2:** Cambia de directorio.

.. raw:: html

   <run></run>

.. code-block::

    cd ~/raphael-kit/python-pi5

**Paso 3:** Ejecuta.

.. raw:: html

   <run></run>

.. code-block::

    sudo python3 4.1.15_AlarmBell_zero.py

Después de que el programa se inicie, el interruptor de palanca se moverá hacia la 
derecha y el zumbador emitirá sonidos de alarma. Al mismo tiempo, los LED rojo y verde 
parpadearán a una cierta frecuencia.

.. warning::

    Si recibe el mensaje de error ``RuntimeError: Cannot determine SOC peripheral base address``, consulte :ref:`faq_soc`

**Código**

.. note::
    Puedes **Modificar/Restablecer/Copiar/Ejecutar/Detener** el código a continuación. Pero antes de eso, necesitas ir a la ruta del código fuente como ``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

    # Inicializar TonalBuzzer en el pin GPIO 22
    BeepPin = TonalBuzzer(22)

    # Inicializar LEDs en los pines GPIO 17 y 27
    ALedPin = LED(17)
    BLedPin = LED(27)

    # Inicializar Botón en el pin GPIO 18
    switchPin = Button(18)

    # Bandera global para controlar los estados del zumbador y los LEDs
    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:
                # Parpadeo alternado de los LEDs
                ALedPin.on()
                time.sleep(0.5)
                ALedPin.off()
                BLedPin.on()
                time.sleep(0.5)
                BLedPin.off()
            else:
                # Apaga ambos LEDs si la bandera no está activada
                ALedPin.off()
                BLedPin.off()

    # Definir la melodía musical como una lista de notas y sus duraciones
    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)  # Muestra la nota actual en la consola
                BeepPin.play(note)  # Reproduce la nota actual
                time.sleep(duration)  # Pausa por la duración de la nota
            BeepPin.stop()  # Detiene el zumbador después de reproducir la melodía

    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:
        # Inicializa y arranca los hilos para el control del zumbador y los LEDs
        tBuzz = threading.Thread(target=buzzerWork)
        tBuzz.start()
        tLed = threading.Thread(target=ledWork)
        tLed.start()
        main()

    except KeyboardInterrupt:
        # Detiene el zumbador y apaga los LEDs al interrumpir el programa
        BeepPin.stop()
        ALedPin.off()    
        BLedPin.off()


**Explicación del Código**

#. Este segmento incluye la importación de bibliotecas esenciales para implementar retrasos y subprocesos. También importa las clases LED, Button y TonalBuzzer de la biblioteca gpiozero, cruciales para controlar dispositivos GPIO en una Raspberry Pi.

   .. code-block:: python

       #!/usr/bin/env python3

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

#. Configura un zumbador en el pin GPIO 22, dos LEDs en los pines GPIO 17 y 27, y un botón en el pin GPIO 18. También se define una bandera global para gestionar el estado del zumbador y los LEDs.

   .. code-block:: python

       # Inicializar TonalBuzzer en el pin GPIO 22
       BeepPin = TonalBuzzer(22)

       # Inicializar LEDs en los pines GPIO 17 y 27
       ALedPin = LED(17)
       BLedPin = LED(27)

       # Inicializar Botón en el pin GPIO 18
       switchPin = Button(18)

       # Bandera global para controlar los estados del zumbador y los LEDs
       flag = 0

#. Esta función controla el parpadeo de los LEDs según el estado de la bandera. Si la bandera está activada (1), alterna entre encender y apagar cada LED. Si no está activada (0), ambos LEDs se apagan.

   .. 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:
                   # Parpadeo alternado de los LEDs
                   ALedPin.on()
                   time.sleep(0.5)
                   ALedPin.off()
                   BLedPin.on()
                   time.sleep(0.5)
                   BLedPin.off()
               else:
                   # Apaga ambos LEDs si la bandera no está activada
                   ALedPin.off()
                   BLedPin.off()

#. La melodía se define como una secuencia de notas (frecuencia) y duraciones (segundos).

   .. code-block:: python

       # Definir la melodía musical como una lista de notas y sus duraciones
       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)
       ]

#. Reproduce una melodía predefinida cuando la bandera está activada. La melodía se detiene si la bandera se desactiva durante su reproducción.

   .. 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)  # Muestra la nota actual en la consola
                   BeepPin.play(note)  # Reproduce la nota actual
                   time.sleep(duration)  # Pausa por la duración de la nota
               BeepPin.stop()  # Detiene el zumbador después de reproducir la melodía

#. Verifica continuamente el estado del botón para activar o desactivar la bandera.

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

#. Se inician los hilos para ``buzzerWork`` y ``ledWork``, permitiendo que se ejecuten simultáneamente con la función principal.

   .. code-block:: python

       try:
           # Inicializa y arranca los hilos para el control del zumbador y los LEDs
           tBuzz = threading.Thread(target=buzzerWork)
           tBuzz.start()
           tLed = threading.Thread(target=ledWork)
           tLed.start()
           main()

#. Detiene el zumbador y apaga los LEDs cuando se interrumpe el programa, asegurando una salida limpia.

   .. code-block:: python

       except KeyboardInterrupt:
           # Detiene el zumbador y apaga los LEDs al interrumpir el programa
           BeepPin.stop()
           ALedPin.off()    
           BLedPin.off()