Comment récupérer un signal analogique ?

NIVEAU 1

Objectifs

  • Configurer et utiliser les entrées analogiques de la carte Nucléo
  • Mesurer une tension analogique

Pré-requis

Convertisseur analogique/numérique

Sur les systèmes numériques, et les microcontrôleurs en particulier, les broches sont naturellement des entrées/sorties numériques.
Or, la plupart des signaux qui nous entourent et que l’on cherche à mesurer (luminosité, température, vitesse…) sont des grandeurs analogiques. Pour palier à ce problème, la plupart des fabricants de microcontrôleurs ont intégré des convertisseurs analogiques-numériques (ADC – Analog to Digital Converter) à leur système, afin d’éviter de passer par des composants externes.

Les cartes Nucleo L476RG possèdent 3 convertisseurs analogiques numériques de 12 bits (c’est à dire convertissant des tensions allant de 0 à 3.3V sur 4096 niveaux différents). Chacun de ses convertisseurs peut échantillonner un signal jusqu’à 5 MHz.

ATTENTION Les cartes Nucléo ne peuvent convertir que des tensions comprises entre 0 et 3.3V !!

Entrées analogiques

Certaines broches du composant (notée AnalogIn sur les connecteurs de la carte) peuvent être reliées à ce convertisseur analogique-numérique.

Déclaration

L’ensemble des classes et des fonctions permettant de réaliser des opérations sur les entrées/sorties de la carte se trouvent dans la bibliothèque “mbed.h” (ou “mbed-os.h”). Il est donc indispensable d’avoir au préalable inclut cette bibliothèque :

#include "mbed.h"

La première étape est la déclaration au compilateur de cette broche en entrée analogique. Il faut la placer après la déclaration des ressources externes (bibliothèques) et avant toute définition de fonction (voir tutoriel Tester ma première application sur Nucléo – Code d’exemple /* Déclaration des entrées/sorties */).

AnalogIn myInput(PC_2);

Dans l’exemple précédent, on configure la broche PC_2 (du connecteur Morpho) en entrée analogique (ou analog en anglais). Dans ce code, il y a trois notions importantes :

  • AnalogIn‘, la classe qui définit le type de la broche, ici une entrée analogique
  • myInput‘, le nom de la variable qui va être associée au port donné dans les parenthèses
  • PC_2‘, le nom de la broche que l’on va associer sur le composant

Lecture d’une donnée analogique

L’intérêt d’utiliser une entrée analogique est de pouvoir récupérer une information analogique provenant de l’extérieur dans son programme (par exemple la sortie d’un capteur).

Il existe deux façons différentes de récupérer une valeur analogique :

  • la fonction float read() qui représente la tension d’entrée par un nombre réel compris entre 0.0 et 1.0 (représentant une fraction de la tension réellement appliquée sur l’entrée analogique)
  • la fonction int read_u16() qui représente la tension d’entrée par un entier non signé sur 16 bits (seuls les 12 bits de poids fort sont utilisés sur les 16 bits, pour stocker le résultat de la conversion sur les cartes L476RG)

Lecture avec read()

Dans l’exemple ci-dessous, nous utilisons la conversion à l’aide de la fonction read().

#include "mbed.h"

AnalogIn analog_in(A0);

DigitalOut led(LED1);

int main()
{
    double meas, tension;

    while(1) {
        meas = analog_in.read(); // Convertit et lit la tension d'entée analogique (valeur entre 0.0 et 1.0)
        tension = meas * 3.3; // Change la valeur pour être entre 0.0 et 3.3 (qui correspond à 3.3V)
        if (tension > 0.5) { // Si la valeur est supérieure à 0.5V, alors on allume la LED
            led = 1;
        } else {          // Sinon on l'éteint
            led = 0;
        }
    }
}

Dans l’exemple précédent, on stocke dans la variable meas le résultat de la conversion sous forme d’un nombre réel compris entre 0 et 1. A la seconde ligne, on multiplie par 3.3 afin d’obtenir un nouveau nombre réel nommé tension égale à une tension comprise entre 0 et 3.3V, image de la tension présente sur la broche A0.

Dans la suite, on teste si cette tension est supérieure à 0.5V : si oui, on met à ‘1’ la sortie led, sinon on met à ‘0’ la sortie led.

Lecture avec read_u16()

Dans l’exemple ci-dessous, nous utilisons la conversion à l’aide de la fonction read_u16().

#include "mbed.h"

AnalogIn analog_in(A0);

DigitalOut led(LED1);

int main()
{
    int meas;
    double tension;

    while(1) {
        meas = analog_in.read_u16(); // Convertit et lit la tension d'entée analogique (valeur entre 0 et 65535)
        tension = meas / 65535 * 3.3;   // Conversion en tension
        if (tension > 0.5) { // Si la valeur est supérieure à 0.5V, alors on allume la LED
            led = 1;
        } else {          // Sinon on l'éteint
            led = 0;
        }
    }
}

Dans ce nouvel exemple, on stocke dans la variable meas le résultat de la conversion sous forme d’un nombre entier compris entre 0 et 65535 (sur 16 bits). A la seconde ligne, on divise la valeur obtenu par \((2^{16}- 1)\) et on multiplie par 3.3 afin d’obtenir un nombre réel nommé tension égale à une tension comprise entre 0 et 3.3V, image de la tension présente sur la broche A0.

Dans la suite, on teste si cette tension est supérieure à 0.5V : si oui, on met à ‘1’ la sortie led, sinon on met à ‘0’ la sortie led.

Attention Le résultat brut acquis par le convertisseur est sur 12 bits (cas de la carte Nucleo L476RG). Le résultat est justifié à gauche sur l’entier fourni par la fonction read_u16(), ce qui signifie que les 4 bits de poids faible sont toujours à 0.

On peut représenter l’information de la façon suivante :

Pour obtenir la valeur sur 12 bits retournée par l’ADC à partir de la valeur transmise par la fonction read_u16, il faut effectuer un décalage de l’information de 4 bits vers la droite :

int valeur_ADC;    // valeur entre 0 et 4095 (12 bits)
int valeur_transmise = analog_in.read_u16();
valeur_ADC = valeur_transmise >> 4;

Affichage de la donnée analogique

Pour afficher l’information analogique convertie par les fonctions précédentes, on peut utiliser une variable interne et l’envoyer par une liaison série vers l’ordinateur pour l’afficher (voir tutoriel Débogage / Console Série) sur l’écran à intervalle régulier.

On peut alors utiliser le programme suivant :

#include "mbed.h"

AnalogIn entree_analog(A0);
Serial pc(USBTX, USBRX);

int main()
{
    pc.baud(115200);
    int meas_int;
    double tension;

    while(1) {
        meas_int = entree_analog.read_u16();  // sur 12 bits MSB
        pc.printf("Tension = %d \n", meas_int);
        tension = meas_int / 65536.0 * 3.3;     // en V
        pc.printf("Tension = %lf V \n", tension);
        wait(1.0);
    }
}

Ce programme va récupérer les valeurs sur l’entrée analogique A0 (connecteur Arduino), transformer l’information pour obtenir une tension en Volt et l’envoyer sur la liaison série de deux façons : la valeur brute (sur 12 bits positionnés en poids fort d’une variable entière sur 16 bits) et la valeur convertie en Volt.

Tester une entrée analogique

Pour pouvoir tester si l’entrée analogique est opérationnelle, on peut utiliser (au moins) deux méthodes que nous allons détailler par la suite.

A l’aide d’une source de tension

La première solution est d’utiliser une source de tension continue réglable. En modifiant la tension de sortie de cette alimentation, on pourra alors vérifier le bon fonctionnement du code précédent.

ATTENTION Avant de connecter la sortie de l’alimentation stabilisée sur l’entrée analogique de la carte, vérifiez bien :

  1. que la masse de la carte Nucléo est bien reliée à la masse du générateur de tension
  2. que la sortie de l’alimentation stabilisée ne dépasse pas 3.3V

Dans les deux cas, la carte Nucléo peut être endommagée.

A l’aide d’un potentiomètre

Si vous ne savez pas ce qu’est un potentiomètre ou comment le cabler, vous pouvez vous rendre sur le tutoriel suivante : Cabler un potentiomètre

Câblage d’un potentiomètre avec une carte Nucléo

La carte Nucléo possède déjà une alimentation stabilisée de 3.3V, accessible sur le connecteur Arduino sous le nom 3V3. On peut alors relier un potentiomètre de la façon suivante pour obtenir une tension variable à sa sortie entre 0 et 3.3V.

Tutoriel lié

MInE Prototyper Prototyper avec Nucleo et MBED

Nucleo – Récupérer un signal analogique