Table des matières

Arduino 33 BLE : mesure de capacité

1. Introduction

Cette page montre comment mesurer une capacité avec un Arduino nano 33 BLE.

La mesure de la capacité (C) d'un condensateur, ou d'un dispositif physique équivalent à un condensateur, peut se faire de différentes manières :

Dans ce document, nous mettons en œuvre la première méthode, la plus simple à réaliser et donnant des mesures très précises sur une très large gamme de capacités (avec le même circuit). La deuxième méthode est souvent utilisée dans l'électronique des capteurs capacitifs mais elle est plus difficile à réaliser car elle nécessite un très bon calibrage de l'oscillateur. La troisième méthode, utilisée dans des appareils de mesure (RLC-mètre), est intéressante pour faire une mesure sur un condesnateur qui sera effectivement utilisé dans un circuit de traitement de signaux, car la valeur de capacité dans ces conditions peut être différente de la valeur mesurée lors d'une charge à courant constant (et peut dépendre de la fréquence).

Le code présenté utilise la programmation directe des périphériques du microcontrôleur Nordic nRF52840. Il n'est donc pas compatible avec les autres arduinos.

2. Circuit de mesure

Le condensateur est chargé à courant constant grace à un intégrateur, la tension à ses bornes variant de 0 à Vcomp. Le traitement numérique, qui sera effectué par un microcontrôleur, consiste à mesurer la durée de cette charge, d'où la valeur de C peut être facilement déduite.

Voici le circuit analogique et la liaison avec l'arduino :

mesureCapacite.svgFigure pleine page

La partie analogique fonctionne avec une double alimentation (par exemple -10/+10 V). L'arduino est alimenté par le port USB. S'il fonctionne en autonomie, il faut l'alimenter par la borne VIN (non stabilisé, entre 5 et 11 V). L'élément central de ce circuit est l'intégrateur, réalisé avec l'ALI CI1, dont la rétroaction négative est constituée du condensateur dont on veut mesurer la capacité (C). L'obtention d'un courant de charge constant et précisément connu est obtenu grace au LM 336 (une référence de tension équivalente à une diode Zener mais en mieux) qui fournit la tension de référence Vref. La résistance R est mesurée avec un ohmmètre. L'intensité du courant dans la capacité est :

i=VrefR(1)

Elle vaut 50 microampère, ce qui est beaucoup plus grand que le courant de polarisation du TL082 (ALI à transistors à effet de champ). Si le condensateur est déchargé à l'instant initial, la tension en sortie de l'intégrateur est :

V1=-VreftRC(2)

La décharge du condensateur est assurée par un interrupteur CMOS (DG441, comportant 4 interrupteurs) piloté par l'arduino. Lorsque l'entrée IN1 est au niveau bas, l'interrupteur entre D1 et S1 est fermé, avec une résistance interne de l'ordre de 50Ω, et le condensateur se décharche donc dans cette résistance. Lorsque IN1 est au niveau haut, l'interrupteur est ouvert et le condensateur se charge en suivant la loi (2).

La tension V1 est négative. Le deuxième ALI réalise un montage inverseur dont la sortie est V7=-V1. CI3 est un comparateur qui permet de détecter le moment où la tension -V1 atteint Vcomp, c'est-à-dire :

tc=VcompRCVref(3)

La sortie du comparateur est un transistor bipolaire en collecteur ouvert. Elle doit être reliée à la borne 3.3 V de l'arduino via la résistance R3, afin de délivrer un signal compatible avec cet arduino. L'entrée D4 de l'arduino est donc soumise à un front montant lorsque V1=-Vcomp, après quoi on peut procéder à la décharge du condensateur, qui est 20000 fois plus rapide que la charge.

Le temps tc mesuré par le microcontrôleur est l'intervalle de temps entre la commande d'ouverture de l'interrupteur (basculement de la sortie D3 de bas à haut) et le front montant sur l'entrée D4.

La capacité est calculée avec :

C=VreftcRVcomp(4)

Avec un microcontrôleur de fréquence d'horloge 16MHz, une précision de mesure de temps d'une microseconde peut être atteinte (peut être mieux). La précision sur la capacité est donc en théorie de l'ordre de 10 picofarad, sous réserve que les tensions de référence et la valeur de R soient connues avec assez de précision. Dans certains cas, on cherche seulement à détecter des variations de capacité sans vouloir une valeur précise et une variation de l'ordre de 10 picofarad semble donc accessible (à vérifier expérimentalement). Il faut aussi remarquer que les pistes de liaison entre le condensateur et les deux bornes de l'ALI sont suffisantes pour introduire une capacité de l'ordre de quelques picofarads, et bien plus si un câble de liaison est utilisé.

3. Programme Arduino

La mesure du temps se fait avec un TIMER, que l'on programme directement comme expliqué dans la notice d'utilisation du microcontrôleur nRF52840. On utilise le TIMER4. En mode timer, son compteur 32 bits est incrémenté par des impulsions d'horloge, à une fréquence égale à 16 MHz/2prescaler. Pour les faibles capacités, on utilisera prescaler=0, ce qui donne 16 incrémentations par microseconde. Le compteur est démarré (à partir d'une valeur nulle) au moment du passage de la sortie D3 du niveau bas au niveau haut (ouverture de l'interrupteur) et sa valeur est lue au moment où l'entrée D4 (sortie du comparateur) passe du niveau bas au niveau haut. La borne D2 est utilisée comme entrée. Elle est reliée à la borne D3. Le PPI (Programmable Peripheral Interconnect) permet de configurer un évènement (NRF_GPIOTE->EVENTS_IN[1]) déclenché lorsque D2 passe de bas à haut. Cet évènement déclenche le TIMER4 (tâche NRF_TIMER4->TASKS_START). On configure aussi un évènement (NRF_GPIOTE->EVENTS_IN[0]) déclenché lors d'un front montant sur l'entrée D4 (sortie du comparateur), qui déclenche la tâche NRF_TIMER4->TASKS_CAPTURE[0], laquelle effectue une recopie de la valeur du compteur dans le registre CC[0] du TIMER4. La lecture de ce registre, après déclenchement de l'évènement NRF_GPIOTE->EVENTS_IN[0], donne accès au temps de charge exprimé en nombre d'impulsions d'horloge.

mesure_capacite.ino
#include "Arduino.h"
#include "nrf.h"
#include "mbed.h"

#define START_OUT 3 // commande de l'interrupteur
#define COMP_IN 4 // sortie du comparateur
#define START_IN 2 // entrée reliée à D2
#define PPI_CAPTURE_CH 10
#define PPI_START_CH 11

#define VREF 4.943 // mesurée
#define VCOMP 8.00 // mesurée
#define R 986e3 // mesurée

float time2C;

float mesure(uint16_t prescaler) {
  const uint8_t pins[14] = {0,0,11,12,15,13,14,23,21,27,2,1,8,13};
  const uint8_t ports[14] = {0,0,1,1,1,1,1,0,0,0,1,1,1,0};
  float timer_dt;
  NRF_GPIOTE->CONFIG[0] = 1 | (pins[COMP_IN]<<8) | (ports[COMP_IN]<<13) | (1<<16); // évènement rise sur COMP_IN
  NRF_GPIOTE->CONFIG[1] = 1 | (pins[START_IN]<<8) | (ports[START_IN]<<13) | (1<<16); // évènement rise sur START_IN
  NRF_TIMER4->TASKS_STOP = 1;
  NRF_TIMER4->MODE = 0; // timer mode
  NRF_TIMER4->BITMODE = 3; // 32 bits
  NRF_TIMER4->PRESCALER = prescaler;
  timer_dt = 1.0/16*pow(2,prescaler);
  NRF_TIMER4->TASKS_CLEAR = 1;
  NRF_PPI->CH[PPI_CAPTURE_CH].EEP = (uint32_t)&NRF_GPIOTE->EVENTS_IN[0];
  NRF_PPI->CH[PPI_CAPTURE_CH].TEP = (uint32_t)&NRF_TIMER4->TASKS_CAPTURE[0];
  NRF_PPI->FORK[PPI_CAPTURE_CH].TEP = (uint32_t)&NRF_TIMER4->TASKS_CLEAR;
  NRF_PPI->CHEN |= (1<< ((uint32_t)PPI_CAPTURE_CH));

  NRF_PPI->CH[PPI_START_CH].EEP = (uint32_t)&NRF_GPIOTE->EVENTS_IN[1];
  NRF_PPI->CH[PPI_START_CH].TEP = (uint32_t)&NRF_TIMER4->TASKS_START;
  NRF_PPI->CHEN |= (1<< ((uint32_t)PPI_START_CH));
  
  NRF_P1->DIR |= (1<<pins[START_OUT]);  //output
  NRF_P1->OUT |= (1 << pins[START_OUT]); // on ouvre l'interrupteur : la charge commence et le TIMER se déclenche
  
  while (NRF_GPIOTE->EVENTS_IN[0] == 0) {;} // on attend le front montant sur D4
  NRF_GPIOTE->EVENTS_IN[0] = 0;
  NRF_TIMER4->TASKS_STOP = 1;
  NRF_P1->OUT &= ~(1 << pins[START_OUT]); // on ferme l'interrupteur pour la décharge
  return timer_dt*NRF_TIMER4->CC[0];
}

void setup() {
  Serial.begin(115200);
  pinMode(START_OUT,OUTPUT);
  pinMode(COMP_IN,INPUT);
  pinMode(START_IN,INPUT);
  digitalWrite(START_OUT,LOW); // interrupteur fermé
  time2C = VREF/(R*VCOMP)*1e3;
}

void loop() {
  float temps;
  float C;
  temps = mesure(0);
  Serial.print(temps); Serial.print(" muS, ");
  C = temps*time2C;
  Serial.print(C,3); Serial.println(" nF");
  rtos::ThisThread::sleep_for(1000);

}   	       
    	       

La mesure est répétée toutes les secondes, avec un affichage du temps de charge et de la capacité.

4. Test du système

Le test présenté ci-dessous est fait avec un condensateur de capacité nominale 2,2nF. Une mesure avec un LRC-mètre donne C=2,155nF100Hz). Voici la sortie console :

3452.25 muS, 2.163 nF
3450.44 muS, 2.162 nF
3453.31 muS, 2.164 nF
3451.94 muS, 2.163 nF
3452.38 muS, 2.163 nF
3452.25 muS, 2.163 nF
3449.94 muS, 2.162 nF
3454.69 muS, 2.165 nF
3449.25 muS, 2.161 nF
3450.69 muS, 2.162 nF
3451.69 muS, 2.163 nF
    	    

Voici la tension en sortie de l'inverseur (en bleu) et la tension de commande de l'interrupteur (en rouge).

oscillo

Voici un détail de la fin de la charge, avec la tension en sortie de l'inverseur (en bleu) et la tension en sortie du comparateur (en rouge).

oscillo

Le temps de montée de la sortie du comparateur est de 4 microsecondes. Il peut être réduit en diminuant la résistance de collecteur (R3) mais on augmente alors le nombre de basculements accidentels (dus au bruit). La documentation du LM392 indique un temps de réponse de 1,3 microsecondes, ce qui correspond au temps le plus faible qu'on puisse obtenir, avec une résistance de collecteur beaucoup plus faible et avec une bascule à hystérésis. Quel est l'effet de ce temps de montée sur la précision de la mesure ? La bascule logique du niveau bas au niveau haut se fait en théorie à 2V (trait pointillé horizontal), soit 1,4 microsecondes avant la fermeture de l'interrupteur. On peut en déduire que la précision de la mesure est limitée par la vitesse du comparateur (non par la précision du compteur) et qu'elle est de l'ordre de la microseconde, soit 10 picofarads, ce que confirme la comparaison des deux valeurs obtenues ci-dessus.

La mesure d'une grandeur par mesure de temps offre un grand avantage comparé à l'utilisation d'un convertisseur analogique-numérique : le compteur peut atteindre des valeurs très élevés (il s'agit d'un compteur 32 bits), ce qui permet de mesurer des valeurs de capacité beaucoup plus grande avec le même montage. Voici par exemple le résultat avec un condensateur de capacité nominale 1 microfarad :

1647901.62 muS, 1032.654 nF
1647694.00 muS, 1032.524 nF
1648387.37 muS, 1032.959 nF
1648111.50 muS, 1032.786 nF
1647842.75 muS, 1032.617 nF
1647634.50 muS, 1032.487 nF
1647973.25 muS, 1032.699 nF
1647660.75 muS, 1032.503 nF
1647640.62 muS, 1032.491 nF
1648354.25 muS, 1032.938 nF
1648385.25 muS, 1032.957 nF
    	    

Le temps de charge est d'environ 1,6s. On constate que le temps mesuré a des variations importantes d'un cycle à l'autre, de l'ordre de plusieurs centaines de microsecondes. Voyons la tension en sortie de l'inverseur (en bleu) et la tension en sortie du comparateur (en rouge) :

oscillo

On constate que la sortie du comparateur subit un très grand nombre de transitions plus ou moins complètes (à cause du bruit), qui s'étalent sur une durée de 900 microsecondes et qui expliquent les aléas sur le passage du niveau logique bas au niveau logique haut (ce qui signifie que la bascule se fait à une tension bien inférieure à 2 V). La tension en sortie de l'intégrateur augmente beaucoup plus lentement avec une forte capacité, ce qui explique ce comportement du comparateur. Autrement dit, le bruit présent dans la tension de la rampe en sortie de l'intégrateur fait que la durée de la montée a une incertitude intrinsèque de l'ordre de quelques centaines de microsecondes. Les variations du temps mesuré sont très faibles par rapport au temps lui-même (moins de 1/1000), ce qui fait que la précision sur la valeur de C est de 0,1 pour cent. On peut d'ailleurs remarquer que chercher à mesurer une valeur de C avec précision inférieure à celle-ci n'a sans doute pas de sens, en raison du bruit présent dans tout signal.

Pour conclure, le dispositif permet de mesurer la capacité avec une précision relative de 0,1 pour cent et une précision absolue maximale de 10 picofarads. Il faut aussi que les différentes valeurs (tensions de référence et valeurs des résistances) soient déterminées avec une précision suffisante, ce qui constitue l'étalonnage du dispositif. Si l'étalonnage n'est pas bien fait, il se produit une erreur systématique.

5. Circuit à alimentation simple

Le circuit utilisé ci-dessus a l'inconvénient de nécessiter une double alimentation. En effet, la tension de sortie d'un intégrateur à ALI est négative (si la tension d'entrée est positive). Pour placer ce circuit dans un système embarqué fonctionnant avec une alimentation simple (typiquement une pile ou un accumulateur), il faudrait utiliser un convertisseur DC-DC à découpage. Une autre solution consiste à charger le condensateur au moyen d'une source de courant réalisée avec un transistor à jonctions PNP. La figure suivante montre ce circuit :

mesureCapacite-transistor.svgFigure pleine page

L'alimentation indiquée sur la figure est une alimentation simple 10 V mais une alimentation simple supérieure à 7 V devrait convenir, par exemple une pile de 9 V. Il est possible d'utiliser une alimentation de 5 V, ou même l'alimentation stabilisée de 3.3 V en sortie de l'arduino, mais il faudra alors remplacer le LM336 par le LM336-2.5, qui fournit une référence de 2,5 V. Le LM336 (équivalent à une diode zéner) en série avec R4, permet de polariser la diode jonction émetteur-base du transistor. La tension Vref aux bornes de la résistance d'émetteur est égale à la tension aux bornes de la diode zéner moins 0,6 V (environ). Une mesure donne Vref=4,39V. L'intensité du courant émetteur s'en déduit :

Ie=VrefR(5)

L'intensité du collecteur, c'est-à-dire l'intensité qui traverse le condensateur (C) est :

Ic=Ie-Ib(6)

La figure suivante montre la caractéristique collecteur-émetteur d'un transistor NPN (2N2222, complémentaire du 2N2907). Vce est la différence de potentiel entre l'émetteur et le collecteur.

transistor

Le transistor est utilisé dans la zone active, là où le courant de collecteur dépend très peu de la tension Vce, ce qui lui confère ses propriétés de source de courant. Le courant de collecteur est de l'ordre de 50 microampères. La correspondante n'est pas repréentée mais peut se déduire de la figure par extrapolation : Ic est effectivement indépendante de Vce dur une très large plage de tension, ce qui permet de réaliser une excellente source de courant. Pour un courant de l'ordre de 10 mA, la source serait beaucoup moins bonne. On voit par ailleurs que le courant de base est environ 28 fois plus faible que le courant de collecteur. En première approximation, on a donc :

IcIe1+128=0,96Ie(7)

La tension aux bornes de C est une rampe :

Vc=IctC=0,97VreftRC(8)

Cette tension est croissante donc positive (ce qui est un avantage par rapport à l'intégrateur utilisé précédemment). Le comparateur bascule au niveau haut lorsque cette tension atteint Vcomp (ajustée à 5,00 volts avec le potentiomètre). La capacité se déduit du temps de charge par la relation :

C=0,96VreftcRVcomp(9)

Cette relation utilise la valeur du gain en courant du transistor, que nous avons évalué à 28 mais qui n'est pas connue avec précision, et qui est probablement légèrement plus petite que cette valeur car le courant est très faible. Il est donc nécessaire de faire un étalonnage avec une capacité connue afin de préciser la valeur du facteur correctif. Nous avons obtenu par étalonnage un facteur de 0,92. On peut aussi déterminer directement le facteur mutliplicatif du temps permettant d'obtenir la capacité. L'étalonnage de ce dispositif a l'inconvénient de nécessiter un autre moyen de mesurer la valeur de C servant d'étalon.

Voici la tension Vc (en bleu) et la tension de commande de l'interrupteur (en rouge).

oscillo

Qu'en est-il de la linéarité du système de mesure, c'est-à-dire de la validité de la relation (9) quelque soit le temps de charge (de quelques microsecondes à plusieurs secondes) ? L'utilisation d'une référence de tension (LM 336) et le fait que le courant de base ne change pratiquement pas garantit en principe une tension Vref constante. Nous avons en effet vérifié que cette tension reste bien égale à 4,39V tout au long du cycle et quelle que soit la capacité C. L'utilisation d'une réference de tension, et non pas d'un simple pont diviseur résistif, garantit que la tension Vref reste constante même si la tension d'alimentation varie, ce qui peut survenir si elle n'est pas stabilisée. Le courant d'émetteur (Ie) est donc bien constant. Lorsqu'on change la capacité (C), la rampe de tension Vc(t) est toujours la même, seulement sa durée change. Si une variation du courant Ic devait se produire, elle se verrait donc sur Vc(t). L'enregistrement de Vc(t) (figure ci-dessus) montre bien une rampe de pente constante, au moins avec une précision de 1 pour cent. On en déduit que le courant de collecteur (Ic), c'est-à-dire le courant qui traverse C, est bien constant, ce qui garantit la linéarité du dispositif.

6. Mesure de résistance

Le même dispositif peut servir à mesurer une résistance. Supposons en effet que la valeur de C soit connue et que R soit la résistance à mesurer. Le temps de charge varie linéairement avec la résistance et sa mesure permet de calculer la résistance :

R=0,96VreftcCVcomp(10)

En pratique, on déterminera le coefficient de proportionnalité entre le temps de charge et R par étalonnage avec une résistance mesurée à l'ohmmètre. La valeur de C est choisie en fonction de la gamme de résistances souhaitée. Pour C=1000nF, une résistance de 100 donne un temps de charge de 126ms. Si l'on suppose que le temps de charge le plus petit qu'on peut mesurer avec une précision de 1/100 est 10 microsecondes, on pourra avec cette valeur de C faire des mesures de résistances de 10Ω à 1 (durée de 10 microsecondes à 1,2 secondes). C'est une gamme de valeur très large. Pour obtenir la même gamme avec une méthode reposant sur une mesure de tension, par exemple en mesurant avec un convertisseur A/N la tension aux bornes de R branchée sur une source de courant, il faudrait un convertisseur A/N 24 bits (car 1,2 secondes est environ 107 fois plus grand que la précision du timer). D'une manière générale, une conversion analogique-numérique qui repose sur une mesure de temps (par ex. la conversion simple rampe ou double rampe) permet d'obtenir une très grande précision. L'inconvénient est bien sûr la relative lenteur, lorsque le temps mesuré est grand.

Les capteurs reposant sur une variation de résistance sont très courants, par exemple la thermistance, dont la résistance dépend de la température. Le dispositif précédent convient bien pour cet usage car il est à la fois capable de détecter de faibles variations de résistance et d'accéder à une gamme de résistances très large.

Voici par exemple des mesures faites sur une thermistance CTN de 47.

60543.81 muS, 47614.688 Ohm
60546.37 muS, 47616.703 Ohm
60595.75 muS, 47655.531 Ohm
60544.06 muS, 47614.883 Ohm
60584.81 muS, 47646.930 Ohm
60583.00 muS, 47645.504 Ohm
60592.37 muS, 47652.879 Ohm
60577.94 muS, 47641.523 Ohm
60593.19 muS, 47653.516 Ohm
60580.44 muS, 47643.488 Ohm
60591.25 muS, 47651.992 Ohm
60569.12 muS, 47634.594 Ohm
60558.19 muS, 47625.992 Ohm 
    	      

À température constante, les variations de résistance sont de l'ordre de 10Ω, ce qui ne réprésente que 1/5000 de la résistance totale. La résistance de la thermistance est une fonction non linéaire de la température (sur une large gamme) mais la relation est à peu près linéaire pour une variation de quelques degrés. Cette thermistance présente une variation d'environ 1 par degré de température. Le dispositif de mesure devrait donc permettre d'accéder à des variations de l'ordre du centième de degré.

Voici un circuit permettant de réaliser la mesure de résistance sur 3 thermistances :

mesureResistance-transistor.svgFigure pleine page

La sélection d'une des trois résistances se fait en fermant l'interrupteur associé et on ouvrant les autres, c.a.d. en mettant l'entrée correspondante du DG441 au niveau bas et les autres au niveau haut (via les sorties D5,D6 et D7 de l'arduino). La résistance interne des interrupteurs CMOS du DG441 est de l'ordre de 50Ω. L'étalonnage des thermistances devra se faire avec ce dispositif afin de tenir compte de cette résistance. Deux thermistances de la même série présente en général des différences de résistance très importantes, donc l'étalonnage est absolument indispensable.

Une autre application, similaire à celle-ci, est la mesure de lumière au moyen de photorésistances. Une photorésistance présente en effet une résistance qui varie très fortement en fonction de la lumière qu'elle reçoit (typiquement de plusieurs MΩ dans l'obscurité à quelques Ω). La méthode est particulièrement intéressante lorsque le l'éclairement est faible. Le temps relativement long permet alors une bonne sensibilité de détection des variations et le temps d'intégration réalise un filtrage passe-bas qui rend la mesure très peu sensible au bruit.

Creative Commons LicenseTextes et figures sont mis à disposition sous contrat Creative Commons.