.. note::

    ¡Hola, bienvenido a la comunidad de entusiastas de SunFounder Raspberry Pi & Arduino & ESP32 en Facebook! Sumérgete en el mundo de Raspberry Pi, Arduino y ESP32 con otros entusiastas.

    **¿Por qué unirte?**

    - **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.10_py_pi5:

4.1.7 Ventilador Inteligente
================================

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

En este proyecto, utilizaremos motores, botones y termistores para crear un 
ventilador inteligente manual y automático cuya velocidad del viento es ajustable.

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

En este proyecto, necesitamos los siguientes componentes.

.. image:: ../python_pi5/img/4.1.10_smart_fan_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_power_module`
        - \-
    *   - :ref:`cpn_thermistor`
        - |link_thermistor_buy|
    *   - :ref:`cpn_l293d`
        - \-
    *   - :ref:`cpn_adc0834`
        - \-
    *   - :ref:`cpn_button`
        - |link_button_buy|
    *   - :ref:`cpn_motor`
        - |link_motor_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
GPIO5          Pin 29 21       5
GPIO6          Pin 31 22       6
GPIO13         Pin 33 23       13
============== ====== ======== ===

.. image:: ../python_pi5/img/4.1.10_smart_fan_schematic.png
   :align: center

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

**Paso 1:** Construye el circuito.

.. image:: ../python_pi5/img/4.1.10_smart_fan_circuit.png

.. note::
    El módulo de alimentación puede usar una batería de 9V con el conector de 
    batería de 9V incluido en el kit. Inserta el puente del módulo de alimentación 
    en las tiras de bus de 5V de la placa de pruebas.

.. image:: ../python_pi5/img/4.1.10_smart_fan_battery.jpeg
   :align: center

**Paso 2**: Accede a la carpeta del código.

.. raw:: html

   <run></run>

.. code-block:: 

    cd ~/raphael-kit/python-pi5

**Paso 3**: Ejecuta.

.. raw:: html

   <run></run>

.. code-block:: 

    sudo python3 4.1.10_SmartFan_zero.py

Cuando el código se ejecuta, inicia el ventilador presionando el botón. 
Cada vez que presionas, se ajusta una velocidad hacia arriba o hacia abajo. 
Hay **5** niveles de velocidad: **0~4**. Cuando se establece en el nivel 
4\ :sup:`to` y presionas el botón, el ventilador deja de funcionar con una 
velocidad de viento de **0**.

Una vez que la temperatura sube o baja más de 2℃, la velocidad automáticamente 
aumenta o disminuye en 1 nivel.

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``. Después de modificar el código, puedes ejecutarlo directamente para ver el efecto.

.. raw:: html

    <run></run>

.. code-block:: python

   #!/usr/bin/env python3

   from gpiozero import Motor, Button
   from time import sleep
   import ADC0834
   import math

   # Inicializar pines GPIO para el botón y control del motor
   BtnPin = Button(22)
   motor = Motor(forward=5, backward=6, enable=13)

   # Inicializar el módulo ADC0834 para la detección de temperatura
   ADC0834.setup()

   # Inicializar variables para rastrear el nivel de velocidad del motor y las temperaturas
   level = 0
   currentTemp = 0
   markTemp = 0

   def temperature():
       """
       Reads and calculates the current temperature from the sensor.
       Returns:
           float: The current temperature in Celsius.
       """
       # Leer valor analógico del módulo ADC0834
       analogVal = ADC0834.getResult()
       # Convertir valor analógico a voltaje y luego a resistencia
       Vr = 5 * float(analogVal) / 255
       Rt = 10000 * Vr / (5 - Vr)
       # Calcular temperatura en Celsius
       temp = 1 / (((math.log(Rt / 10000)) / 3950) + (1 / (273.15 + 25)))
       Cel = temp - 273.15
       return Cel

   def motor_run(level):
       """
       Adjusts the motor speed based on the specified level.
       Args:
           level (int): Desired motor speed level.
       Returns:
           int: Adjusted motor speed level.
       """
       # Detener el motor si el nivel es 0
       if level == 0:
           motor.stop()
           return 0
       # Limitar el nivel a 4 para velocidad máxima
       if level >= 4:
           level = 4
       # Configurar la velocidad del motor
       motor.forward(speed=float(level / 4))
       return level

   def changeLevel():
       """
       Changes the motor speed level when the button is pressed and updates the reference temperature.
       """
       global level, currentTemp, markTemp
       print("Button pressed")
       # Cycle through levels 0-4
       level = (level + 1) % 5
       # Actualizar la temperatura de referencia
       markTemp = currentTemp

   # Vincular el evento de presionar el botón a la función changeLevel
   BtnPin.when_pressed = changeLevel

   def main():
       """
       Main function to continuously monitor and respond to temperature changes.
       """
       global level, currentTemp, markTemp
       # Establecer la temperatura de referencia inicial
       markTemp = temperature()
       while True:
           # Leer continuamente la temperatura actual
           currentTemp = temperature()
           # Ajustar el nivel del motor según la diferencia de temperatura
           if level != 0:
               if currentTemp - markTemp <= -2:
                   level -= 1
                   markTemp = currentTemp
               elif currentTemp - markTemp >= 2:
                   if level < 4:
                       level += 1
                   markTemp = currentTemp
           # Ejecutar el motor al nivel ajustado
           level = motor_run(level)

   # Ejecutar la función principal y manejar KeyboardInterrupt
   try:
       main()
   except KeyboardInterrupt:
       # Detener el motor cuando se interrumpe el script
       motor.stop()



Explicación del Código
--------------------------

#. Importa clases para gestionar un motor y un botón, y la función sleep para introducir pausas. Además, importa la biblioteca ADC0834 para la detección de temperatura y la biblioteca math para cálculos matemáticos.

   .. code-block:: python

       #!/usr/bin/env python3

       from gpiozero import Motor, Button
       from time import sleep
       import ADC0834
       import math

#. Configura el botón en el pin GPIO 22 y configura el motor con pines GPIO específicos para el control. Inicializa el módulo ADC0834 para la medición de temperatura. También, inicializa variables para monitorear el nivel de velocidad del motor y las temperaturas.

   .. code-block:: python

       # Inicializar pines GPIO para el control del botón y el motor
       BtnPin = Button(22)
       motor = Motor(forward=5, backward=6, enable=13)

       # Inicializar el módulo ADC0834 para la detección de temperatura
       ADC0834.setup()

       # Inicializar variables para rastrear el nivel de velocidad del motor y las temperaturas
       level = 0
       currentTemp = 0
       markTemp = 0

#. Define una función para leer y calcular la temperatura del sensor, convirtiendo la lectura a Celsius.

   .. code-block:: python

       def temperature():
           """
           Reads and calculates the current temperature from the sensor.
           Returns:
               float: The current temperature in Celsius.
           """
           # Leer valor analógico del módulo ADC0834
           analogVal = ADC0834.getResult()
           # Convertir valor analógico a voltaje y luego a resistencia
           Vr = 5 * float(analogVal) / 255
           Rt = 10000 * Vr / (5 - Vr)
           # Calcular temperatura en Celsius
           temp = 1 / (((math.log(Rt / 10000)) / 3950) + (1 / (273.15 + 25)))
           Cel = temp - 273.15
           return Cel

#. Introduce una función para ajustar la velocidad del motor según el nivel especificado.

   .. code-block:: python

       def motor_run(level):
           """
           Adjusts the motor speed based on the specified level.
           Args:
               level (int): Desired motor speed level.
           Returns:
               int: Adjusted motor speed level.
           """
           # Detener el motor si el nivel es 0
           if level == 0:
               motor.stop()
               return 0
           # Limitar el nivel a 4 para velocidad máxima
           if level >= 4:
               level = 4
           # Configurar la velocidad del motor
           motor.forward(speed=float(level / 4))
           return level

#. Implementa una función para cambiar manualmente el nivel de velocidad del motor utilizando un botón, y vincula esta función al evento de presionar el botón.

   .. code-block:: python

       def changeLevel():
           """
           Changes the motor speed level when the button is pressed and updates the reference temperature.
           """
           global level, currentTemp, markTemp
           print("Button pressed")
           # Ciclar a través de los niveles 0-4
           level = (level + 1) % 5
           # Actualizar la temperatura de referencia
           markTemp = currentTemp

       # Vincular el evento de presionar el botón a la función changeLevel
       BtnPin.when_pressed = changeLevel

#. La función principal, diseñada para ajustar continuamente la velocidad del motor en respuesta a las fluctuaciones de temperatura, aún debe ser implementada.

   .. code-block:: python

       def main():
           """
           Main function to continuously monitor and respond to temperature changes.
           """
           global level, currentTemp, markTemp
           # Establecer la temperatura de referencia inicial
           markTemp = temperature()
           while True:
               # Leer continuamente la temperatura actual
               currentTemp = temperature()
               # Ajustar el nivel del motor según la diferencia de temperatura
               if level != 0:
                   if currentTemp - markTemp <= -2:
                       level -= 1
                       markTemp = currentTemp
                   elif currentTemp - markTemp >= 2:
                       if level < 4:
                           level += 1
                       markTemp = currentTemp
               # Ejecutar el motor al nivel ajustado
               level = motor_run(level)

#. Ejecuta la función principal y asegura que el motor se detenga si el script es interrumpido.

   .. code-block:: python

       # Ejecutar la función principal y manejar KeyboardInterrupt
       try:
           main()
       except KeyboardInterrupt:
           # Detener el motor cuando se interrumpe el script
           motor.stop()


