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

.. _2.1.6_py_pi5:

2.1.6 Module Encodeur Rotatif
========================================

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

Dans ce projet, vous apprendrez à utiliser un encodeur rotatif. 
Un encodeur rotatif est un interrupteur électronique avec un ensemble 
de pulsations régulières dans une séquence de synchronisation stricte. 
Lorsqu'il est utilisé avec un CI, il peut permettre des opérations telles 
que l'incrémentation, la décrémentation, le changement de page et d'autres 
opérations comme le défilement de la souris, la sélection de menu, etc.


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

Pour ce projet, nous avons besoin des composants suivants :

.. image:: ../python_pi5/img/2.1.6_rotary_encoder_list.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_rotary_encoder`
        - |link_rotary_encoder_buy|

Schéma de Connexion
--------------------------

.. image:: ../python_pi5/img/2.1.6_rotary_encoder_schematic.png
   :align: center

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

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

.. image:: ../python_pi5/img/2.1.6_rotary_encoder_circuit.png

Dans cet exemple, nous pouvons connecter la broche de l'encodeur rotatif 
directement au Raspberry Pi en utilisant une plaque de montage et un câble 
40 broches. Connectez le GND de l'encodeur rotatif au GND, le 「+」au 5V, 
SW au GPIO numérique 27, DT au GPIO numérique 18 et CLK au GPIO numérique 17.

**Étape 2 :** Ouvrir le fichier de code.

.. raw:: html

   <run></run>

.. code-block::

    cd ~/raphael-kit/python-pi5

**Étape 3 :** Exécuter.

.. raw:: html

   <run></run>

.. code-block::

    sudo python3 2.1.6_RotaryEncoder_zero.py

Vous verrez le décompte dans le terminal. Lorsque vous tournez l'encodeur rotatif dans le sens des aiguilles d'une montre, le décompte augmente ; lorsque vous le tournez dans le sens inverse, le décompte diminue. Si vous appuyez sur l'interrupteur de l'encodeur rotatif, les lectures reviendront à zéro.

.. warning::

    Si vous recevez le message d'erreur ``RuntimeError: Cannot determine SOC peripheral base address``, veuillez consulter :ref:`faq_soc`

**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-pi5``. Après avoir modifié le code, vous pouvez l'exécuter directement pour voir l'effet.

.. raw:: html

    <run></run>

.. code-block:: python

   #!/usr/bin/env python3
   from gpiozero import RotaryEncoder, Button
   from time import sleep

   # Initialize the rotary encoder and button
   encoder = RotaryEncoder(a=17, b=18)  # Rotary Encoder connected to GPIO pins 17 (CLK) and 18 (DT)
   button = Button(27)                  # Button connected to GPIO pin 27

   global_counter = 0  # Track the rotary encoder's position

   def rotary_change():
      """ Update the global counter based on the rotary encoder's rotation. """
      global global_counter
      global_counter += encoder.steps  # Adjust counter based on encoder steps
      encoder.steps = 0  # Reset encoder steps after updating counter
      print('Global Counter =', global_counter)  # Display current counter value

   def reset_counter():
      """ Reset the global counter to zero when the button is pressed. """
      global global_counter
      global_counter = 0  # Reset the counter
      print('Counter reset')  # Indicate counter reset

   # Assign the reset_counter function to button press event
   button.when_pressed = reset_counter

   try:
      # Monitor rotary encoder continuously and process changes
      while True:
         rotary_change()  # Handle rotary encoder changes
         sleep(0.1)  # Short delay to reduce CPU load

   except KeyboardInterrupt:
      # Gracefully handle a keyboard interrupt (Ctrl+C)
      pass



**Analyse du Code**

#. Importe les classes ``RotaryEncoder`` et ``Button`` de la bibliothèque ``gpiozero``, ainsi que la fonction ``sleep`` pour les délais.

   .. code-block:: python

      #!/usr/bin/env python3
      from gpiozero import RotaryEncoder, Button
      from time import sleep

#. Initialise l'encodeur rotatif avec les broches GPIO 17 et 18, et un bouton sur la broche GPIO 27.

   .. code-block:: python

      # Initialize the rotary encoder and button
      encoder = RotaryEncoder(a=17, b=18)  # Rotary Encoder connected to GPIO pins 17 (CLK) and 18 (DT)
      button = Button(27)                  # Button connected to GPIO pin 27

#. Déclare une variable globale ``global_counter`` pour suivre la position de l'encodeur rotatif.

   .. code-block:: python

      global_counter = 0  # Track the rotary encoder's position

#. Définit une fonction ``rotary_change`` pour mettre à jour le compteur global en fonction de la rotation de l'encodeur rotatif.

   .. code-block:: python

      def rotary_change():
         """ Update the global counter based on the rotary encoder's rotation. """
         global global_counter
         global_counter += encoder.steps  # Adjust counter based on encoder steps
         encoder.steps = 0  # Reset encoder steps after updating counter
         print('Global Counter =', global_counter)  # Display current counter value

#. Définit une fonction ``reset_counter`` pour réinitialiser le compteur global à zéro lorsque le bouton est pressé.

   .. code-block:: python

      def reset_counter():
         """ Reset the global counter to zero when the button is pressed. """
         global global_counter
         global_counter = 0  # Reset the counter
         print('Counter reset')  # Indicate counter reset

#. Assigne la fonction ``reset_counter`` pour qu'elle soit appelée lorsque le bouton est pressé.

   .. code-block:: python

      # Assign the reset_counter function to button press event
      button.when_pressed = reset_counter

#. Dans une boucle continue, le script appelle ``rotary_change`` pour gérer les changements de l'encodeur rotatif et introduit un court délai pour réduire la charge du CPU. Utilise un bloc try-except pour gérer les interruptions clavier de manière élégante.

   .. code-block:: python

      try:
         # Monitor rotary encoder continuously and process changes
         while True:
            rotary_change()  # Handle rotary encoder changes
            sleep(0.1)  # Short delay to reduce CPU load

      except KeyboardInterrupt:
         # Gracefully handle a keyboard interrupt (Ctrl+C)
         pass

