.. note::

    Bonjour, bienvenue dans la communauté SunFounder pour les passionnés de Raspberry Pi, Arduino et ESP32 sur Facebook ! Plongez dans l'univers de Raspberry Pi, Arduino et ESP32 avec d'autres passionnés.

    **Pourquoi nous rejoindre ?**

    - **Support d'experts** : Résolvez les problèmes après-vente et relevez les défis techniques grâce à l'aide de notre communauté et de notre équipe.
    - **Apprendre & Partager** : Échangez des conseils et tutoriels pour perfectionner vos compétences.
    - **Aperçus exclusifs** : Obtenez un accès anticipé aux nouvelles annonces de produits et à des avant-premières.
    - **Réductions spéciales** : Bénéficiez de réductions exclusives sur nos derniers produits.
    - **Promotions festives et concours** : Participez à des concours et promotions pendant les fêtes.

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

.. _2.2.6_py_pi5:

2.2.6 Module MPU6050
=======================

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

Le MPU-6050 est le premier et le seul dispositif de suivi de mouvement à 6 axes 
au monde (3 axes de gyroscope et 3 axes d'accéléromètre), conçu pour les smartphones, 
les tablettes et les capteurs portables répondant aux exigences de faible consommation, 
de faible coût et de haute performance.

Dans cette expérience, nous utiliserons le bus I2C pour obtenir les valeurs du capteur 
d'accélération et du gyroscope du MPU6050 et les afficherons à l'écran.


Composants nécessaires
-------------------------

Dans ce projet, nous aurons besoin des composants suivants : 

.. image:: ../python_pi5/img/2.2.6_mpu6050_list.png

.. raw:: html

   <br/>

Schéma de câblage
---------------------

Le module MPU6050 communique avec le microcontrôleur via l'interface de bus I2C. 
Les broches SDA1 et SCL1 doivent être connectées aux broches correspondantes.

.. image:: ../python_pi5/img/2.2.6_mpu6050_schematic.png


Procédure expérimentale
--------------------------

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

.. image:: ../python_pi5/img/2.2.6_mpu6050_circuit.png


**Étape 2 :** Configurez l'I2C (consultez l'annexe :ref:`i2c_config`. Si l'I2C est déjà configuré, ignorez cette étape.)

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

.. raw:: html

   <run></run>

.. code-block::

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

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

.. raw:: html

   <run></run>

.. code-block::

    sudo python3 2.2.6_mpu6050.py

Lorsque le code est exécuté, l'angle de déviation des axes x et y, ainsi que 
l'accélération et la vitesse angulaire sur chaque axe, seront calculés puis 
affichés à l'écran.

.. note::

    * Si vous obtenez l'erreur ``FileNotFoundError: [Errno 2] No such file or directory: '/dev/i2c-1'``, vous devez vous référer à :ref:`i2c_config` pour activer l'I2C.
    * Si vous obtenez l'erreur ``ModuleNotFoundError: No module named 'smbus2'``, exécutez la commande ``sudo pip3 install smbus2``.
    * Si l'erreur ``OSError: [Errno 121] Remote I/O error`` apparaît, cela signifie que le module est mal câblé ou endommagé.

.. warning::

    En cas de 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 accéder au chemin source du code, comme ``davinci-kit-for-raspberry-pi/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

   import smbus
   import math
   import time

   # Registres de gestion de l'alimentation
   power_mgmt_1 = 0x6b
   power_mgmt_2 = 0x6c

   def read_byte(adr):
       return bus.read_byte_data(address, adr)

   def read_word(adr):
       high = bus.read_byte_data(address, adr)
       low = bus.read_byte_data(address, adr+1)
       val = (high << 8) + low
       return val

   def read_word_2c(adr):
       val = read_word(adr)
       if (val >= 0x8000):
           return -((65535 - val) + 1)
       else:
           return val

   def dist(a,b):
       return math.sqrt((a*a)+(b*b))

   def get_y_rotation(x,y,z):
       radians = math.atan2(x, dist(y,z))
       return -math.degrees(radians)

   def get_x_rotation(x,y,z):
       radians = math.atan2(y, dist(x,z))
       return math.degrees(radians)


   bus = smbus.SMBus(1) # Initialisation du bus I2C
   address = 0x68       # Adresse obtenue avec la commande i2cdetect

   # Sortir le MPU6050 du mode veille
   bus.write_byte_data(address, power_mgmt_1, 0)

   while True:
       time.sleep(0.1)
       gyro_xout = read_word_2c(0x43)
       gyro_yout = read_word_2c(0x45)
       gyro_zout = read_word_2c(0x47)

       print ("gyro_xout : ", gyro_xout, " scaled: ", (gyro_xout / 131))
       print ("gyro_yout : ", gyro_yout, " scaled: ", (gyro_yout / 131))
       print ("gyro_zout : ", gyro_zout, " scaled: ", (gyro_zout / 131))

       accel_xout = read_word_2c(0x3b)
       accel_yout = read_word_2c(0x3d)
       accel_zout = read_word_2c(0x3f)

       accel_xout_scaled = accel_xout / 16384.0
       accel_yout_scaled = accel_yout / 16384.0
       accel_zout_scaled = accel_zout / 16384.0

       print ("accel_xout: ", accel_xout, " scaled: ", accel_xout_scaled)
       print ("accel_yout: ", accel_yout, " scaled: ", accel_yout_scaled)
       print ("accel_zout: ", accel_zout, " scaled: ", accel_zout_scaled)

       print ("x rotation: " , get_x_rotation(accel_xout_scaled, accel_yout_scaled, accel_zout_scaled))
       print ("y rotation: " , get_y_rotation(accel_xout_scaled, accel_yout_scaled, accel_zout_scaled))

       time.sleep(1)


**Explication du code**

#. Lire les données envoyées par le MPU6050.

   .. code-block:: python

       def read_word(adr):
           high = bus.read_byte_data(address, adr)
           low = bus.read_byte_data(address, adr+1)
           val = (high << 8) + low
           return val

       def read_word_2c(adr):
           val = read_word(adr)
           if (val >= 0x8000):
               return -((65535 - val) + 1)
           else:
               return val

#. Calculer l'angle de déviation sur l'axe y.

   .. code-block:: python

       def get_y_rotation(x,y,z):
           radians = math.atan2(x, dist(y,z))
           return -math.degrees(radians)

#. Calculer l'angle de déviation sur l'axe x.

   .. code-block:: python

       def get_x_rotation(x,y,z):
           radians = math.atan2(y, dist(x,z))
           return math.degrees(radians)

#. Lire les valeurs des axes x, y et z du gyroscope, convertir les données en vitesse angulaire et les afficher.

   .. code-block:: python

       gyro_xout = read_word_2c(0x43)
       gyro_yout = read_word_2c(0x45)
       gyro_zout = read_word_2c(0x47)

       print ("gyro_xout : ", gyro_xout, " scaled: ", (gyro_xout / 131))
       print ("gyro_yout : ", gyro_yout, " scaled: ", (gyro_yout / 131))
       print ("gyro_zout : ", gyro_zout, " scaled: ", (gyro_zout / 131))

#. Lire les valeurs des axes x, y et z de l'accéléromètre, convertir les données en accélération (en unités de gravité) et les afficher.

   .. code-block:: python

       accel_xout = read_word_2c(0x3b)
       accel_yout = read_word_2c(0x3d)
       accel_zout = read_word_2c(0x3f)

       accel_xout_scaled = accel_xout / 16384.0
       accel_yout_scaled = accel_yout / 16384.0
       accel_zout_scaled = accel_zout / 16384.0

       print ("accel_xout: ", accel_xout, " scaled: ", accel_xout_scaled)
       print ("accel_yout: ", accel_yout, " scaled: ", accel_yout_scaled)
       print ("accel_zout: ", accel_zout, " scaled: ", accel_zout_scaled)

#. Afficher les angles de déviation sur les axes x et y.

   .. code-block:: python

       print ("x rotation: " , get_x_rotation(accel_xout_scaled, accel_yout_scaled, accel_zout_scaled))
       print ("y rotation: " , get_y_rotation(accel_xout_scaled, accel_yout_scaled, accel_zout_scaled))

