.. note::

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

    **Pourquoi nous rejoindre ?**

    - **Support d'experts** : Résolvez vos problèmes après-vente et relevez des défis techniques avec l'aide de notre communauté et de notre équipe.
    - **Apprendre & Partager** : Échangez des conseils et des tutoriels pour améliorer vos compétences.
    - **Aperçus exclusifs** : Accédez en avant-première aux nouvelles annonces de produits et aux avant-premières.
    - **Réductions spéciales** : Profitez de remises exclusives sur nos nouveaux produits.
    - **Promotions festives et cadeaux** : Participez à des tirages au sort et à des promotions spéciales pour les fêtes.

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

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. Ici, nous mettons en œuvre ce processus à l'aide d'un potentiomètre. 
Le potentiomètre modifie la grandeur physique — la tension — qui est 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 de type 
`approximation successive <https://cn.bing.com/dict/search?q=successive approximations&FORM=BDVSP6&mkt=zh-cn>`__ 
équipé d'un multiplexeur multicanal configurable en entrée et d'une interface d'entrée/sortie série. L'interface série est 
conçue pour interagir avec des registres à décalage standard ou des microprocesseurs.

.. image:: img/image309.png


**Séquence d'opération**

Une conversion est lancée en mettant CS à un niveau bas, ce qui active tous les 
circuits logiques. CS doit être maintenu bas pendant toute la durée du processus 
de conversion. Une horloge d'entrée est alors envoyée par le processeur. À chaque 
transition de l'horloge de bas en haut, les données sur DI sont horodatées dans le 
registre de décalage d'adressage du multiplexeur. Le premier niveau logique haut 
est le bit de départ. Un mot d'affectation de 3 à 4 bits suit ce bit de départ. À 
chaque transition de l'horloge de bas en haut, le bit de départ et le mot d'affectation 
sont décalés dans le registre de décalage. Lorsque le bit de départ atteint la position 
de démarrage du registre du multiplexeur, le canal d'entrée est sélectionné et la 
conversion commence. La sortie de statut du SAR (SARS) passe à un niveau haut pour 
indiquer qu'une conversion est en cours, et DI est désactivé pendant toute la durée 
de la conversion.

Une période d'horloge est automatiquement insérée pour permettre au canal multiplexé 
sélectionné de se stabiliser. La sortie de données DO quitte l'état haute impédance 
et fournit un niveau bas initial pour cette période d'horloge de stabilisation. Le 
comparateur du SAR compare successivement les sorties de l'échelle résistive avec le 
signal analogique d'entrée. 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 avance, les données de conversion sont simultanément sorties par 
la broche de sortie DO, avec le bit de poids fort (MSB) en premier.

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 émises en ordre du bit de poids faible après 
la séquence MSB en premier.

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


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

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


**Potentiomètre**

Le potentiomètre est un composant résistif à trois bornes dont la valeur de résistance 
peut être ajustée selon une variation régulière. Il se compose généralement d'une 
résistance et d'une brosse mobile. Lorsque la brosse se déplace le long de la résistance, 
une certaine résistance ou tension de sortie 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. Fonction de diviseur de tension.

Le potentiomètre est une résistance réglable en continu. Lorsque vous ajustez l'axe ou 
la poignée de glissement du potentiomètre, le contact mobile se déplace sur la résistance. 
À ce moment, une tension peut être émise en fonction de la tension appliquée sur le 
potentiomètre et de l'angle ou de la distance parcourue par le bras mobile.

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

.. image:: img/image311.png


.. image:: img/image312.png


Procédures expérimentales
-------------------------

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

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

.. note::
    Veuillez placer la puce en vous référant à la position correspondante indiquée 
    sur l'image. Notez que les encoches de la puce doivent être à gauche lorsqu'elle 
    est positionnée.

**É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 le programme.

.. raw:: html

   <run></run>

.. code-block::

    sudo ./a.out

Après l'exécution du code, 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 s'il y a un message d'erreur 
    indiquant : \"wiringPi.h: No such file or directory\", 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 (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;
    }

    int main(void)
    {
        uchar analogVal;
        if(wiringPiSetup() == -1){ // lorsque l'initialisation de wiringPi échoue, afficher un message à l'écran
            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éfinit les broches CS, CLK et DIO de l'ADC0834, connectées respectivement 
à GPIO0, GPIO1 et GPIO2. Puis, la LED est attachée à 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);
        // ODD (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;
    }

Cette fonction de l'ADC0834 effectue la conversion analogique-numérique (ADC). 
Le flux de travail détaillé est le suivant :

.. code-block:: c

    digitalWrite(ADC_CS, 0);

Met CS à un niveau bas pour commencer à activer la conversion analogique-numérique.

.. code-block:: c

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

Lors de la première transition du signal d'horloge de bas à haut, DIO est mis à 1 comme bit de démarrage. Au cours des trois étapes suivantes, 3 bits d'affectation sont envoyés.

.. 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 bas à haut du signal d'horloge, DIO est à nouveau défini à 1, ce qui active le mode Single End.

.. code-block:: c

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

Lorsque cette opération se produit pour la troisième fois, la valeur de DIO est déterminée par la variable **odd**.

.. code-block:: c

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

Lors du quatrième changement de niveau du signal d'horloge de bas à haut, 
la valeur de DIO est déterminée par la variable **sel**.

Lorsque channel=0, sel=0, odd=0, les formules de calcul pour **sel** et **odd** 
sont les suivantes :

.. code-block:: c

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

Pour la condition channel=1, sel=0, odd=1, référez-vous au tableau de la 
logique de contrôle d'adresse ci-dessous. Ici, CH1 est sélectionné, et le 
bit de démarrage est décalé dans la position de départ du registre du 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 mis à 1 deux fois, cette opération peut être ignorée.

.. 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 changement de niveau du 
signal CLK de haut à bas se produit, DIO est défini en mode entrée. La conversion 
commence alors, et la valeur convertie est stockée dans la variable dat1. Après 
huit cycles 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 envoyées via DO 
après huit autres cycles 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 est utilisé pour comparer la valeur obtenue 
pendant la conversion avec la valeur de sortie. Si elles sont égales, la 
valeur convertie dat1 est retournée, sinon la valeur retournée est 0. Ici, 
le flux de travail de l'ADC0834 est terminé.

.. code-block:: c

    softPwmCreate(LedPin,  0, 100);

Cette fonction permet de créer par logiciel une broche PWM, LedPin. La largeur 
d'impulsion initiale est fixée à 0, et la période du signal PWM est définie à 100 x 100 us.

.. 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 du canal 0, qui est connecté à un 
potentiomètre, est lue et stockée dans la variable analogVal, puis elle 
est écrite dans LedPin. Vous pouvez ainsi observer la variation de la 
luminosité de la LED en fonction de la valeur du potentiomètre.

