Capacitance Meter

Hi all,

I am following the tutorial on how to make a capacitance meter here. I have quite high value capacitors to test so I am using a 100R charge resistor and have 3 pins on a Nano all switching simultaneously to give distribute the current through the chip a bit better (rather than pulling >40mA though one pin).

The above works fine, getting accurate numbers.

I have a few 2V7 capacitors, which can't be tested with this 5V circuit. My plan was to put the pin output through a voltage divider (R1=100R, R2=200R) to reduce the charge voltage, and adjust the time constant reading to 63% of the new voltage. However I get a very different time constant (much lower, same order of magnitude). Tried the same with a R1=2k R2=2.2K network and same issue.

I get the feeling I am doing something fundamentally daft here, can anyone spot it?

Code below, thanks to Paul Bader for the original code on the tutorial.

/*  RCTiming_capacitance_meter
     Paul Badger 2008
    Demonstrates use of RC time constants to measure the value of a capacitor

   Theory   A capcitor will charge, through a resistor, in one time constant, defined as T seconds where
      TC = R * C

      TC = time constant period in seconds
      R = resistance in ohms
      C = capacitance in farads (1 microfarad (ufd) = .0000001 farad = 10^-6 farads )

      The capacitor's voltage at one time constant is defined as 63.2% of the charging voltage.

    Hardware setup:
    Test Capacitor between common point and ground (positive side of an electrolytic capacitor  to common)
    Test Resistor between chargePin and common point
    220 ohm resistor between dischargePin and common point
    Wire between common point and analogPin (A/D input)
*/

#define analogPin      A0         // analog pin for measuring capacitor voltage
#define dischargePin   4         // pin to discharge the capacitor
//#define resistorValue  99.2   // change this to whatever resistor value you are using
#define resistorValue  2000.0   // change this to whatever resistor value you are using
#define num_pins 3

char charge_pin[num_pins] = {5, 6, 7};
float resistor[1]  = {resistorValue};
char selector = 1;
unsigned long startTime;
unsigned long elapsedTime;
float microFarads;                // floating point variable to preserve precision, make calculations
float nanoFarads;
float milliFarads;
float farads;
void discharge(char* pin);
long charge(char* pin);
int Vtau;

void setup() {
  // Setup pin modes
  for (int i = 0; i < num_pins; i++) {
    pinMode(charge_pin[i], OUTPUT);
    digitalWrite(charge_pin[i], LOW);
  }
  pinMode(dischargePin, OUTPUT);
  pinMode(analogPin, INPUT);

  // Set charge pins hig, read in the voltage and calculate 63%. Allows for changing potential without needing to reprogramme
  pinMode(A1, OUTPUT); digitalWrite(A1, HIGH);
  delay(1000);
  analogReference(EXTERNAL);
  for (int i = 0; i < num_pins; i++) {
    pinMode(charge_pin[i], OUTPUT);
    digitalWrite(charge_pin[i], HIGH);
  }
  delay(100);
  Vtau = 0.63 * analogRead(analogPin);
  for (int i = 0; i < num_pins; i++) {
    pinMode(charge_pin[i], OUTPUT);
    digitalWrite(charge_pin[i], LOW);
  }

  Serial.begin(115200);             // initialize serial transmission for debugging
  Serial.print("\n\nCapacitance Sensor at ");
  Serial.print((float)Vtau * 0.00488 / 0.63, 2);
  Serial.println("V\n\n");
}

void loop() {
  /* dicharge the capacitor  */
  discharge(charge_pin);

  elapsedTime = charge(charge_pin);

  // convert microseconds to seconds ( 10^-6 )
  farads = (float)elapsedTime * 1e-6 / resistor[0];
  Serial.print(elapsedTime);       // print the value to serial port
  Serial.print("uS\t");         // print units and carriage return

  if (elapsedTime <= 2) Serial.println("Not connected");
  else if (farads >= 1.0) {
    Serial.print(farads, 1);      // print the value to serial port
    Serial.println("F");         // print units and carriage return
    selector = 0;
  }
  else if (farads > 10e-3) {
    milliFarads = farads * 1e3;
    Serial.print(milliFarads, 1);      // print the value to serial port
    Serial.println("mF");         // print units and carriage return
    selector = 1;
  }
  else if (farads > 10e-6) {
    microFarads = farads * 1e6;
    Serial.print(microFarads, 1);      // print the value to serial port
    Serial.println("uF");         // print units and carriage return
    selector = 2;
  }
  else
  {
    nanoFarads = farads * 1e9;      // multiply by 1000 to convert to nanoFarads (10^-9 Farads)
    Serial.print(nanoFarads, 1);        // print the value to serial port
    Serial.println("nF");          // print units and carriage return
    selector = 3;
  }
}


long charge(char* pin) {
  for (int i = 0 ; i < num_pins ; i++) {
    pinMode(pin[i], OUTPUT);
    digitalWrite(pin[i], HIGH);  // set chargePin HIGH and capacitor charging
  }
  startTime = micros();
  Serial.print("Charging...");
  while (analogRead(analogPin) < Vtau) {     // 647 is 63.2% of 1023, which corresponds to full-scale voltage
  }
  return micros() - startTime;
}

void discharge(char* pin) {
  Serial.print("Discharging...");
  for (int i = 0; i < num_pins; i++) {
    pinMode(pin[i], INPUT);
  }
  while (true) {       // wait until capacitor is completely discharge
    digitalWrite(dischargePin, HIGH);
    delay(100);
    if (analogRead(analogPin) <= 0) {
      digitalWrite(dischargePin, LOW);
      delay(100);
      if (analogRead(analogPin) <= 0) break;
    }
  }
  return;
}

The Thevenin equivalent of a voltage divider 5V-100R-200R-Gnd is:

3.33V-66.67R

You said a different time constant, "lower". Did you mean shorter? That would make sense, with only 67 ohms.

How about a 2.5V regulator with a 100 ohm resistor? The voltage at 63.2% will be half that at 5V.

I would discharge it through an external transistor, either NPN bipolar or MOSFET, rather than through the Arduino. How are you dividing the current up between the 3 pins? Separate resistors? If not, you cannot guarantee that one pin isn't current hogging.