.. note::

    ¡Hola! Bienvenido a la comunidad de entusiastas de SunFounder para Raspberry Pi, Arduino y ESP32 en Facebook. Profundiza en el mundo de Raspberry Pi, Arduino y ESP32 junto con otros entusiastas.

    **¿Por qué unirte?**

    - **Soporte experto**: Resuelve problemas posventa y desafíos técnicos con la ayuda de nuestra comunidad y equipo.
    - **Aprende y comparte**: Intercambia consejos y tutoriales para mejorar tus habilidades.
    - **Avances exclusivos**: Accede a anuncios de nuevos productos y vistas previas exclusivas.
    - **Descuentos especiales**: Disfruta de descuentos exclusivos en nuestros productos más recientes.
    - **Promociones y sorteos festivos**: Participa en sorteos y promociones durante las festividades.

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

3.1.4 Ventilador Inteligente
=============================

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

En este curso, usaremos motores, botones y termistores para crear un ventilador 
inteligente manual y automático, con velocidad de viento ajustable.


Componentes
----------------
.. image:: img/list_Smart_Fan.png
    :align: center

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

============ ======== ======== ===
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
GPIO5        Pin 29   21       5
GPIO6        Pin 31   22       6
GPIO13       Pin 33   23       13
============ ======== ======== ===

.. image:: img/Schematic_three_one4.png
    :width: 500
    :align: center

Procedimiento Experimental
-----------------------------

**Paso 1:** Construye el circuito.

.. image:: img/image245.png
   :alt: Smart Fan_bb
   :width: 800
   :align: center

.. note::
    El módulo de alimentación puede utilizar una batería de 9V con el 
    conector de batería de 9V incluido en el kit. Inserta el capuchón 
    del módulo de energía en las tiras de bus de 5V de la protoboard.

.. image:: img/image118.jpeg
   :alt: \_MG_2084
   :width: 2.80694in
   :height: 0.94375in
   :align: center

**Para Usuarios de Lenguaje C**
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

**Paso 2**: Ingresa en la carpeta del código.

.. raw:: html

   <run></run>

.. code-block::

    cd ~/davinci-kit-for-raspberry-pi/c/3.1.4/

**Paso 3**: Compila el código.

.. raw:: html

   <run></run>

.. code-block::

    gcc 3.1.4_SmartFan.c -lwiringPi -lm

**Paso 4**: Ejecuta el archivo ejecutable anterior.

.. raw:: html

   <run></run>

.. code-block::

    sudo ./a.out

Al ejecutar el código, inicia el ventilador presionando el botón. Cada 
vez que presiones, se ajustará una velocidad hacia arriba o hacia abajo. 
Hay **5** niveles de velocidad: **0~4**. Al establecer el nivel de velocidad 
en el 4\ :sup:`to` y presionar el botón, el ventilador dejará de funcionar 
con velocidad de viento **0**.

.. note::

    Si no funciona después de ejecutarlo o aparece el mensaje de error: \"wiringPi.h: No such file or directory\", consulta :ref:`C code is not working?`.

Una vez que la temperatura sube o baja más de 2℃, la velocidad se ajusta 
automáticamente a un nivel más rápido o más lento.


**Explicación del Código**

.. code-block:: c

    int temperture(){
        unsigned char analogVal;
        double Vr, Rt, temp, cel, Fah;
        analogVal = get_ADC_Result(0);
        Vr = 5 * (double)(analogVal) / 255;
        Rt = 10000 * (double)(Vr) / (5 - (double)(Vr));
        temp = 1 / (((log(Rt/10000)) / 3950)+(1 / (273.15 + 25)));
        cel = temp - 273.15;
        Fah = cel * 1.8 +32;
        int t=cel;
        return t;
    }

La función temperture() convierte los valores del termistor leídos por el 
ADC0834 en valores de temperatura. Consulta :ref:`2.2.2 Thermistor` para obtener más detalles.

.. code-block:: c

    int motor(int level){
        if(level==0){
            digitalWrite(MotorEnable,LOW);
            return 0;
        }
        if (level>=4){
            level =4;
        }
        digitalWrite(MotorEnable,HIGH);
        softPwmWrite(MotorPin1, level*25);
        return level;    
    }

Esta función controla la velocidad de rotación del motor. El rango de **nivel** 
es **0-4** (el nivel **0** detiene el motor). Cada ajuste de nivel representa un 
cambio del **25%** en la velocidad del viento.

.. code-block:: c

    int main(void)
    {
        setup();
        int currentState,lastState=0;
        int level = 0;
        int currentTemp,markTemp=0;
        while(1){
            currentState=digitalRead(BtnPin);
            currentTemp=temperture();
            if (currentTemp<=0){continue;}
            if (currentState==1&&lastState==0){
                level=(level+1)%5;
                markTemp=currentTemp;
                delay(500);
            }
            lastState=currentState;
            if (level!=0){
                if (currentTemp-markTemp<=-2){
                    level=level-1;
                    markTemp=currentTemp;
                }
                if (currentTemp-markTemp>=2){
                    level=level+1;
                    markTemp=currentTemp;
                }
            }
            level=motor(level);
        }
        return 0;
    }

La función **main()** contiene todo el proceso del programa, como se muestra a continuación:

1) Leer constantemente el estado del botón y la temperatura actual.

2) Cada pulsación incrementa el nivel en **+1** y, al mismo tiempo, se actualiza 
la temperatura. El **nivel** varía entre **1~4**.

3) Cuando el ventilador está en funcionamiento (el nivel es **diferente de 0**), 
se realiza una detección de temperatura. Un cambio de **2℃\ +** provoca el aumento o disminución del nivel.

4) El motor ajusta su velocidad de rotación según el **nivel**.

**Para Usuarios de Python**
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

**Paso 2**: Ingresar en la carpeta del código.

.. raw:: html

   <run></run>

.. code-block:: 

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

**Paso 3**: Ejecutar.

.. raw:: html

   <run></run>

.. code-block:: 

    sudo python3 3.1.4_SmartFan.py

Al ejecutar el código, inicia el ventilador presionando el botón. Cada vez 
que presionas, se ajusta un nivel de velocidad hacia arriba o hacia abajo. 
Hay **5** niveles de velocidad: **0~4**. Cuando se ajusta al 4\ :sup:`to` 
nivel y se presiona el botón, el ventilador se detiene con velocidad de 
viento **0**.

Una vez que la temperatura sube o baja más de 2℃, la velocidad se ajusta 
automáticamente a un nivel superior o inferior.

**Código**

.. note::

    Puedes **Modificar/Restablecer/Copiar/Ejecutar/Detener** el código a continuación. Sin embargo, antes de hacerlo, debes dirigirte a la ruta de código fuente, como ``davinci-kit-for-raspberry-pi/python``.
    
.. raw:: html

    <run></run>

.. code-block:: python

    import RPi.GPIO as GPIO
    import time
    import ADC0834
    import math

    # Configurar pines
    MotorPin1   = 5
    MotorPin2   = 6
    MotorEnable = 13
    BtnPin   = 22

    def setup():
        global p_M1,p_M2
        ADC0834.setup()
        GPIO.setmode(GPIO.BCM)
        GPIO.setup(MotorPin1, GPIO.OUT)
        GPIO.setup(MotorPin2, GPIO.OUT)
        p_M1=GPIO.PWM(MotorPin1,2000)
        p_M2=GPIO.PWM(MotorPin2,2000)
        p_M1.start(0)
        p_M2.start(0)
        GPIO.setup(MotorEnable, GPIO.OUT, initial=GPIO.LOW)
        GPIO.setup(BtnPin, GPIO.IN)

    def temperature():
        analogVal = ADC0834.getResult()
        Vr = 5 * float(analogVal) / 255
        Rt = 10000 * Vr / (5 - Vr)
        temp = 1/(((math.log(Rt / 10000)) / 3950) + (1 / (273.15+25)))
        Cel = temp - 273.15
        Fah = Cel * 1.8 + 32
        return Cel

    def motor(level):
        if level == 0:
            GPIO.output(MotorEnable, GPIO.LOW)
            return 0
        if level>=4:
            level = 4
        GPIO.output(MotorEnable, GPIO.HIGH)
        p_M1.ChangeDutyCycle(level*25)
        return level


    def main():
        lastState=0
        level=0
        markTemp = temperature()
        while True:
            currentState =GPIO.input(BtnPin)
            currentTemp=temperature()
            if currentState == 1 and lastState == 0:
                level=(level+1)%5
                markTemp = currentTemp
                time.sleep(0.5)
            lastState=currentState
            if level!=0:
                if currentTemp-markTemp <= -2:
                    level = level -1
                    markTemp=currentTemp            
                if currentTemp-markTemp >= 2:
                    level = level +1
                    markTemp=currentTemp             
            level = motor(level)
            

    def destroy():
        GPIO.output(MotorEnable, GPIO.LOW)
        p_M1.stop()
        p_M2.stop()
        GPIO.cleanup()    

    if __name__ == '__main__':
        setup()
        try:
            main()
        except KeyboardInterrupt:
            destroy()

**Explicación del Código**

.. code-block:: python

    def temperature():
        analogVal = ADC0834.getResult()
        Vr = 5 * float(analogVal) / 255
        Rt = 10000 * Vr / (5 - Vr)
        temp = 1/(((math.log(Rt / 10000)) / 3950) + (1 / (273.15+25)))
        Cel = temp - 273.15
        Fah = Cel * 1.8 + 32
        return Cel

La función **temperature()** convierte los valores del termistor leídos 
por **ADC0834** en valores de temperatura. Consulte :ref:`2.2.2 Termistor` 
para obtener más detalles.

.. code-block:: python

    def motor(level):
        if level == 0:
            GPIO.output(MotorEnable, GPIO.LOW)
            return 0
        if level>=4:
            level = 4
        GPIO.output(MotorEnable, GPIO.HIGH)
        p_M1.ChangeDutyCycle(level*25)
        return level

Esta función controla la velocidad de rotación del motor. El rango del **nivel** 
es **0-4** (nivel **0** detiene el motor). Cada ajuste de nivel representa un 
cambio de **25%** en la velocidad del ventilador.

.. code-block:: python

    def main():
        lastState=0
        level=0
        markTemp = temperature()
        while True:
            currentState =GPIO.input(BtnPin)
            currentTemp=temperature()
            if currentState == 1 and lastState == 0:
                level=(level+1)%5
                markTemp = currentTemp
                time.sleep(0.5)
            lastState=currentState
            if level!=0:
                if currentTemp-markTemp <= -2:
                    level = level -1
                    markTemp=currentTemp            
                if currentTemp-markTemp >= 2:
                    level = level +1
                    markTemp=currentTemp             
            level = motor(level)


La función **main()** contiene el proceso completo del programa como se muestra:

1) Leer constantemente el estado del botón y la temperatura actual.

2) Cada pulsación incrementa el nivel en **+1** y al mismo tiempo, 
   se actualiza la temperatura. El **nivel** varía entre **1~4**.

3) Cuando el ventilador está en funcionamiento (el nivel es **diferente de 0**), 
   la temperatura se encuentra bajo monitoreo. Un cambio de **2℃+** provoca un aumento o disminución en el nivel.

4) El motor ajusta su velocidad de rotación según el **nivel**.

Imagen del Fenómeno
------------------------

.. image:: img/image246.png
   :align: center