Küçük kapasitansın kaydedilmesi

Bir multimetre kullanarak bir sistemin kapasitansını ölçüyorum ve değerin çok küçük olduğunu tespit ettim (50pF'den 100 pF'ye dalgalanıyor). Sistem dinamiktir, dolayısıyla kapasite zamanla değişir.

Şimdi bu değeri bir metin dosyasına kaydetmem gerekiyor (örneğin, csv). Bunu Arduino ile nasıl yapabilirim? Direnç ise, basit bir voltaj bölücü kurabilir ve ADC'yi kullanarak voltajı algılayabilirdim. Ayrıca C çok küçük, C için bazı ölçüm devresi yapamadım.

5
Kapasitif bir algılama uygulamasıdır.
katma yazar roetnig, kaynak
Ne kadar hassasiyet gereklidir? Kapasitansın kesin bir ölçüsüne sahip olmanız mı gerekiyor yoksa bir açma koşulunu tespit etmeniz yeterli mi? Başvurunuz nedir
katma yazar Arperum, kaynak

6 cevap

The standard way to measure a resistance with an Arduino is to build a voltage divider by putting it in series with a known resistance. I have tried the same approach for measuring capacitances, and it turns out it works well in the 100 pF range! The circuit is like this:

  ┌───────────── Arduino digital output
  │
──┴── known
──┬── cap
  │
  ├───────────── Arduino analog input
  │
──┴── unknown
──┬── cap
  │
 GND

Tek yakalamak, ölçümü nispeten hızlı bir şekilde yapmanız gerektiğidir. Aksi takdirde kaçak dirençlerin oranını ölçüyorsunuz. İşte ölçüm protokolü:

  1. Set both pins to OUPUT LOW in order to discharge both capacitors.
  2. Delay for one or two CPU cycles to make sure they are fully discharged.
  3. Set the analog input pin to INPUT mode: this will make it high impedance and isolate the node connected to it.
  4. Set the digital output to HIGH: this will charge the two capacitors in series to 5 V.
  5. Delay for one or two CPU cycles for the voltage to stabilize.
  6. Take an analog reading.

Şimdi kapasitansı aynısını kullanarak okumadan türetebilirsiniz. dirençlerle kullanacağınız formül, yalnızca empedanslarla (veya 1/C) dirençler yerine:

C_unknown = C_ref × (1024 − reading) ÷ reading;

Aynı formül, düğümün bağlı olduğu dikkate alınarak türetilebilir. Her kondansatörün bir plakasını içeren analog giriş, sıfır net ücret.

Dikkat çekmeye değer birkaç şey:

  • You will get the best resolution by choosing the reference capacitance close to the one you want to measure.
  • The delays are not actually needed: as the capacitors charge and discharge very fast, a single CPU cycle is about 24 time constants.
  • If you were to measure large capacitances (several nanofarads) with this setup, you would want protective resistors in series with the Arduino pins, but then the delays become mandatory. In the 100 pF range I would not worry about the in-rush currents.
  • If the delay in step 5 is too long, your measurement will be affected by the leakage of the caps and the analog input pin.
  • You need not worry about the 14 pF cap on the sample and hold circuit: it will slightly affect the very first measurement but, once that cap is charged, subsequent measurement will not be affected as long as the unknown cap does not change to much between consecutive measurements. You do need to calibrate out the stray capacitance of the pin and probes.
2
katma

Küçük sabit kapasitans değerinin RC sabit kestirimi üzerinden ölçülmesi esasen kesin zaman ölçümü gerektirir. ATmega çipleri, her saat döngüsünü artırmak üzere programlanabilen TCNT1 zamanlayıcıya sahiptir, ve ACSR kaydında bit ACIC kullanarak bir karşılaştırıcı tarafından durdurulabilir. 16 MHz'de bir sayaç çalıştırmak, size picofarad aralığında kapasite ölçümleri için yeterli olan 62,5 ns'lik bir çözünürlük verecektir. İşte bu kodu kullanan bir kod örneği ölçüm tekniği

AnalogRead is about 1000 times slower, so you'll be limited to nF range if you use it.

Böyle küçük bir kapasitansı ölçerken sisteminizi kalibre etmeniz gerektiğini unutmayın. Bu, sondalar bağlıyken ancak hedef sistem olmadan bir ölçüm gerçekleştirerek yapılır. Sisteminizin tek başına kapasitansını elde etmek için daha sonra bu kapasitans değerini (kullandığınız problara bağlı olarak tipik olarak 20-50 pF) çıkaracaksınız.

2
katma

PF kadar küçük kapasitans için, RC zaman sabiti yöntemi bir Arduino kartı üzerinde kirli sonuçlar verir.

Bir "kapasitans bölücü" devre oluşturmak ve küçük bir gerilim bölücü devreden direnç alacağınız gibi hesaplamak için küçük kapasitansta (Pf'in kendisinde olan) yerleşik Arduino pinlerini kullanabilirsiniz.

See this excellent post by Nethercott for reference Arduino capacitance meter

1
katma
Teşekkür ederim :-) Bu haklı olduğunuzu hayal ediyorum, ancak bu metodu sınırlarına kadar uzatma şansım olmamıştı. Onunla olan deneyimimden, günlük bir ortamda bir Arduino Uno kartı ve 15 cm uzunluğunda normal jumper telleri kullanarak tatmin edici sonuçlar elde ettim.
katma yazar christoff, kaynak
Güzel bul, + 1! Parazitik pin özelliklerine dayanarak, bu yöntemin ne kadar kesin göründüğüne şaşırdım. Her ne kadar bunun sadece iyi EMI koruması ile veya EMI'siz koşullarda iyi çalıştığını farz ediyorum.
katma yazar nreich, kaynak

(50pF ila 100 pF arasında dalgalanma).

a few ways for such small values -> assuming you can really read it like a capacitor.

1) form a lc tank and measure its frequency -> most effective in measuring small value capacitance. but needs precision inductor/calibration, and is subject to parasitics.

2) bir CCS üzerinden şarj edin/boşaltın: ve zamanı ölçün. Bir ccs kadar basit, büyük bir direnç vasıtasıyla oluşturulabilir. gerçekten küçük kapasitans ile etkili değil;

3) charge transfer: using the capacitance of the adc. very effective against small capacitance: < 10x of adc capacitance. needs calibration.

her birinin kendi sorunları var.

1
katma
CCS nedir?
katma yazar nreich, kaynak

Ölçülecek kapasitans 1 nF'nin (50-100 pF) çok altında olduğundan, giriş kapasitansı nedeniyle (veri sayfasına göre 14 pF) Arduino'nun ADC'si ile ölçmeye çalışırken ciddi sorunlarla karşılaşırsınız. Kabloların, başlıkların ve Arduino panelinin başıboş kapasitelerini ekleyin; ölçmeye çalıştığınız şeyle aynı büyüklükte olan (= ÇOK KÖTÜ BİR) sırayla 25 pF'lik giriş kapasitansı ile kolayca bitirin.

Ne yapmalı o zaman? Ana seçenekler bunlar ...

Harici bir ölçüm devresi kullanın

Bu, aktif cihazlar (op amper, karşılaştırıcı, zamanlayıcılar ...) ve hassas pasif bileşenler dahil anlamına gelir. Gerçek bir HW tabanlı çözüm.

Bu durumda ölçümün doğruluğu tamamen dış devrenin tasarımına (devre topolojisi ve bileşen seçimi) bağlı olacaktır. Devre, ilave herhangi bir önemli hataya neden olmadan, bir analog voltaj veya frekansı Arduino tarafından ölçülebilen bir sinyal sağlayacaktır.

555 zamanlayıcı kullanan bir örnek (daha fazla doğruluk için OUT ile TH arasında 4 pF ek kapasitör gerekir):

555 timer capacitance meter

Frequency vs capacitance

Source: Use Analog Techniques To Measure Capacitance In Capacitive Sensors, an article by Martin Tomasz published in Electronic Design.

Harici devreyi bir "sensör" veya "sensör" (ölçülecek kapasitans) için bir sinyal koşullandırma devresi olarak düşünün. Aslında, ölçmeye çalıştığınız dinamik kapasitans muhtemelen bir sensörden (nem, nem?) Geliyor, değil mi?

Kondansatörü doğrudan Uno'nun analog pinlerine bağlayın ve okumaları kalibre edin

Kulağa şaşırtıcı gelebilir, ancak bu işe yarayan kadar basit bir şey (elbette doğruluk pahasına):

Uno as capacitance meter

O nasıl? Çünkü başlangıçta tespit ettiğimiz giriş kapasitans sorunu hassasiyeti ciddi şekilde azaltacak kadar büyüktür, ancak ölçümü tamamen olanaksız kılmaz. Bu nedenle, bu etkiyi kalibre edebiliriz ve hala hedef aralıkta (50-100 pF) geçerli (düşük doğrulukta olmasına rağmen) bir ölçüm var.

Kalibrasyon, aşağıdaki Arduino eskizinde bazı kodlanmış varsayılan değerler aracılığıyla yapılır (braulio777'deki kaynak buradaki ). Daha iyi doğruluk için, bazı kapasitörlerin ölçümlerini önceden bilinen kapasitans değerleri ile karşılaştırarak (krokide yapabileceğiniz), eskizdeki IN_STRAY_CAP_TO_GND ve R_PULLUP değerlerini kalibre etmelisiniz.

//Digital Capacitance Meter
//Measuring from 0.000pF to 1000uF

#include 
LiquidCrystal lcd(11, 9, 5, 4, 3, 2);
const int OUT_PIN = A4;
const int IN_PIN = A0;
const float IN_STRAY_CAP_TO_GND = 24.48;
const float IN_CAP_TO_GND  = IN_STRAY_CAP_TO_GND;
const float R_PULLUP = 34.8;  
const int MAX_ADC_VALUE = 1023;

void setup()
{
  pinMode(OUT_PIN, OUTPUT);
  pinMode(IN_PIN, OUTPUT);
  lcd.begin(16, 2);
  }

void loop()
{
    pinMode(IN_PIN, INPUT);
    digitalWrite(OUT_PIN, HIGH);
    int val = analogRead(IN_PIN);
    digitalWrite(OUT_PIN, LOW);

    if (val < 1000)
    {
      pinMode(IN_PIN, OUTPUT);

      float capacitance = (float)val * IN_CAP_TO_GND/(float)(MAX_ADC_VALUE - val);

      lcd.setCursor(0,0);
      lcd.print("Capacitance = ");
      lcd.setCursor(0,1);
      lcd.print("                ");
      lcd.setCursor(0,1);
      lcd.print(capacitance, 3);// for the best precision
      lcd.print("pF ");

    }

    else
    {
      pinMode(IN_PIN, OUTPUT);
      delay(1);
      pinMode(OUT_PIN, INPUT_PULLUP);
      unsigned long u1 = micros();
      unsigned long t;
      int digVal;

      do
      {
        digVal = digitalRead(OUT_PIN);
        unsigned long u2 = micros();
        t = u2 > u1 ? u2 - u1 : u1 - u2;
      } 

      while ((digVal < 1) && (t < 400000L));

      pinMode(OUT_PIN, INPUT);  
      val = analogRead(OUT_PIN);
      digitalWrite(IN_PIN, HIGH);
      int dischargeTime = (int)(t/1000L) * 5;
      delay(dischargeTime);   
      pinMode(OUT_PIN, OUTPUT);  
      digitalWrite(OUT_PIN, LOW);
      digitalWrite(IN_PIN, LOW);

      float capacitance = -(float)t/R_PULLUP
                             /log(1.0 - (float)val/(float)MAX_ADC_VALUE);

      lcd.setCursor(0,0);
      lcd.print("Capacitance = ");
      if (capacitance > 1000.0)
      {
        lcd.setCursor(0,1);
        lcd.print("                ");
        lcd.setCursor(0,1);
        lcd.print(capacitance/1000.0, 2);
        lcd.print("uF ");

      }

      else
      {
        lcd.setCursor(0,1);
        lcd.print("                ");
        lcd.setCursor(0,1);
        lcd.print(capacitance, 2);
        lcd.print("nF ");

      } 

    while (millis() % 1000 != 0);
}
    }

Yukarıdaki örnek kod, ölçülen değerleri bir LCD ekrana gönderir. Amacınız için en iyi seçenek muhtemelen harici bir SD karta veri yazmaktır.

Disclosure: I have not tested the code above myself.

1
katma

Her Arduino kapasitans ölçer, zaman sabiti olan direnç kapasitör (RC) devrelerinin özelliğine dayanır. Bir RC devresinin zaman sabiti, tam şarj olduğunda kapasitördeki voltajın voltajının% 63.2'sine ulaşması için geçen süre olarak tanımlanır. Daha büyük kapasitörlerin şarj edilmesi daha uzun sürer ve bu nedenle daha büyük zaman sabitleri oluşturur. Bir RC devresindeki kapasitans, denklemin zaman sabiti ile ilgilidir:

TC = R x C

where TC = time constant in seconds R = resistance in ohms C = capacitance in farads

Kapasitans için çözmek üzere denklemin yeniden düzenlenmesi şunları verir:

C = TC/R

schematic

simulate this circuit – Schematic created using CircuitLab

Example: 1 megohm * 1 microfarad = 1 second enter image description here

Her kapasitans ölçer, bilinen direnç değerlerine ve bilinmeyen bir kapasitör değerine sahip bir RC devresine sahiptir. Arduino, kapasitördeki voltajı ölçecek ve tam olarak şarj olduğunda (zaman sabiti) voltajının% 63.2'sine ulaşmak için geçen süreyi kaydedecektir. Direnç değeri zaten bilindiğinden, yukarıdaki formülü bilinmeyen kapasitansı hesaplayacak bir programda kullanabiliriz.

Kapasitansınız Pico Farad Range'de çok Küçük olduğundan, kapasitansı analog piminiz üzerinden bu şekilde ölçebilirsiniz ... Şematik Kondansatörünüzün doğada dinamik olduğu için en az 10 değer almanız ve doğru değeri elde etmek için ortalama vermeniz gerektiğini söylediniz.

Ölçüm kodu pF aralığında düşük kapasitans

const int OUT_PIN = A5;
const int IN_PIN = A0;
const float IN_STRAY_CAP_TO_GND = 24.48;
const float IN_CAP_TO_GND  = IN_STRAY_CAP_TO_GND;
const float R_PULLUP = 34.8;  
const int MAX_ADC_VALUE = 1023;

void setup()
{
  pinMode(OUT_PIN, OUTPUT);
  pinMode(IN_PIN, OUTPUT);
  Serial.begin(9600);
}

void loop()
{
    pinMode(IN_PIN, INPUT);
    digitalWrite(OUT_PIN, HIGH);
    int val = analogRead(IN_PIN);
    digitalWrite(OUT_PIN, LOW);

    if (val < 1000)
    {
      pinMode(IN_PIN, OUTPUT);

      float capacitance = (float)val * IN_CAP_TO_GND/(float)(MAX_ADC_VALUE - val);

      Serial.print(F("Capacitance Value = "));
      Serial.print(capacitance, 3);
      Serial.print(F(" pF ("));
      Serial.print(val);
      Serial.println(F(") "));
    }
    else
    {
      pinMode(IN_PIN, OUTPUT);
      delay(1);
      pinMode(OUT_PIN, INPUT_PULLUP);
      unsigned long u1 = micros();
      unsigned long t;
      int digVal;

      do
      {
        digVal = digitalRead(OUT_PIN);
        unsigned long u2 = micros();
        t = u2 > u1 ? u2 - u1 : u1 - u2;
      } while ((digVal < 1) && (t < 400000L));

      pinMode(OUT_PIN, INPUT);  
      val = analogRead(OUT_PIN);
      digitalWrite(IN_PIN, HIGH);
      int dischargeTime = (int)(t/1000L) * 5;
      delay(dischargeTime);   
      pinMode(OUT_PIN, OUTPUT);  
      digitalWrite(OUT_PIN, LOW);
      digitalWrite(IN_PIN, LOW);

      float capacitance = -(float)t/R_PULLUP
                             /log(1.0 - (float)val/(float)MAX_ADC_VALUE);

      Serial.print(F("Capacitance Value = "));
      if (capacitance > 1000.0)
      {
        Serial.print(capacitance/1000.0, 2);
        Serial.print(F(" uF"));
      }
      else
      {
        Serial.print(capacitance, 2);
        Serial.print(F(" nF"));
      }

      Serial.print(F(" ("));
      Serial.print(digVal == 1 ? F("Normal") : F("HighVal"));
      Serial.print(F(", t= "));
      Serial.print(t);
      Serial.print(F(" us, ADC= "));
      Serial.print(val);
      Serial.println(F(")"));
    }
    while (millis() % 1000 != 0)
      ;    
}
1
katma
−1: Bu yöntem bu kadar küçük kapasitanslar için gerçekten uygun değil: delicesine büyük bir direnç değerine ihtiyacınız olacak, aksi halde zaman sabiti iyi bir ölçüm yapmak için çok kısa olacaktır. Bir RC zaman sabiti ölçümü yapmak istiyorsanız, bunun yerine Dmitry Grigoryev'in cevabında açıklanan yöntemi kullanmalısınız.
katma yazar Sprogz, kaynak
“Bir fikir” ve daha sonra bu fikirden çok farklı bir şey yapan bir kod parçası verdiniz. Bu kodu yazdıysanız, gerçekte ne yaptığını neden açıklamıyorsunuz? Değilse, neden orijinal yazara kredi vermiyorsunuz?
katma yazar Sprogz, kaynak
Peki ya arduino pinlerinin yük kapasiteleri?
katma yazar Arperum, kaynak
ATmega328 veri sayfasına göre 14 pF civarında. Konfor için ölçüm aralığına çok yakın. Ayrıca kablolardan ve Uno panelinden ve başlıklarından kaynaklanan her türlü başıboş kapasitans.
katma yazar Arperum, kaynak
Evet haklısın. Ama ben bunu tattım ve bana çok iyi ve net bir sonuç vermedim, tatmin edici değil. Sakin ol dostum Ben onun sorunu için çözümler değil, genel bir fikir verdim.
katma yazar Inky1980, kaynak