.. note::

    Bonjour, bienvenue dans la communauté SunFounder Raspberry Pi & Arduino & ESP32 Enthusiasts sur Facebook ! Plongez plus profondément dans l'univers du Raspberry Pi, Arduino et ESP32 avec d'autres passionnés.

    **Pourquoi nous rejoindre ?**

    - **Support d'experts** : Résolvez les problèmes post-vente et les défis techniques avec l'aide de notre communauté et de notre équipe.
    - **Apprendre & Partager** : Échangez des astuces et des tutoriels pour améliorer vos compétences.
    - **Aperçus exclusifs** : Bénéficiez d'un accès anticipé aux nouvelles annonces de produits et aperçus.
    - **Réductions spéciales** : Profitez de réductions exclusives sur nos derniers produits.
    - **Promotions festives et concours** : Participez à des concours et des promotions de fêtes.

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

.. _2.1.4_potentiometer:

2.1.4 Potentiomètre
======================

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

La fonction ADC peut être utilisée pour convertir des signaux analogiques en 
signaux numériques. Dans cette expérience, nous utilisons l'ADC0834 pour réaliser 
cette conversion avec un potentiomètre. Le potentiomètre modifie la quantité physique 
— la tension — qui est ensuite convertie par la fonction ADC.

Composants
-----------

.. image:: img/list_2.1.4_potentiometer.png


Principe
----------

**ADC0834**

L'ADC0834 est un convertisseur analogique-numérique 8 bits à `successive approximation <https://cn.bing.com/dict/search?q=successive approximations&FORM=BDVSP6&mkt=zh-cn>`__ 
équipé d'un multiplexeur multicanal configurable et d'une entrée/sortie série. Cette entrée/sortie série est conçue pour interfacer avec des registres à décalage ou des microprocesseurs.

.. image:: img/image309.png


**Séquence d'Opération**
La conversion est initiée en plaçant CS à un niveau bas, ce qui active tous 
les circuits logiques. CS doit rester à un niveau bas pendant tout le processus 
de conversion. Un signal d'horloge est ensuite reçu du processeur. À chaque 
transition du signal d'horloge de bas en haut, les données sur DI sont envoyées 
dans le registre de décalage d'adresse du multiplexeur. Le premier signal haut 
sur l'entrée correspond au bit de démarrage. Un mot d'assignation de 3 à 4 bits 
suit le bit de démarrage. À chaque transition suivante de bas en haut du signal 
d'horloge, le bit de démarrage et le mot d'assignation sont décalés dans le 
registre de décalage. Lorsque le bit de démarrage atteint la position de démarrage 
du registre du multiplexeur, le canal d'entrée est sélectionné et la conversion 
commence. La sortie SAR Statu (SARS) passe à un niveau haut pour indiquer qu'une 
conversion est en cours, et l'entrée DI du registre de décalage du multiplexeur 
est désactivée pendant la durée de la conversion.

Un intervalle d'une période d'horloge est automatiquement inséré pour permettre au 
canal multiplexé sélectionné de se stabiliser. La sortie des données (DO) quitte 
l'état haute impédance et fournit un niveau bas pour cette période d'horloge de 
stabilisation du multiplexeur. Le comparateur SAR compare les sorties successives 
de l'échelle résistive au signal analogique entrant. La sortie du comparateur 
indique si l'entrée analogique est supérieure ou inférieure à la sortie de l'échelle 
résistive. Au fur et à mesure que la conversion progresse, les données de conversion 
sont simultanément envoyées depuis la broche de sortie DO, en commençant par le bit 
de poids fort (MSB).

Après huit périodes d'horloge, la conversion est terminée et la sortie SARS passe à 
un niveau bas. Enfin, les données sont sorties, en commençant par le bit de poids 
faible (LSB) après le flux de données commençant par le MSB.

.. image:: img/image175.png
    :width: 800
    :align: center


**Table de contrôle d'adresse MUX de l'ADC0834**

.. image:: img/image176.png
    :width: 800
    :align: center


**Potentiomètre**

Le potentiomètre est un composant de résistance avec trois bornes dont la valeur de 
résistance peut être ajustée. Il est généralement composé d'un résistor et d'un contact 
mobile. Lorsque le contact se déplace le long du résistor, une certaine résistance ou 
une tension est générée en fonction du déplacement.

.. image:: img/image310.png
    :width: 300
    :align: center


Les fonctions du potentiomètre dans le circuit sont les suivantes :

1. Servir de diviseur de tension

Le potentiomètre est une résistance ajustable en continu. Lorsque vous ajustez 
l'arbre ou le curseur du potentiomètre, le contact mobile se déplace sur le 
résistor. Une tension est alors générée en fonction de la tension appliquée et 
de l'angle ou de la distance parcourue par le bras mobile.

Schéma
---------

.. image:: img/image311.png


.. image:: img/image312.png


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

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

.. image:: img/image180.png
    :width: 800



.. note::
    Placez la puce en vous référant à la position indiquée sur l'image. Veillez 
    à ce que les rainures sur la puce soient orientées à gauche lors de son placement.

Pour les utilisateurs de langage C
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

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

.. raw:: html

   <run></run>

.. code-block::

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

**Étape 3 :** Compilez le code.

.. raw:: html

   <run></run>

.. code-block::

    gcc 2.1.4_Potentiometer.c -lwiringPi

**Étape 4 :** Exécutez.

.. raw:: html

   <run></run>

.. code-block::

    sudo ./a.out

Une fois le code exécuté, tournez le bouton du potentiomètre et l'intensité 
de la LED changera en conséquence.

.. note::

    Si cela ne fonctionne pas après l'exécution, ou si un message d'erreur apparaît : "wiringPi.h: Aucun fichier ou répertoire de ce type", veuillez consulter :ref:`C code is not working?`.

**Code**

.. code-block:: c

    #include <wiringPi.h>
    #include <stdio.h>
    #include <softPwm.h>

    typedef unsigned char uchar;
    typedef unsigned int uint;

    #define     ADC_CS    0
    #define     ADC_CLK   1
    #define     ADC_DIO   2
    #define     LedPin    3

    uchar get_ADC_Result(uint channel)
    {
        uchar i;
        uchar dat1=0, dat2=0;
        int sel = channel > 1 & 1;
        int odd = channel & 1;

        digitalWrite(ADC_CLK, 1);
        delayMicroseconds(2);
        digitalWrite(ADC_CLK, 0);
        delayMicroseconds(2);

        pinMode(ADC_DIO, OUTPUT);
        digitalWrite(ADC_CS, 0);
        // Bit de démarrage
        digitalWrite(ADC_CLK,0);
        digitalWrite(ADC_DIO,1);    delayMicroseconds(2);
        digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
        // Mode Single End
        digitalWrite(ADC_CLK,0);
        digitalWrite(ADC_DIO,1);    delayMicroseconds(2);
        digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
        // ODD
        digitalWrite(ADC_CLK,0);
        digitalWrite(ADC_DIO,odd);  delayMicroseconds(2);
        digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
        // Sélection
        digitalWrite(ADC_CLK,0);
        digitalWrite(ADC_DIO,sel);    delayMicroseconds(2);
        digitalWrite(ADC_CLK,1);

        digitalWrite(ADC_DIO,1);    delayMicroseconds(2);
        digitalWrite(ADC_CLK,0);
        digitalWrite(ADC_DIO,1);    delayMicroseconds(2);

        for(i=0;i<8;i++)
        {
            digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
            digitalWrite(ADC_CLK,0);    delayMicroseconds(2);

            pinMode(ADC_DIO, INPUT);
            dat1=dat1<<1 | digitalRead(ADC_DIO);
        }

        for(i=0;i<8;i++)
        {
            dat2 = dat2 | ((uchar)(digitalRead(ADC_DIO))<<i);
            digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
            digitalWrite(ADC_CLK,0);    delayMicroseconds(2);
        }

        digitalWrite(ADC_CS,1);
        pinMode(ADC_DIO, OUTPUT);
        return(dat1==dat2) ? dat1 : 0;
    }

    int main(void)
    {
        uchar analogVal;
        if(wiringPiSetup() == -1){ //si l'initialisation échoue, affichage du message d'erreur
            printf("setup wiringPi failed !");
            return 1;
        }
        softPwmCreate(LedPin,  0, 100);
        pinMode(ADC_CS,  OUTPUT);
        pinMode(ADC_CLK, OUTPUT);

        while(1){
            analogVal = get_ADC_Result(0);
            printf("Current analogVal : %d\n", analogVal);
            delay(100);
            softPwmWrite(LedPin, analogVal);
            delay(100);
        }
        return 0;
    }

**Explication du code**

.. code-block:: c

    #define     ADC_CS    0
    #define     ADC_CLK   1
    #define     ADC_DIO   2
    #define     LedPin    3

Définissez CS, CLK, DIO pour l'ADC0834, et connectez-les respectivement à GPIO0, 
GPIO1 et GPIO2. Ensuite, connectez la LED à GPIO3.

.. code-block:: c

    uchar get_ADC_Result(uint channel)
    {
        uchar i;
        uchar dat1=0, dat2=0;
        int sel = channel > 1 & 1;
        int odd = channel & 1;

        digitalWrite(ADC_CLK, 1);
        delayMicroseconds(2);
        digitalWrite(ADC_CLK, 0);
        delayMicroseconds(2);

        pinMode(ADC_DIO, OUTPUT);
        digitalWrite(ADC_CS, 0);
        // Bit de démarrage
        digitalWrite(ADC_CLK,0);
        digitalWrite(ADC_DIO,1);    delayMicroseconds(2);
        digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
        // Mode Single End
        digitalWrite(ADC_CLK,0);
        digitalWrite(ADC_DIO,1);    delayMicroseconds(2);
        digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
        // Impair
        digitalWrite(ADC_CLK,0);
        digitalWrite(ADC_DIO,odd);  delayMicroseconds(2);
        digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
        // Sélection
        digitalWrite(ADC_CLK,0);
        digitalWrite(ADC_DIO,sel);    delayMicroseconds(2);
        digitalWrite(ADC_CLK,1);

        digitalWrite(ADC_DIO,1);    delayMicroseconds(2);
        digitalWrite(ADC_CLK,0);
        digitalWrite(ADC_DIO,1);    delayMicroseconds(2);
        for(i=0;i<8;i++)
        {
            digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
            digitalWrite(ADC_CLK,0);    delayMicroseconds(2);

            pinMode(ADC_DIO, INPUT);
            dat1=dat1<<1 | digitalRead(ADC_DIO);
        }

        for(i=0;i<8;i++)
        {
            dat2 = dat2 | ((uchar)(digitalRead(ADC_DIO))<<i);
            digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
            digitalWrite(ADC_CLK,0);    delayMicroseconds(2);
        }

        digitalWrite(ADC_CS,1);
        pinMode(ADC_DIO, OUTPUT);
        return(dat1==dat2) ? dat1 : 0;
    }

Il s'agit d'une fonction pour l'ADC0834 qui permet d'effectuer une conversion 
analogique-numérique. Le déroulement spécifique est le suivant :

.. code-block:: c

    digitalWrite(ADC_CS, 0);

Réglez CS sur niveau bas pour commencer l'activation de la conversion AD.

.. code-block:: c

    // Bit de démarrage
    digitalWrite(ADC_CLK,0);
    digitalWrite(ADC_DIO,1);    delayMicroseconds(2);
    digitalWrite(ADC_CLK,1);    delayMicroseconds(2);

Lorsque la première transition de l'entrée d'horloge de bas en haut se produit, 
réglez DIO sur 1 en tant que bit de démarrage. Dans les trois étapes suivantes, 
il y a trois mots d'affectation.

.. code-block:: c

    // Mode Single End
    digitalWrite(ADC_CLK,0);
    digitalWrite(ADC_DIO,1);    delayMicroseconds(2);
    digitalWrite(ADC_CLK,1);    delayMicroseconds(2);

Lors de la deuxième transition de l'horloge, réglez DIO sur 1 pour choisir le 
mode Single End.

.. code-block:: c

    // Impair
    digitalWrite(ADC_CLK,0);
    digitalWrite(ADC_DIO,odd);  delayMicroseconds(2);
    digitalWrite(ADC_CLK,1);    delayMicroseconds(2);

Pour la troisième transition, la valeur de DIO est contrôlée par la variable **odd**.

.. code-block:: c

    // Sélection
    digitalWrite(ADC_CLK,0);
    digitalWrite(ADC_DIO,sel);    delayMicroseconds(2);
    digitalWrite(ADC_CLK,1);

À la quatrième transition de l'horloge, la valeur de DIO est contrôlée par la 
variable **sel**.

Si channel=0, sel=0, odd=0, les formules opératoires concernant **sel** et **odd** 
sont les suivantes :

.. code-block:: c

    int sel = channel > 1 & 1;
    int odd = channel & 1;

Lorsque channel=1, sel=0, odd=1, reportez-vous à la table de logique de contrôle 
de l'adresse ci-dessous. Ici, CH1 est sélectionné et le bit de démarrage est 
transféré à l'emplacement de démarrage du registre multiplexeur et la conversion commence.

.. image:: img/image313.png


.. code-block:: c

    digitalWrite(ADC_DIO,1);    delayMicroseconds(2);
    digitalWrite(ADC_CLK,0);
    digitalWrite(ADC_DIO,1);    delayMicroseconds(2);

Ici, DIO est réglé deux fois sur 1, cela peut être ignoré.

.. code-block:: c

    for(i=0;i<8;i++)
        {
            digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
            digitalWrite(ADC_CLK,0);    delayMicroseconds(2);

            pinMode(ADC_DIO, INPUT);
            dat1=dat1<<1 | digitalRead(ADC_DIO);
        }

Dans la première boucle for(), dès que le cinquième signal d'horloge passe de haut à 
bas, DIO est réglé en mode entrée. La conversion commence alors et la valeur convertie 
est stockée dans la variable dat1. Après huit périodes d'horloge, la conversion est terminée.

.. code-block:: c

    for(i=0;i<8;i++)
        {
            dat2 = dat2 | ((uchar)(digitalRead(ADC_DIO))<<i);
            digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
            digitalWrite(ADC_CLK,0);    delayMicroseconds(2);
        }

Dans la deuxième boucle for(), les valeurs converties sont sorties via DO après huit 
autres périodes d'horloge et stockées dans la variable dat2.

.. code-block:: c

    digitalWrite(ADC_CS,1);
    pinMode(ADC_DIO, OUTPUT);
    return(dat1==dat2) ? dat1 : 0;

return(dat1==dat2) ? dat1 : 0 permet de comparer la valeur obtenue pendant la 
conversion et la valeur de sortie. Si elles sont égales, la valeur convertie 
dat1 est renvoyée ; sinon, 0 est renvoyé. Ici, le processus de conversion de 
l'ADC0834 est terminé.

.. code-block:: c

    softPwmCreate(LedPin,  0, 100);

La fonction utilise un PWM logiciel pour créer une broche PWM, LedPin, 
avec une largeur d'impulsion initiale de 0 et une période de PWM de 100 x 100 µs.

.. code-block:: c

    while(1){
            analogVal = get_ADC_Result(0);
            printf("Current analogVal : %d\n", analogVal);
            softPwmWrite(LedPin, analogVal);
            delay(100);
        }

Dans le programme principal, la valeur de la chaîne 0, connectée à un potentiomètre, 
est lue et stockée dans la variable analogVal, puis écrite dans LedPin. Vous pouvez 
alors observer la variation de la luminosité de la LED en fonction de la valeur du 
potentiomètre.

Pour les utilisateurs Python
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

**Étape 2 :** Ouvrez le fichier de code

.. raw:: html

   <run></run>

.. code-block::

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

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

.. raw:: html

   <run></run>

.. code-block::

    sudo python3 2.1.4_Potentiometer.py

Après l'exécution du code, tournez le bouton du potentiomètre, l'intensité de la 
LED changera en conséquence.

**Code**

.. note::

    Vous pouvez **Modifier/Réinitialiser/Copier/Exécuter/Arrêter** le code ci-dessous. Mais avant cela, vous devez aller au chemin source du code comme ``davinci-kit-for-raspberry-pi/python``.
    
.. raw:: html

    <run></run>

.. code-block:: python

    import RPi.GPIO as GPIO
    import ADC0834
    import time

    LedPin = 22

    def setup():
        global led_val
        # Configurer le mode GPIO en numérotation BCM
        GPIO.setmode(GPIO.BCM)
        # Configurer le mode LedPin en sortie avec un niveau initial élevé (3,3V)
        GPIO.setup(LedPin, GPIO.OUT, initial=GPIO.HIGH)
        ADC0834.setup()
        # Configurer la LED comme canal PWM avec une fréquence de 2kHz
        led_val = GPIO.PWM(LedPin, 2000)
        # Démarrer avec une valeur initiale de 0
        led_val.start(0)

    def destroy():
        # Arrêter tous les canaux PWM
        led_val.stop()
        # Libérer les ressources
        GPIO.cleanup()

    def loop():
        while True:
            analogVal = ADC0834.getResult()
            print ('analog value = %d' % analogVal)
            led_val.ChangeDutyCycle(analogVal*100/255)
            time.sleep(0.2)
    if __name__ == '__main__':
        setup()
        try:
            loop()
        except KeyboardInterrupt: # Lorsque 'Ctrl+C' est appuyé, la fonction destroy() est exécutée.
            destroy()

**Explication du code**

.. code-block:: python

    import ADC0834

Importer la bibliothèque ADC0834. Vous pouvez vérifier le contenu de la bibliothèque 
en appelant la commande `nano ADC0834.py`.

.. code-block:: python

    def setup():
        global led_val
        # Configurer le mode GPIO en numérotation BCM
        GPIO.setmode(GPIO.BCM)
        # Configurer le mode LedPin en sortie avec un niveau initial élevé (3,3V)
        GPIO.setup(LedPin, GPIO.OUT, initial=GPIO.HIGH)
        ADC0834.setup()
        # Configurer la LED comme canal PWM avec une fréquence de 2kHz
        led_val = GPIO.PWM(LedPin, 2000)

        # Démarrer avec une valeur initiale de 0
        led_val.start(0)

Dans la fonction setup(), définissez le mode BCM pour la numérotation, configurez 
LedPin comme canal PWM et réglez la fréquence à 2 kHz.

**ADC0834.setup() :** Initialise l'ADC0834 et connecte les broches définies CS, CLK, 
DIO de l'ADC0834 aux GPIO17, GPIO18 et GPIO27 respectivement.

.. code-block:: python

    def loop():
        while True:
            res = ADC0834.getResult()
            print ('res = %d' % res)
            R_val = MAP(res, 0, 255, 0, 100)
            led_val.ChangeDutyCycle(R_val)
            time.sleep(0.2)

La fonction getResult() est utilisée pour lire les valeurs analogiques des quatre 
canaux de l'ADC0834. Par défaut, elle lit la valeur du canal CH0. Pour lire les 
autres canaux, entrez le numéro du canal dans les parenthèses, par exemple **getResult(1)**.

La fonction loop() lit d'abord la valeur de CH0 et l'assigne à la variable **res**. 
Ensuite, la fonction MAP est appelée pour mapper la valeur lue du potentiomètre entre 
0 et 100. Cette étape permet de contrôler le cycle de travail de LedPin. Vous verrez 
alors la luminosité de la LED varier en fonction de la valeur du potentiomètre.




Image du phénomène
-----------------------

.. image:: img/image181.jpeg

