.. note::

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

    **¿Por qué unirse?**

    - **Soporte experto**: Resuelve problemas post-venta 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**: Obtén acceso temprano a nuevos anuncios de productos y adelantos.
    - **Descuentos especiales**: Disfruta de descuentos exclusivos en nuestros productos más nuevos.
    - **Promociones festivas y sorteos**: Participa en sorteos y promociones de temporada.

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

.. _1.3.2_py:

1.3.2 Servo
===============

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

En este proyecto, aprenderemos a hacer que el servo gire.

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

En este proyecto, necesitamos los siguientes componentes. 

.. image:: ../img/list_1.3.2.png

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

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

    *   - Nombre	
        - ELEMENTOS 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_servo`
        - |link_servo_buy|

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

.. image:: ../img/image337.png


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

**Paso 1:** Montar el circuito.

.. image:: ../img/image125.png

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

.. raw:: html

   <run></run>

.. code-block::

    cd ~/raphael-kit/python/

**Paso 3**: Ejecutar el archivo ejecutable.

.. raw:: html

   <run></run>

.. code-block::

    sudo python3 1.3.2_Servo.py

Después de ejecutar el programa, el servo girará de 0 grados a 180 grados, 
y luego de 180 grados a 0 grados, en forma circular.

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


.. raw:: html

    <run></run>

.. code-block:: python

    import RPi.GPIO as GPIO
    import time

    SERVO_MIN_PULSE = 500
    SERVO_MAX_PULSE = 2500
    ServoPin = 18

    def map(value, inMin, inMax, outMin, outMax):
        return (outMax - outMin) * (value - inMin) / (inMax - inMin) + outMin

    def setup():
        global p
        GPIO.setmode(GPIO.BCM)       # Numerar los GPIOs por BCM
        GPIO.setup(ServoPin, GPIO.OUT)   # Configurar el modo de ServoPin como salida
        GPIO.output(ServoPin, GPIO.LOW)  # Establecer ServoPin en bajo
        p = GPIO.PWM(ServoPin, 50)     # Establecer frecuencia a 50Hz
        p.start(0)                     # Ciclo de trabajo = 0
        
    def setAngle(angle):      # hacer que el servo gire a un ángulo específico (0-180 grados) 
        angle = max(0, min(180, angle))
        pulse_width = map(angle, 0, 180, SERVO_MIN_PULSE, SERVO_MAX_PULSE)
        pwm = map(pulse_width, 0, 20000, 0, 100)
        p.ChangeDutyCycle(pwm)#mapear el ángulo al ciclo de trabajo y enviarlo    
    def loop():
        while True:
            for i in range(0, 181, 5):   #hacer que el servo gire de 0 a 180 grados
                setAngle(i)     # Escribir al servo
                time.sleep(0.002)
            time.sleep(1)
            for i in range(180, -1, -5): #hacer que el servo gire de 180 a 0 grados
                setAngle(i)
                time.sleep(0.001)
            time.sleep(1)
    def destroy():
        p.stop()
        GPIO.cleanup()

    if __name__ == '__main__':     # El programa empieza aquí
        setup()
        try:
            loop()
        except KeyboardInterrupt:  # Cuando se presiona 'Ctrl+C', se ejecutará el programa destroy().
            destroy()

**Explicación del Código**

.. code-block:: python

    p = GPIO.PWM(ServoPin, 50)     # set Frequecy to 50Hz
    p.start(0)                     # Duty Cycle = 0

Configura el ServoPin como pin PWM, luego la frecuencia a 50Hz y el periodo a 20ms.

p.start(0): Ejecuta la función PWM y establece el valor inicial en 0.

.. code-block:: python

    def setAngle(angle):      # make the servo rotate to specific angle (0-180 degrees) 
        angle = max(0, min(180, angle))
        pulse_width = map(angle, 0, 180, SERVO_MIN_PULSE, SERVO_MAX_PULSE)
        pwm = map(pulse_width, 0, 20000, 0, 100)
        p.ChangeDutyCycle(pwm)#map the angle to duty cycle and output it

Crea una función, setAngle() para escribir un ángulo que varía de 0 a 180 en el servo.

.. code-block:: python

    angle = max(0, min(180, angle))

Este código se utiliza para limitar el ángulo dentro del rango 0-180°.

La función min() devuelve el mínimo de los valores de entrada. Si 180<ángulo, entonces devuelve 180, si no, devuelve ángulo.

El método max() devuelve el elemento máximo en un iterable o el mayor de dos o más parámetros. Si 0>ángulo, entonces devuelve 0, si no, devuelve ángulo.

.. code-block:: python

    pulse_width = map(angle, 0, 180, SERVO_MIN_PULSE, SERVO_MAX_PULSE)
    pwm = map(pulse_width, 0, 20000, 0, 100)
    p.ChangeDutyCycle(pwm)

Para establecer un rango de 0 ~ 180° en el servo, el ancho de pulso del servo se establece en 0.5ms (500us) - 2.5ms (2500us).

El periodo del PWM es de 20ms (20000us), por lo tanto, el ciclo de trabajo del PWM es (500/20000)% - (2500/20000)%, y el rango 0 ~ 180 se mapea a 2.5 ~ 12.5.

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

.. image:: ../img/image126.jpeg

