La conversion analogique-numérique avec Raspberry Pi

Acquisition de température avec un capteur analogique et visualisation des données

Le Raspberry Pi ne possède pas de port analogique. Dans ce tutoriel, vous allez apprendre à exploiter un convertisseur analogique-numérique tel le MCP3208 interfacé avec le Raspberry Pi. Comme exemple d'application, on propose un programme en C d'acquisition de température provenant d'un capteur analogique (LM335).

Les points abordés dans ce tutoriel sont les suivants :

  • Caractéristique de transfert du convertisseur analogique-numérique.
  • Principe de la conversion analogique-numérique par approximations successives.
  • Communication par liaison série SPI (Serial Peripheral Interface).
  • Prototypage de la chaîne d'acquisition.
  • Programmation du port GPIO en langage C et la bibliothèque bcm2835.
  • Création d'un tableau de bord de visualisation des données de température en temps réel dans un navigateur avec Node-RED.

4 commentaires Donner une note à l'article (5)

Article lu   fois.

L'auteur

Profil Pro

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. Objectif

L'objectif est d'acquérir une tension aux bornes d'un capteur de température analogique (LM335) en interfaçant un convertisseur analogique-numérique externe (Microchip MCP3208) au Raspberry Pi. Le programme d'acquisition sera réalisé en langage C accompagné de la bibliothèque bcm2835 (le bcm2835 étant le processeur Broadcom dont sont équipés les Raspberry Pi modèles A, B, B+ et Zero). Les données seront visualisées en temps réel dans un navigateur grâce à l'outil Node-RED.

Image non disponible
Image non disponible
Tableau de bord avec jauge et courbe de température visualisé en temps réel dans un navigateur web grâce à Node-RED

II. Matériel requis

Matériels

Remarques

  • Raspberry Pi
Image non disponible
  • Capteur de température analogique LM335 ou 335A (boîtier TO-92)
Image non disponible
  • Ce capteur se comporte comme une diode Zener avec une tension de claquage directement proportionnelle à la température en Kelvin (10 mV/°K). Correctement calibré à 25 °C, sa précision est inférieure au 1 °C sur une plage de température de plus de 100 °C (gamme de mesure entre -40 et +100 °C). Prix constaté : 1-2 €.
  • Convertisseur analogique-numérique MCP3208 (boîtier PDIP 16 broches) de Microchip
Image non disponible

ou

Image non disponible
  • Le MCP3208 est un convertisseur analogique-numérique à interface SPI comportant 8 entrées analogiques avec une résolution de 12 bits. Il s'interface aisément avec tout microcontrôleur et même le Raspberry Pi. Prix constaté : 4-5 €.
  • Le composant principal du HAT(1) du constructeur Nation Electronics est justement un MCP3208. Comme tout HAT qui se respecte, celui-ci vous facilitera la tâche… mais cela a un coût ! Prix constructeur : 19,95 $ à ce jour (sans les frais de port).
  • Plaque de câblage rapide, fils de connexion (mâle-mâle et mâle-femelle)

    Image non disponible
  • Résistances électriques, potentiomètre 10k
Image non disponible
  • Tous ces petits matériels, qui font partie de l'attirail de l'apprenti maker, peuvent être trouvés facilement chez un revendeur de matériel électronique ou dans des kits d'électronique pour débutant.

  • Analyseur logique USB
Image non disponible
  • On peut s'en passer ici, mais ce dispositif reste un bon compagnon pour le diagnostic et l'analyse des signaux logiques. Vous trouverez facilement des analyseurs logiques USB à bas coûts (env. 15 € pour un analyseur 8 canaux, 24 MHz) qui conviendront parfaitement pour décoder les trames série UART, I2C, SPI…

III. Fonctionnement du convertisseur analogique-numérique MCP3208

Un signal analogique est un signal qui varie de façon continue, comme la température d'un lieu au cours du temps, alors qu'un signal numérique varie de façon discrète dans le temps.

Un convertisseur analogique-numérique (ou en anglais ADC pour Analog to Digital Converter) est un dispositif électronique dont la fonction est de traduire une tension analogique VE en une valeur numérique N codée sur n bits.

Image non disponible
Par Jacques.boudier — Travail personnel, CC BY-SA 3.0

Transformé en une succession de 0 et de 1, le signal peut être plus facilement transporté, stocké et traité par l'informatique, mais le signal quantifié présente des échelettes qui traduisent la perte d'information lors du passage dans le numérique :

Image non disponible
Quantification d'un signal analogique sur 2 bits (4 valeurs). Graphique du bas : différence entre les deux signaux du graphique du haut (l'accumulation des erreurs de quantification représente le bruit). https://commons.wikimedia.org/w/index.php?curid=19228529

III-A. Caractéristique de transfert

La figure ci-dessous montre la caractéristique de transfert d'un convertisseur analogique-numérique 3 bits. La plage de tension (VREF = tension de référence, la tension maximale admissible en entrée du convertisseur) est divisée en plages d'égales dimensions et de largeur q. Il y a autant de plages que de valeurs possibles de la sortie numérique (c.-à-d. ici 23=8 valeurs). On peut ainsi associer une valeur numérique à chaque plage et former des paliers :

Image non disponible
Caractéristique de transfert d'un convertisseur analogique-numérique 3 bits

La largeur q de ces paliers (le pas de quantification), parfois appelée quantum, définit la résolution en tension du convertisseur :

kitxmlcodelatexdvpq= \frac{V_{REF}}{2^{n}}finkitxmlcodelatexdvp

Plus q est petit, plus l'« effet d'escalier » dû à la quantification s'estompe, et la caractéristique de transfert s'approche de la caractéristique de transfert idéale en rouge.

Par convention, la caractéristique de transfert est décalée d'un demi-quantum pour réduire l'erreur de quantification en valeur absolue (±1/2.q, sauf pour le dernier palier).

Image non disponible
Quantification linéaire centrée

Ainsi, le quantum pour le MCP3208 de résolution 12 bits avec une tension de référence de 3,3 V est :

kitxmlcodelatexdvpq= \frac{3,3}{2^{12}}=\frac{3,3}{4096}=0,0008 \, V< 1 \, mVfinkitxmlcodelatexdvp

Outre les erreurs de quantification dues à la résolution du convertisseur, les convertisseurs analogique-numérique présentent d'autres défauts identifiés qui font dévier ses caractéristiques de la droite caractéristique idéale.

Image non disponible
Principaux défauts statiques d'un convertisseur analogique-numérique. Erreur de gain, de décalage, de non-linéarité, de code manquant… Source : http://www.industrial-electronics.com/DAQ/IOT-2-ADC.html

Ces erreurs sont généralement exprimées en multiple du quantum (quantum noté LSB Least Significant Bit dans les documentations, car le quantum est la plus petite variation en volts correspondant au changement du bit de poids faible).

Par exemple, l'erreur de non-linéarité différentielle (ou DNL pour Differential Nonlinearity) est l'écart entre la largeur réelle du palier et la largeur idéale (de taille égale à la valeur du quantum). Si la largeur réelle est égale au quantum, l'erreur DNL est nulle, et toute largeur qui s'écarte du quantum donne lieu à une erreur DNL.

Image non disponible
Image Maxim Integrated : en bas, la largeur du palier bleu est égale à 2xLSB, soit l'erreur DNL=+1xLSB.

Pour plus de détails :

Image non disponible
Caractéristiques statiques du MCP3208 - extrait datasheet

L'erreur totale ne s'obtient pas en faisant le cumul de toutes les erreurs (mais elle peut être la somme de plusieurs types d'erreurs) ! En général, l'erreur de décalage (offset) et l'erreur de gain peuvent être annulées ou compensées par logiciel. L'erreur de non-linéarité intégrale (INL) qui est l'image des cumuls des erreurs DNL sur la plage de tension donne alors une bonne estimation de l'erreur maximale. Pour limiter les effets de non-linéarité, on peut faire la moyenne sur plusieurs conversions.

Il y a d'autres sources d'erreurs qui n'ont pas été évoquées et qui peuvent influer sur la précision de la conversion : bruit d'alimentation, qualité de la régulation, impédance d'entrée, bruit électromagnétique…

III-B. Principe de la conversion analogique-numérique par approximations successives

Le schéma bloc fonctionnel du MCP3208 tel qu'on le trouve dans la documentation constructeur (datasheet) est le suivant :

Image non disponible

La structure est celle d'un convertisseur fonctionnant par approximations successives.

Lorsque le mode single-ended est choisi (une voie d'entrée, la tension mesurée étant référencée à la masse), le multiplexeur en entrée (Input Channel Mux) sélectionne l'entrée choisie parmi CH0 à CH7. La tension d'entrée échantillonnée et bloquée (Sample and Hold) constitue une des deux entrées du comparateur (Comparator). Le rôle de l'échantillonneur-bloqueur est d'acquérir une valeur de tension à l'entrée du convertisseur à un instant donné. Il doit également maintenir la tension acquise stable pendant la durée de la conversion. L'autre entrée du comparateur provient du convertisseur numérique-analogique (DAC pour Digital to Analogic Converter) dont l'entrée est fournie par le registre 12 bits d'« approximations successives » (SAR pour Successive Approximation Register). Le rôle du DAC est de produire une tension analogique en fonction de la valeur contenue dans ce registre 12 bits selon la formule :

kitxmlcodelatexdvp\text{tension analogique} = \frac{\text{valeur SAR}}{2^{12} - 1} \cdot V_{REF}finkitxmlcodelatexdvp

Si on prend VREF = VDD = 3,3 V, on a par exemple :

Valeur SAR

Tension analogique DAC

211 = 2048 = 0b1000 0000 0000

(2048/4095) x 3,3 = 1,65 V

210 = 1024 = 0b0100 0000 0000

(1024/4095) x 3,3 = 0,83 V

29 = 512 = 0b0010 0000 0000

(512/4095) x 3,3 = 0,41 V

28 = 256 = 0b0001 0000 0000

(256/4095) x 3,3 = 0,21 V

20 = 1 = 0b0000 0000 0001

(1/4095) x 3,3 = 0,0008 V

Maintenant, supposez que la tension échantillonnée et bloquée sur une des entrées CHx vaut 2,02 V. L'algorithme par approximations successives réalisera les étapes suivantes à chaque coup d'horloge CLK :

  • Premièrement, le SAR est initialisé à zéro.
  • Le bit 11 de poids fort du SAR est mis à 1, la tension produite en sortie du DAC est donc de 1,65 V (50 % de VREF). Cette tension est ensuite comparée avec celle de l'entrée CHx. Comme 2,02 est supérieur à 1,65 ; le signal en sortie du comparateur est à l'état haut et le bit 11 du SAR est maintenu à 1 : SAR = 0b1000 0000 0000.
  • Le bit 10 du SAR est mis à 1, c'est-à-dire 0b1100 0000 0000 = 3072, soit une tension produite par le DAC de 2,48 V (75 % de VREF). Cette fois, l'entrée (2,02 V) est inférieure à 2,48 V ; le signal en sortie du comparateur bascule à l'état bas et le bit 10 du SAR rebascule à 0 : SAR = 0b1000 0000 0000. On sait à cet instant que la tension sur l'entrée CHx est comprise entre 50 % et 75 % de la tension de référence VREF.
  • Le bit 9 du SAR est mis à 1, c'est-à-dire 0b1010 0000 000 = 2560, soit une tension produite par le DAC de 2,06 V (62,5 % de VREF). L'entrée (2,02 V) est inférieure à 2,06 V ; le signal en sortie du comparateur est à l'état bas et le bit 9 du SAR rebascule à 0 : SAR = 0b1000 0000 0000. On sait à cet instant que la tension sur l'entrée CHx est comprise entre 50 % et 62,5 % de la tension de référence VREF.
  • Le bit 8 du SAR est mis à 1, c'est-à-dire 0b1001 0000 000 = 2304, soit une tension produite par le DAC de 1,86 V (56,3 % de VREF). L'entrée (2,02 V) est supérieure à 1,86 V ; le signal en sortie du comparateur est à l'état haut et le bit 8 du SAR est maintenu à 1 : SAR = 0b1001 0000 0000. On sait à cet instant que la tension sur l'entrée CHx est comprise entre 56,3 % et 62,5 % de la tension de référence VREF.
  • Etc. À chaque nouveau coup d'horloge, l'intervalle de recherche est divisé par deux.

Une fois que le dernier bit 0 du SAR est testé, l'algorithme se termine. À ce moment, on pourra vérifier que le SAR vaut 0b1001 1100 1010 = 2506, soit une tension produite par le DAC égale à (2506/4095) x 3,3 = 2,0195 V, valeur constituant une très bonne approximation des 2,2 V en entrée.

Cette dernière valeur du SAR est alors envoyée bit par bit sur l'interface SPI.

Image non disponible
Valeur du SAR obtenue par approximations successives (VE=2,02V, VREF=3,3V et n=12 bits). À la dernière étape, SAR=2506.

III-C. Liaison série SPI

III-C-1. Généralités

Dans les systèmes à base de microcontrôleurs, les échanges de données entre les composants se font maintenant le plus souvent avec des bus série.

Dans le cas particulier du MCP3208, la communication série de données numériques entre le Pi et le MCP3208 doit permettre de :

  • configurer les entrées analogiques ;
  • démarrer une conversion ;
  • récupérer la valeur numérique après conversion.

Le bus série SPI (Synchronous Peripheral Interface) a été initialement développé par Motorola. D'autres fabricants (Microchip, Atmel, Texas Instruments, etc.) ont adopté ce type de liaison et de nombreux composants communiquant en SPI sont apparus (mémoires, horloges temps réels, convertisseurs analogique-numérique, numérique-analogique, capteurs divers…). En général, la mise en œuvre du bus SPI ne pose pas de problèmes, mais avec la multiplicité des modes de fonctionnement (fréquence, polarisation, phase de l'horloge…), et le manque de standardisation ou de spécifications techniques claires, on peut rencontrer des difficultés.

Quelques caractéristiques du bus SPI :

  • Bus synchrone série à haut débit, multipoint (un maître et un ou plusieurs esclaves).
  • Protocole simple. Pas d'adressage (mais sélection de l'esclave).
  • Transmission à courte distance en full duplex sur deux lignes unidirectionnelles.
  • Pas de contrôle physique de transmission des données.

Les échanges de données avec un microcontrôleur se font généralement octet par octet. La transmission s'effectue sur deux fils unidirectionnels nommés MOSI (Master Output Slave Input) et MISO (Master Input Slave Output).

Une horloge indépendante (fil SCLK pour Serial Clock) fixée par le maître synchronise les échanges (en général sur front de l'horloge). La fréquence de l'horloge peut aller jusqu'à 20 MHz, voire plus selon les performances des circuits reliés au bus.

Il n'y a pas d'adressage des esclaves (comme sur un bus i2C par exemple). L'esclave devient actif au moyen d'une ligne de sélection dédiée (fil /SSx : Slave Select x ou /CEx : Chip Enable x, généralement actif à l'état bas).

Le bus est donc constitué de trois fils auxquels il faut ajouter les fils de sélection d'esclave.

Image non disponible
Liaison SPI avec un maître et trois esclaves - image Wikipédia
Image non disponible
Interface SPI sur le port GPIO du Raspberry Pi - GPIO 7, 8, 9, 10 et 11

Il faut imaginer la liaison SPI maître-esclave transmettant les données selon le principe du registre à décalage (shift register) :

Image non disponible

Une fois l'esclave sélectionné en abaissant sa ligne CEx, le transfert est possible et la communication est initiée par le basculement du signal d'horloge par le périphérique maître (ici, le Raspberry Pi). Sur front de l'horloge, le maître et l'esclave envoient chacun un bit sur leur ligne respective. Au bout de huit cycles d'horloge, un octet a été transféré du maître vers l'esclave, puis de l'esclave vers le maître (liaison full duplex). Cet échange simultané est souvent dissimulé par logiciel. Par exemple lorsque le maître veut envoyer des données vers l'esclave (opération d'écriture), les données retournées par l'esclave sont ignorées par le maître. Inversement, lors d'une opération de lecture des données envoyées par l'esclave, le maître envoie un octet nul qui sera ignoré par l'esclave. En fin de transmission avec l'esclave, sa ligne correspondante CEx doit être désactivée.

Deux bits de configuration définissent les modes de transmission du bus SPI. Ces deux bits sont nommés CPOL (Clock Polarity) et CPHA (Clock Phase). Il existe donc quatre modes de transmission différents. Pour une transmission correcte, il faut que les périphériques reliés au bus soient configurés selon le même mode.

  • CPOL détermine si au repos l'horloge est au niveau bas (CPOL=0) ou haut (CPOL=1).
  • CPHA détermine à quels fronts de l'horloge les données alignées sont échantillonnées et envoyées.

En général, les composants sont compatibles avec le Mode 0 qui constitue le mode par défaut (CPOL=0 et CPHA=0) :

Image non disponible
Mode 0 : l'horloge est à l'état bas au repos. Chaque bit aligné sur les lignes MOSI et MISO est échantillonné sur front montant de l'horloge. Sur front descendant, les bits sont mis à jour.

III-C-2. Test de la liaison SPI

Si vous avez un doute sur le fonctionnement matériel de la liaison SPI du Raspberry Pi, il existe un moyen de diagnostic en mode loopback. Dans ce mode de fonctionnement, les broches MOSI et MISO du Pi sont reliées entre elles puis on regarde si les données envoyées sur la ligne MOSI sont bien reçues à l'identique sur la ligne MISO.

La procédure est la suivante.

- Par défaut, le pilote Linux gérant la liaison SPI n'est probablement pas activé dans le noyau. Dans un terminal :

 
Sélectionnez
ls /dev/spidev*

ls: impossible d'accéder à /dev/spidev*: Aucun fichier ou dossier de ce type

Vous pouvez activer le pilote soit depuis le menu Préférences/Configuration du Raspberry Pi de l'interface graphique du bureau Raspbian, soit depuis l'utilitaire raspi-config. Une fois le pilote activé, les deux interfaces pour chaque broche de sélection CE0 et CE1 apparaissent :

 
Sélectionnez
ls /dev/spidev*

/dev/spidev0.0  /dev/spidev0.1

- Récupérez le programme de test spidev_test.c, puis compilez-le :

 
Sélectionnez
wget https://raw.githubusercontent.com/raspberrypi/linux/rpi-3.10.y/Documentation/spi/spidev_test.c

gcc -o spidev_test spidev_test.c

Ce programme de test envoie une séquence d'octets sur la ligne MOSI et affiche les octets reçus sur la ligne MISO.

Séquence d'octets
Sélectionnez
uint8_t tx[] = {
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0x40, 0x00, 0x00, 0x00, 0x00, 0x95,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0xDE, 0xAD, 0xBE, 0xEF, 0xBA, 0xAD,
        0xF0, 0x0D,
    };

Si vous lancez le test une première fois sans précaution, vous obtenez une série de zéros :

Image non disponible

Ce qui est normal dans un premier temps puisqu'il n'y a rien de connecté sur la ligne MISO.

- Dans un deuxième temps, avec un fil femelle-femelle, vous allez connecter la broche MOSI (GPIO 10, broche 19) à la broche MISO (GPIO 9, broche 21). Il est plus prudent de faire la connexion avec le Pi hors alimentation. Lancez à nouveau le programme de test :

Image non disponible

Cette fois, la séquence d'octets envoyés sur la ligne MOSI est bien réceptionnée sur la ligne MISO. La communication SPI s'effectue correctement, par contre ce test ne permet pas de vérifier le bon fonctionnement des lignes de sélection CE0 et CE1.

Source : Loopback test

Image non disponible
Observation à l'analyseur logique : envoi et réception de l'octet 0xAD avec le programme de test

III-C-3. Analyse d'une communication SPI avec le convertisseur MCP3208

L'extrait suivant de la datasheet du MCP3208 montre comment se présentent les données pour une transaction SPI, octet par octet avec une configuration en Mode 0 :

Image non disponible
Extrait datasheet du Microchip MCP3208

Les bits utiles (Start Bit, SGL/DIFF, D2, D1, D0, Null, puis B11 à B0) sont complétés avec cinq zéros en début de transmission pour former trois octets complets. Ce qui donne une transaction en 24 cycles d'horloge. N'oubliez pas que la transmission s'effectue en full duplex, les données sont émises et reçues simultanément.

Une fois le bit de Start transmis s'ensuivent quatre bits (Single/Diff, D2, D0 et D1) de configuration des entrées analogiques du MCP3208 :

Image non disponible
Extrait datasheet du Microchip MCP3208

En mode differential, on sélectionne la paire de voies d'entrée pour une mesure différentielle. En mode single-end, on sélectionne une voie d'entrée et la mesure de tension est référencée à la masse.

En C, les trois octets à transmettre seront préparés dans un tableau :

 
Sélectionnez
    unsigned char mcp3208_TransmittedData[]={    
        (1<<2)  | (input_mode<<1) | ((channel>>2) & 0x01),
        channel<<6,
        0x00 };

Le MCP3208 commence à échantillonner l'entrée analogique sur le quatrième front montant de l'horloge après le bit de Start. L'échantillonnage est terminé sur le cinquième front descendant de l'horloge après le bit de Start. Le MCP3208 retourne un bit Null (à zéro), puis les 12 bits issus de la conversion analogique-numérique (en commençant par le bit 11 de poids fort).

En C, les trois octets retournés dans un tableau sont récupérés et traités pour obtenir la valeur numérique de la conversion dans une variable :

 
Sélectionnez
unsigned char mcp3208_ReceivedData[3];
unsigned int result;

// lancement de la communication SPI, 3 octets transmis et 3 octets en retour
bcm2835_spi_transfernb(mcp3208_TransmittedData, mcp3208_ReceivedData, 3);

result = (mcp3208_ReceivedData[1] & 0x0f)<<8 | mcp3208_ReceivedData[2];

IV. Capteur de température analogique LM335

Afin de tester le convertisseur analogique-numérique… un capteur de température analogique LM335, trouvé dans mes tiroirs.

Image non disponible
LM335 dans son boîtier TO-92, un composant à trois broches (V+, V- et ADJ) enfichable sur une plaque d'essai

Le LM335 se comporte comme une diode Zener avec une tension de claquage directement proportionnelle à la température en Kelvin (10 mV/°K). Correctement calibré à 25 °C, sa précision est inférieure au 1 °C sur une plage de température de plus de 100 °C (gamme de mesure entre -40 et +100 °C).

Si on souhaite l'utiliser pour mesurer des températures ambiantes en intérieur, disons entre 15 °C et 35 °C, la tension entre ses bornes V+ et V- devrait varier entre :

Vmin = (273,15 + 15) x 10 x 10-3 = 2,88 V

Vmax = (273,15 + 35) x 10 x 10-3 = 3,08 V

Pour une meilleure précision, on a intérêt à ce que la tension d'entrée du convertisseur analogique-numérique évolue dans la totalité de la plage de tension entre 0 et la tension maximale VREF, ce qui est loin d'être le cas ici où la tension d'entrée évolue de façon resserrée autour des 3 V à température ambiante. Toutefois, le quantum du MCP3208 avec VREF = 3,3 V est inférieur au millivolt, soit une résolution en température inférieure à 0,1 °C. On peut donc envisager un montage basique comme celui de la figure ci-dessous sans adaptation de tension particulière, avec la tension OUTPUT qui constitue la tension d'entrée du convertisseur analogique-numérique :

Image non disponible
Montage basique du LM335 selon sa datasheet

Pour être correctement polarisé, le constructeur recommande un courant traversant le LM335 évoluant entre 0,4 et 5 mA. Dans cette plage de courant, les caractéristiques du LM335 sont indépendantes de la valeur du courant.

Si on alimente le capteur avec V+ = 5 V , la tension aux bornes du capteur évoluant autour de 3 V à température ambiante : la tension aux bornes de la résistance R1 vaut approximativement 5 - 3 = 2 V (loi des mailles en électricité). Si on veut limiter le courant à 2 mA, la loi d'Ohm impose une résistance R1 = 2 / 0,002 = 1 kΩ.

Pour améliorer la précision, le constructeur recommande de calibrer le capteur à 25 °C avec un potentiomètre 10 kΩ selon le montage ci-dessous :

Image non disponible
Extrait datasheet LM335

Pour calibrer le capteur, on doit régler le potentiomètre de façon à mesurer une tension en sortie de 2,98 V à 25 °C.

Relation entre la température en degré Celsius et la valeur numérique N après conversion analogique-numérique :

kitxmlcodelatexdvp\left\{\begin{matrix} V^{+}-V^{-}=0,01 \times T\left ( ^oK \right ) \qquad \text{caractéristique du LM335} \\ V^{+}-V^{-}=\frac{N}{2^{12}-1}\times V_{REF} \qquad \text{conversion analogique-numérique} \\ \Theta \left ( ^oC \right )=T\left ( ^oK \right )-273,15 \qquad \text{conversion Kelvin-Celsius} \end{matrix}\right.finkitxmlcodelatexdvp

Soit :

kitxmlcodelatexdvp\Theta \left ( ^oC \right )=\left (\frac{N}{2^{12}-1}\times V_{REF} \right ) \times 100-273,15finkitxmlcodelatexdvp

V. Schéma du montage

Image non disponible
Schéma réalisé avec https://easyeda.com/editor

____

Sur ce genre de schémas, les broches des composants et du Pi sont disposées de façon logique (les alimentations sont regroupées ensemble, comme les broches de la liaison SPI, les entrées analogiques, etc.). Cette disposition logique n'a souvent rien à voir avec la disposition physique des broches sur les composants :

Image non disponible

La tension d'alimentation VDD du MCP3208 et la tension de référence VREF sont à 3,3 V. La sortie du capteur de température est connectée directement à l'entrée Channel 0. R2 est un potentiomètre pour calibrer le capteur pour plus de précision. Le curseur du potentiomètre est connecté sur la broche ADJ du LM335. Le MCP3208 sera sélectionné sur la broche CE0 (Chip Enable 0) du Pi (le Pi peut sélectionner jusqu'à deux esclaves SPI sur ses broches CE0 et CE1).

Si vous optez pour le HAT de Nation Electronics, vous profitez bien entendu de certains avantages :

Image non disponible

Moins de câblage, des configurations par cavaliers (jumpers), reconnaissance du HAT au démarrage du Pi grâce à la mémoire EEPROM, etc. Vous enfichez le HAT sur le port GPIO du Pi, et vous avez pratiquement une carte d'extension plug and play. Les broches d'entrées analogiques sont facilement accessibles sur le côté de la carte, et la reprise des 40 broches du port GPIO permet d'y brancher d'autres composants ou même d'empiler un deuxième HAT.

Avec ce HAT, le MCP3208 est alimenté en 5 V pris sur la broche GPIO 5 V du Pi par défaut, mais on peut aussi l'alimenter avec une source extérieure grâce à un connecteur sur le côté de la carte (il faut retirer le cavalier Back Power dans ce cas). Alimenter le MCP3208 en 5 V plutôt qu'en 3,3 V permet d'augmenter sensiblement la vitesse d'acquisition (jusqu'à 100 000 échantillons par seconde théoriquement d'après la documentation). Les niveaux logiques de tension du port GPIO du Pi étant sur du 0 - 3,3 V, l'électronique de la carte prévoit un indispensable convertisseur de niveau logique 3,3 - 5 V pour les échanges sur la liaison SPI.

Image non disponible
Pi + HAT MCP3208 avec le montage du LM335 sur plaque de câblage. Au fond, l'analyseur logique pour espionner les trames.

VI. Acquisition de la température en langage C

VI-A. Installation de la bibliothèque bcm2835

Cette bibliothèque open source en C permet d'accéder au port GPIO du Pi sans passer par les pilotes Linux.

Lien vers la bibliothèque bcm2835 à installer sur le Pi : C library for Broadcom BCM 2835 as used in Raspberry Pi

Vous y trouverez le lien de téléchargement de la dernière version (fichier tar.gz).

La procédure d'installation y est également décrite :

 
Sélectionnez
# download the latest version of the library, say bcm2835-1.xx.tar.gz, then:
tar zxvf bcm2835-1.xx.tar.gz
cd bcm2835-1.xx
./configure
make
sudo make check
sudo make install

VI-B. Le code

La bibliothèque bcm2835 comporte les fonctions nécessaires pour gérer une communication SPI : SPI access.

temperature_mcp3208.c
Sélectionnez
#include <bcm2835.h>
#include <stdio.h>
#include <stdlib.h>

unsigned int readADC(unsigned char);
unsigned int median(unsigned int n, unsigned int *x);
static int compare (void const *a, void const *b);

int main (int argc, char **argv){
  unsigned char channel = 0; // acquisition sur CH0
  double vref = 3.3; // tension de reference VREF=3,3V
  unsigned int nbSamples = 5; // filtre median sur 5 echantillons
  
  unsigned int x[nbSamples];
  unsigned int result;
  unsigned int i;
  double temperature;

    if (!bcm2835_init())
    {
      printf("Echec bcm2835_init.\n");
      return EXIT_FAILURE;
    }   
    if (!bcm2835_spi_begin())
    {
      printf("Echec bcm2835_spi_begin.\n");
      return EXIT_FAILURE;
    }
    
    bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_MSBFIRST); // bit de poids fort en premier
    bcm2835_spi_setDataMode(BCM2835_SPI_MODE0);  // Mode 0 : CPOL=0, CPHA=0 
    bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_2048); // diviseur frequence
    bcm2835_spi_chipSelect(BCM2835_SPI_CS0);  // Chip Select 0
    bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS0, LOW); // Chip Select actif au niveau bas
    
    // Lancement des conversions   
    for (i=0; i<nbSamples; i++)
    {
        x[i] = readADC(channel);
    }
        
    result = median(nbSamples,x); // valeur mediane
    
    temperature = ((double)result / (double)4095 * vref) *100 - 273.15;
   
    fprintf(stdout,"%.1f\n", temperature);

    bcm2835_spi_end();
    bcm2835_close();
    return EXIT_SUCCESS;
}

unsigned int readADC(unsigned char channel) {
    // echantillonnage et conversion sur l'entree channel
    
    unsigned char mcp3208_ReceivedData[3];
    unsigned char input_mode = 1; // single ended = 1, differential = 0
    unsigned int result;
    
    // octets transmis
    unsigned char mcp3208_TransmittedData[]={    
        (1<<2)  | (input_mode<<1) | ((channel>>2) & 0x01),
        channel<<6,
        0x00 };
        
    // lancement de la transaction
    bcm2835_spi_transfernb(mcp3208_TransmittedData, mcp3208_ReceivedData, 3);
                
    // Recuperation de la valeur issue de la conversion
    result = (mcp3208_ReceivedData[1] & 0x0f)<<8 | mcp3208_ReceivedData[2];
    return result;
}

unsigned int median(unsigned int n, unsigned int *x) {
    // valeur mediane du tableau
    qsort (x, n, sizeof(unsigned int), compare);
       
    if(n%2==0) {
        return ((x[n/2] + x[n/2 - 1]) / 2);
    } else {
        return x[n/2];
    }
}

static int compare (void const *a, void const *b) {
   // definition du tri par ordre croissant

   unsigned int const *pa = a;
   unsigned int const *pb = b;
 
   return *pa - *pb;
}

Le code est compilé avec la commande :

 
Sélectionnez
gcc -Wall -o temperature_mcp3208 temperature_mcp3208.c -lbcm2835 -std=c99

Les étapes du code :

  • Initialiser la communication SPI.
  • Démarrer la conversion analogique-numérique de 5 échantillons, les valeurs sont contenues dans un tableau.
  • Extraire la valeur médiane afin d'éliminer les quelques valeurs aberrantes dues aux parasites. Pour cela, on extrait la valeur au milieu du tableau trié avec la fonction qsort()).
  • Convertir la valeur médiane en une valeur de température en degré Celsius.
  • Afficher la valeur de la température formatée au 1/10 °C dans la console.
Image non disponible
Sur Raspberry Pi, édition et compilation du code avec Geany

VI-C. Remarques sur la vitesse d'acquisition

La documentation du MCP3208 annonce une fréquence maximale de l'horloge SPI à 2 MHz pour une tension d'alimentation VDD = 5 V (et seulement 1 MHz avec VDD = 2,7 V). Avec une transaction SPI comportant 20 bits utiles, cela donne en théorie 100 000 échantillons convertis par seconde, ce qui est confirmé par la documentation qui annonce la valeur maximale de 100 ksps (kilo samples per second).

L'horloge SPI du Pi est configurée à la ligne :

 
Sélectionnez
bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_2048);

La fréquence de l'horloge SPI est calculée à partir de la fréquence de l'horloge principale et d'un diviseur (le diviseur est nécessairement une puissance de 2) :

Pour le Pi 3 : Fréquence horloge SPI = 400 MHz/diviseur

Pour les Pi 1 et 2 : Fréquence horloge SPI = 250 MHz/diviseur

Voir les explications ici : bcm2835SPIClockDivider

Possédant un Pi 3 avec le HAT MCP3208 de Nation Electronics, la fréquence avec un diviseur de 2048 est égale à 400 Mhz/2048 = 195 kHz. En théorie, on devrait pouvoir pousser la fréquence à 400 Mhz/256 = 1,5 MHz et s'approcher des performances maximales annoncées par le constructeur.

En pratique, avec Raspberry Pi sous Linux, il faut tempérer les performances, et on peut s'en rendre compte en visualisant les signaux avec un analyseur logique :

Image non disponible
Visualisation de la transaction SPI avec un analyseur logique USB
Image non disponible
Visualisation de trame SPI montrant trois conversions d'affilée
  • les données qui transitent sur les lignes MISO et MOSI sont des paquets de 8 bits, et il faut donc au moins 24 cycles d'horloge, au lieu de 20 en théorie, pour échanger les trois octets. Ce qui ne donne plus que 2 Mhz/24 = 83 000 échantillons par seconde au maximum.
  • Rajoutez à cela un délai avant de lancer la communication une fois la ligne CEx activée, et un délai entre chaque octet (environ 1,5 cycle d'horloge à chaque fois)… sans compter d'éventuelles latences de Linux.

Si on mesure le temps pris (avec clock_gettime) pour réaliser 10 000 acquisitions dans une boucle, voici un exemple de résultat obtenu (Pi 3 + HAT MCP3208 avec un diviseur 2048) :

Image non disponible
Conditions d'utilisation : Pi 3 sous Raspbian Jessie, fréquence SPI=195 kHz

Soit la durée d'une transaction correspondant à environ 28 cycles d'horloge.

La vitesse d'acquisition maximale tombe en théorie autour de 2 MHz / 28 = 71 ksps et le diviseur de l'horloge SPI ne devrait pas descendre en dessous de 256 (les valeurs obtenues à la conversion analogique-numérique deviennent en effet aberrantes avec un diviseur de 128).

Image non disponible
Conditions d'utilisation : Pi 3 sous Raspbian Jessie, fréquence SPI=1562 kHz

De la vitesse de 100 ksps annoncée par le constructeur, nous descendons à 55 ksps en pratique, et encore moins si le MCP3208 n'est alimenté qu'en 3,3 V…

Évidemment, ces considérations n'ont pas grande importance pour quelques acquisitions à effectuer dans l'heure d'un signal qui varie très lentement, mais il faut en tenir compte en fonction de la rapidité de variation de vos signaux analogiques et même du nombre de signaux à acquérir (le MCP3208 ne permet de faire des conversions que pour une seule entrée à la fois).

On rappelle que pour un signal donné, le théorème de Shannon permet de connaître la fréquence d'échantillonnage minimale (au moins deux fois la fréquence maximale recherchée dans le signal). Si ce critère n'est pas respecté, le spectre du signal échantillonné présente des fréquences parasites qui n'appartiennent pas au signal de départ (phénomène de repliement spectral ou aliasing).

Voir par exemple cette démonstration animée du phénomène sur un signal sinusoïdal : Repliement spectral

Pour plus de détails, chez National Instruments :

VII. Visualisation des données temporelles avec Node-RED

Comment visualiser des données de températures acquises en temps réel dans un navigateur Web ?

VII-A. Installation et premier flux

Node-RED est un outil de programmation graphique et open source soutenu par IBM pour mettre en œuvre des objets connectés. Uniquement en connectant des « nœuds » configurables à la souris, on fait circuler des flux de données pour piloter le port GPIO du Pi, réaliser des interfaces graphiques Web, accéder à une base de données (locale ou dans le cloud) ou à une plateforme IdO (Internet des Objets) pour stocker/visualiser/analyser des données, envoyer des mails ou des tweets suite à un événement, et beaucoup d'autres choses encore.

Node-RED est installé par défaut sur Raspbian Jessie. En cas de soucis, il faudra peut-être mettre à jour votre distribution Linux et la version de Node-RED. Voir Node-RED - Running on Raspberry Pi.

 
Sélectionnez
sudo su
apt-get update
apt-get upgrade
update-nodejs-and-nodered

Pour démarrer/arrêter le serveur Node-RED :

 
Sélectionnez
node-red-start
node-red-stop

Après avoir démarré le serveur, rendez-vous dans un navigateur à l'adresse http://adresse IP du Pi:1880/.

On commence par programmer un flux très simple :

Image non disponible

Depuis de la palette des nœuds à gauche, faites glisser les nœuds suivants dans la fenêtre principale du flux Flow1, puis reliez-les entre eux à la souris :

Image non disponible
Image non disponible
Image non disponible

Le nœud exec permet d'exécuter un programme extérieur. Il sera configuré pour lancer l'acquisition d'une température. Pour lancer le programme du chapitre précédent, cela donne :

Image non disponible

Cliquez sur le bouton Image non disponible pour déployer le flux. À droite de l'interface Node-RED, sélectionnez l'onglet Debug. Puis cliquez sur le bouton carré du nœud d'injection (renommé Timestamp par défaut) pour injecter les données dans le flux. De nouvelles données de température devraient s'afficher dans la fenêtre Debug à chaque injection dans le flux :

Image non disponible

VII-B. Visualisation avancée dans un tableau de bord

Pour visualiser les données dans une interface plus agréable, sous forme de jauge ou de courbe de température, il faudra installer des nœuds supplémentaires.

Pour cela, cliquez sur le bouton Image non disponible pour accéder au menu Node-RED, puis sélectionnez le menu Manage palette.

Image non disponible

Recherchez et installez le module intitulé node-red-dashboard :

Image non disponible

Il faudra éventuellement arrêter et relancer le serveur Node-RED pour découvrir les nouveaux outils dans la palette :

Image non disponible

Vous pouvez maintenant reprendre le flux précédent et rajouter les nouveaux nœuds suivants :

Image non disponible

Le flux devient :

Image non disponible

Vous pouvez paramétrer le format d'affichage du graphique et de la jauge. Créez et paramétrez un tab node « Chez moi » avec deux group node « myGauge » et « myChart ».

Image non disponible

Si on veut une acquisition de température toutes les cinq minutes, il faut paramétrer le timestamp :

Image non disponible

Redéployez la mise à jour du flux. Pour visualiser le tableau de bord, cliquez sur le lien :

Image non disponible

Exemple obtenu après plus de deux heures d'acquisition :

Image non disponible

Après un peu de mise en forme du tableau de bord, et 24 heures d'acquisition plus tard :

Image non disponible

VIII. Conclusion

Le MCP3208 de Microchip est un composant qui, à moindres frais, répond à l'absence de port analogique sur la célèbre carte Raspberry Pi. L'électronique du HAT MCP3208 de Nation Electronics offre en plus des facilités de réglage et de connexion ainsi qu'une alimentation du MCP3208 en 5 V augmentant sensiblement la vitesse d'échantillonnage et de conversion pour des signaux analogiques rapides. La bibliothèque bcm2835 en langage C propose des fonctions d'accès bas niveau au port GPIO, notamment liées au protocole de communication SPI, et ceci sans faire appel aux pilotes Linux. Bien calibré, le LM335 offre une précision au degré près et les courbes (chaque point de la courbe est la valeur médiane sur cinq échantillons) montrent une fidélité des mesures à ±0,1 °C. Node-RED est aussi un outil de choix pour l'Internet des Objets, il permet de réaliser quasiment sans aucune programmation de véritables prototypes d'applications connectées.

Je remercie Vincent PETIT pour la relecture technique et Claude Leloup pour la correction orthographique.

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   


HAT : Hardware Attached on Top, une carte additionnelle qui s'enfiche sur le port GPIO du Pi et qui permet d'ajouter des fonctionnalités au Pi à moindre effort. Voir Apprendre à fabriquer sa propre carte d'extension Pi HAT.

  

Copyright © 2017 f-leb. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.