 
.. note::

    Bonjour et bienvenue dans la Communauté Facebook des passionnés de Raspberry Pi, Arduino et ESP32 de SunFounder ! Plongez plus profondément dans l'univers des Raspberry Pi, Arduino et ESP32 avec d'autres passionnés.

    **Pourquoi rejoindre ?**

    - **Support d'experts** : Résolvez les problèmes après-vente et les défis techniques avec l'aide de notre communauté et de notre équipe.
    - **Apprendre et partager** : Échangez des astuces et des tutoriels pour améliorer vos compétences.
    - **Aperçus exclusifs** : Accédez en avant-première aux annonces de nouveaux produits et aux aperçus.
    - **Réductions spéciales** : Profitez de réductions exclusives sur nos produits les plus récents.
    - **Promotions festives et cadeaux** : Participez à des cadeaux et des promotions de vacances.

    👉 Prêt à explorer et à créer avec nous ? Cliquez [|link_sf_facebook|] et rejoignez-nous aujourd'hui !

.. _1.3.2_py:

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

Introduction
-----------------

Dans ce projet, nous allons apprendre à faire tourner un servo-moteur.

Composants Nécessaires
--------------------------------

Pour ce projet, nous avons besoin des composants suivants.

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

Il est certainement pratique d'acheter un kit complet, voici le lien :

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

    *   - Nom	
        - ARTICLES DANS CE KIT
        - LIEN
    *   - Kit Raphael
        - 337
        - |link_Raphael_kit|

Vous pouvez également les acheter séparément à partir des liens ci-dessous.

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

    *   - INTRODUCTION AUX COMPOSANTS
        - LIEN D'ACHAT

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

Schéma de Principe
---------------------

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


Procédures Expérimentales
---------------------------

**Étape 1 :** Construisez le circuit.

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

**Étape 2 :** Accédez au dossier du code.

.. raw:: html

   <run></run>

.. code-block::

    cd ~/raphael-kit/python/

**Étape 3 :** Exécutez le fichier exécutable.

.. raw:: html

   <run></run>

.. code-block::

    sudo python3 1.3.2_Servo.py

Après l'exécution du programme, le servo-moteur tournera de 0 degrés 
à 180 degrés, puis de 180 degrés à 0 degrés, en boucle.
**Code**

.. note::

    Vous pouvez **Modifier/Réinitialiser/Copier/Exécuter/Arrêter** le code ci-dessous. Mais avant cela, vous devez vous rendre dans le chemin du code source comme ``raphael-kit/python``. Après avoir modifié le code, vous pouvez l'exécuter directement pour voir l'effet.


.. 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)       # Numbers GPIOs by BCM
        GPIO.setup(ServoPin, GPIO.OUT)   # Set ServoPin's mode is output
        GPIO.output(ServoPin, GPIO.LOW)  # Set ServoPin to low
        p = GPIO.PWM(ServoPin, 50)     # set Frequecy to 50Hz
        p.start(0)                     # Duty Cycle = 0
        
    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    
    def loop():
        while True:
            for i in range(0, 181, 5):   #make servo rotate from 0 to 180 deg
                setAngle(i)     # Write to servo
                time.sleep(0.002)
            time.sleep(1)
            for i in range(180, -1, -5): #make servo rotate from 180 to 0 deg
                setAngle(i)
                time.sleep(0.001)
            time.sleep(1)
    def destroy():
        p.stop()
        GPIO.cleanup()

    if __name__ == '__main__':     #Program start from here
        setup()
        try:
            loop()
        except KeyboardInterrupt:  # When 'Ctrl+C' is pressed, the program destroy() will be executed.
            destroy()

**Explication du Code**

.. code-block:: python

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

Définir la broche ServoPin comme broche PWM, puis la fréquence à 50Hz, et la période à 20ms.

p.start(0) : Exécutez la fonction PWM et définissez la valeur initiale à 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

Créer une fonction, setAngle() pour écrire un angle compris entre 0 et 180 dans le servo.

.. code-block:: python

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

Ce code est utilisé pour limiter l'angle dans la plage 0-180°.

La fonction min() renvoie la valeur minimale des valeurs d'entrée.
Si 180<angle, alors retourner 180, sinon retourner angle.

La méthode max() renvoie l'élément maximal d'un itérable ou le plus grand de
deux ou plusieurs paramètres. Si 0>angle, alors retourner 0, sinon retourner angle.

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

Pour rendre une plage de 0 à 180° au servo, la largeur d'impulsion du servo
est définie à 0,5ms(500us)-2,5ms(2500us).

La période du PWM est de 20ms(20000us), donc le cycle de service du PWM est
(500/20000)%-(2500/20000)%, et la plage 0-180 est mappée à 2,5-12,5.


Image du Phénomène
------------------------

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

