Capacimètre spécial petites capacités, de 0,1 à 100 pF

Bonjour,
Je vous propose en partage mon capacimètre destiné à la mesure de faibles capacités.

Pourquoi?
Il existe déjà des capacimètres Arduino!
Cependant ils ont tous en commun de ne pas être efficace en dessous d'une dizaine de pF.
Ce capacimètre a donc été conçu pour y remédier.
Pour les capacités supérieures à 100pF vous pourrez utiliser un de ceux-là:
http://www.circuitbasics.com/how-to-make-an-arduino-capacitance-meter/

Ils utilisent d'autres algorithmes mieux adaptés aux capacités plus élevées (analogueRead).
Voir le tableau pour choisir le mieux adapté en fonction des capacités à mesurer.

Ce capacimètre permet la mesure de petites capacités de l'ordre du picoFarad avec une précision d'environ 3% avec un bon calibrage. Ce qui est difficile à obtenir avec un capacimètre du commerce (du moins je n'en connais pas, d'où ce programme).

Son domaine d'application concerne essentiellement la mesure des capacités parasites sur les circuits H.F.

L'étalonnage se fait en ajustant la constante K. Après après avoir soustrait l'offset avec la touche "c" on teste un condensateur de 100pF étalonné. Si la valeur lue est inférieure à la valeur réelle, on augmente la valeur de K et inversement.
Sans étalonnage, la précision est de l'ordre de 5%.

/* Capacimètre spécial faibles valeurs, de 0,1 à 100pF
 * Auteur Christophe JUILLET
 *  
 * A0 broche de lecture du condensateur
 * A1 broche de charge du condensateur
 * 
 * Le condensateur est relié à la masse et à la broche A0
 * La résistance R1 est reliée à la broche A0 et à la broche A1
 * Les broches doivent être A0 et A1
 * 
 * seuil = 1-(1/e^c) où c est la constante de temps
 * constante de temps = ln (1-Vseuil/VCC) où Vseuil est la tension de bascule 
 */

#define R1  2200 // résistance de charge en KiloOhm (entre 1,5 et 3,3MOhm) compromis idéal à 2,2MOhm
#define K 0.059 // K = 0.059 coefficient correspondant à une constante de temps de 0,693 (seuil à 0,5*VCC) à ajuster pour calibrage

void setup() {
  Serial.begin(115200);
  TCCR1A = 0; // Timer 1 en mode compteur
  TCCR1B = 1; // prédiviseur du timer 1 à 1
  pinMode(A1, OUTPUT);
  Serial.println(F("Tapez \"0\" pour lire la valeur du condensateur\n\"c\" pour calibrer le capacimetre (a vide)\n\"p\" pour une mesure precise\n\"r\" pour une mesure rapide (par defaut)"));
}

void loop() {
  static long offset = 0;
  static unsigned imax = 2048;
  static bool precis = false;
  static float c; // capacité en pF
  
  if (Serial.available()) {
    char touche = Serial.read();
    if (touche == '0') {
      digitalWrite(A1, HIGH);
      delayMicroseconds(400); // test dépassement de capacité
      bool over = !digitalRead(A0);
      digitalWrite(A1, LOW);
      if (over) {
        Serial.println(F("Capacite superieure a 100pF"));
      }
      else {
        long tt = mesure(imax);         
        precis ? tt >>= 2 : tt <<= 1;
        c = (tt - offset) / (float) R1 * K;
        Serial.print(c, precis ? 2 : 1);
        Serial.println("pF");
      }
    }
    if (touche == 'c') {
      Serial.println(F("Calibrage offset en cours..."));
      offset = mesure(65536L);
      offset /= 16;      
      c = offset / (float) R1 * K;
      Serial.print(F("Capacite parasite: "));
      Serial.print(c, 2);
      Serial.println("pF");
    }
    if (touche == 'p') {
      imax = 16384;
      precis = true;
      Serial.println("Mode precis");
    }
    if (touche == 'r') {
      imax = 2048;
      precis = false;
      Serial.println("Mode rapide");
    }
  }
}

long mesure(long imax) {
  long tt = 0;
  int t;

  pinMode(A0, OUTPUT);
  delayMicroseconds(100); // vider le condensateur
  for (long i = 0; i < imax; i++) { // on répète la mesure afin d'améliorer la précision
    pinMode(A0, INPUT);
    byte oldSREG = SREG;
    cli();
    bitSet(PORTC, 1); // broche A1 HIGH
    TCNT1 = 0;
    asm volatile(
      "boucle:\n" // 3 cycles horloge
      "sbis 0x06, 0\n" // PINC 0 broche A0
      "rjmp boucle\n"
    );
    t = TCNT1;
    SREG = oldSREG;
    digitalWrite(A1, LOW); // vider le condensateur
    pinMode(A0, OUTPUT);
    tt += t / 3;
  }
  pinMode(A0, INPUT);
  return tt;
}

merci pour le partage, ça semble un projet fort utile :wink:

J'ai réalisé avec succès ce capacimètre. Pour des contrainte de temps réel souhaiterais limité imax à 256 au détriment de la précision. Comment modifier le code ? Merci

superair78:
J'ai réalisé avec succès ce capacimètre. Pour des contrainte de temps réel souhaiterais limité imax à 256 au détriment de la précision. Comment modifier le code ? Merci

Bonjour,
Par défaut imax vaut 2048 (en mode rapide), donc si tu remplaces imax par 256 tu dois multiplier le résultat stocké dans la variable tt (addition des mesures) par 8 pour compenser.
Mais tu divises la précision de la mesure par sqrt8

Une application de ton capacimètre :

superair78:
Une application de ton capacimètre :

Sympa, je n'avais pas pensé à cette application. :slight_smile:

Juste quelques remarques:

1 arduino pro mini ATmega328 (5V, 16MHz) à 2 euros l’arduino pro mini 3.3V, 8MHz, n’est pas assez rapide. «Vous êtes prévenus»

Je suppose que l'avertissement concerne le reste du code, pour le capacimetre, 8Mhz suffisent, mais il faut doubler la variable tt pour compenser, encore que dans ton cas ce n'est pas important, pas plus que la variable k, car tu ne mesures pas une capacité mais un ratio entre deux capacités.

En revanche, on suppose que la valeur de capacité reste quasi proportionnelle au niveau de carburant dans le réservoir.

Ce n'est pas le cas, en particulier si le réservoir est cylindrique (tu peux faire une abaque, si tu veux un résultat précis).

Les avertis me diront que la datasheet indique que l’alimentation du GY 521 ne doit pas dépasser 3.3V mais avec une batterie NiMH de 4 éléments ou avec l’alimentation Vcc de l’arduino ça passe…

Oui il faut ajouter un régulateur 3.3V sous peine de destruction rapide (les entrées par contre supportent le 5V).

Dans mon application, la valeur de la capacité parasite est de l’ordre de 40 pF (c’est beaucoup)

En l'absence de carburant, tu obtiens un condensateur disque à air, donc rien d'anormal.

Beau travail. :slight_smile: