Оскільки ємність, що підлягає вимірюванню, значно нижче 1 нФ (50-100 пФ), ви зіткнетеся з серйозними проблемами, намагаючись виміряти її з АЦП Arduino через його вхідну ємність (14 пФ відповідно до таблиці). Додайте блукаючі ємності проводів, заголовків і самої плати Arduino, і ви легко вийде з вхідною ємністю 25 пФ, яка знаходиться в тому ж порядку, що й ви намагаєтеся виміряти (= ДУЖЕ ПОРУЧЕННЯ).
Що ж робити? Ну, основні варіанти це ...
Використовуйте зовнішню схему вимірювання
Це означатиме включення активних пристроїв (операційні підсилювачі, компаратори, таймери ...) і точні пасивні компоненти. Істинне рішення на основі HW.
Точність вимірювання в цьому випадку була б повністю залежати від конструкції (топологія та вибір компонентів) зовнішнього контуру. Схема буде забезпечувати або аналогову напругу, або сигнал, частота якого може бути виміряна Arduino без додаткових значних помилок.
Приклад з використанням таймера 555 (необхідний додатковий компенсаційний конденсатор на 4 пФ між OUT і TH для підвищення точності):


Source: Use Analog Techniques To Measure Capacitance In Capacitive Sensors, an article by Martin Tomasz published in Electronic Design.
Подумайте про зовнішній контур як про «датчик» або про схему підготовки сигналу для «датчика» (ємність, яку потрібно виміряти). Насправді, динамічна ємність, яку ви намагаєтеся виміряти, ймовірно, надходить від датчика (вологість, вологість?), Чи не так?
Підключіть конденсатор безпосередньо до аналогових контактів Uno і калібруйте показання
Це може здатися дивовижним, але чимось простим, як це працює (за рахунок точності, звичайно):

Як це? Тому що проблема вхідної ємності, яку ми виявили на початку, достатньо велика, щоб серйозно пошкодити точність, але не робить вимірювання абсолютно неможливим. Таким чином, ми можемо відкалібрувати цей ефект і все ще мати дійсний (хоча і з пониженою точністю) вимірювач в цільовому діапазоні (50-100 пФ).
Калібрування виконується через деякі типові значення за замовчуванням у наступному ескізі Arduino (джерело тут з braulio777). Для більшої точності ви повинні калібрувати значення IN_STRAY_CAP_TO_GND
і R_PULLUP
в ескізі, порівнюючи вимірювання деяких конденсаторів з їх вже відомими значеннями ємності (за умови, що це можна зробити).
//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);
}
}
Наведений вище приклад коду виводить виміряні значення на РК-дисплей. Найкращим варіантом для вашого призначення є запис даних на зовнішню SD-карту.
Disclosure: I have not tested the code above myself.