As part of a soil humidity monitoring system, I needed to test how much the water (used as a dielectric) can influence the capacitance between two metal plates inserted into the ground. The capacitance is very small, in the pF range, so this got me searching for a simple way (yet hopefully accurate) to get an idea of ranges I had to work with.
Luckily somebody else did the heavy lifting by coming up with an ingenious way of measuring very small capacitance using an Arduino UNO. I’m trying to expand on Jonathan blog by presenting my results using an Arduino Leonardo as well as a Seeeduino Lite v1.0b board that I have at hand (I don’t own any Arduino UNO).
I’ve also employed an OLED screen so that I can see the measurement next to where I will be using the capacitor.
The capacitor on the left is the one to be measured (connected between A0 and A2 inputs). The OLED screen has a resolution of 128×64 pixels (mono) and works on I²C bus. No other parts needed!
Leonardo board seems to have the same IN_STRAY_CAP_TO_GND = 24.48 requirement as the Arduino UNO, but playing around with the Seeeduino Lite board (Leonardo equivalent), I had to modify IN_STRAY_CAP_TO_GND = 26.4 to get it to offer similar results as the Leonardo for the pF capacitors I have been measuring.
#define OLED_RESET 6
const int OUT_PIN = A2;
const int IN_PIN = A0;
//Capacitance between IN_PIN and Ground
//Stray capacitance is always present. Extra capacitance can be added to
//allow higher capacitance to be measured.
const float IN_STRAY_CAP_TO_GND = 26.40; //initially this was 30.00, then 24.48 (for seeeduino lite 26.40)
const float IN_EXTRA_CAP_TO_GND = 0.0;
const float IN_CAP_TO_GND = IN_STRAY_CAP_TO_GND + IN_EXTRA_CAP_TO_GND;
const int MAX_ADC_VALUE = 1023;
//digitalWrite(OUT_PIN, LOW); //This is the default state for outputs
// by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3D (for the 128x64)
// init done
// Clear the buffer.
// Set text size and color
//Capacitor under test between OUT_PIN and IN_PIN
//Rising high edge on OUT_PIN
int val = analogRead(IN_PIN);
//Clear everything for next measurement
//Calculate and print result
float capacitance = (float)val * IN_CAP_TO_GND / (float)(MAX_ADC_VALUE - val);
Serial.print(F("Capacitance Value = "));
Serial.print(F(" pF ("));
display.clearDisplay(); // clear buffer
display.print("A0 -||- A2");
while (millis() % 500 != 0);
I had few caps lying around plus few close up pics of the some caps being measured:
The results below were obtained from Leonardo running the code with IN_STRAY_CAP_TO_GND = 24.48 and from Seeeduino Lite running the code with IN_STRAY_CAP_TO_GND = 26.4.
Circuit provides stable measurements when powered from my laptop’s USB port or when using a 3xAA batteries on the Vcc pin. However, when powered from rechargeable power banks (tried two of them), measurements were allover the place with about 10% variation and randomly changing. I noticed a small 50mV ripple on the oscilloscope – while the laptop’s power supply has a really flat output independent of the demand of the circuit.
Touching any of the leads (or the board around the ports area) will mess up with the measurement.
I had no way to estimate the input capacitance of the Seeeduino board (like the the original article for the UNO) so the 26.4 value of IN_STRAY_CAP_TO_GND was obtained by trial and error so that the Seeeduino results match the Leonardo across all the measured values.