Capacity measurement


Capacitors - as all other parts of electronic equipments - show a certain tolerance given in their specifications. If they are used to suppress the humming of the mains you would not mind if their capacity is even higher than the nominal value, at least as long as they do not destroy the fuse. But especially in analog circuits like filters you surely want to have the exact value. And there are a lot of Arduino projects to measure the value (at least as exact as you can afford). In many cases measuring is done by making the unknown capacitor to a part of an RC oscillator and measure the frequency.

The approach shown here goes a completely different way:
the capacitor to test is charged to the supply voltage via a relay. Then it is discharged with a 1 kΩ resistor by switching the relay. The discharging characteristic is recorded (up to 500 samples) and fitted for an exponential function. The parameters of this function give you the value of its capacity. Unfortunately, you have to do some math and statistics.

/* Kondensator-Messgeraet *  Start: 1.9.2015
 *  improved: 3.11.2015 *  
 *      [A0]
 *       o                 +-------------------< ----+
 *       |                 |                          Cx
 *   +------+              o               +---< ----+
 *   |   /  | . . . . . . . \              |
 *   +------+            o   o             |
 *       |               |   |             |
 *       |               |   o- [+VCC}   [GND]
 *       |  +------+     |
 *       +--+  1 K +-----+---o  [A1]
 *       |  +------+
 *       |
 *       o      
 *     [GND]             
 */

#define PRINT

const byte relaisPin =     A0;
const byte discharge =     A1;
const int nMax       =    500;
long N               =   nMax;
const long R         = 100000;
int v[nMax+1];

void setup() {
  Serial.begin(9600);
  Serial.println(F(__FILE__));
  long t1 = micros();
  long t2 = micros();
  long t0 = t2 - t1;
  pinMode(relaisPin,OUTPUT);
  Serial.println(F("charging"));
  digitalWrite(relaisPin,LOW);
  delay(1000);
  Serial.println(F("discharging\n"));
  digitalWrite(relaisPin,HIGH);
  // wait for the relay to switch and beginning of discharge:
  int neu = analogRead(discharge); 
  int alt;
  do {
    alt = neu;
    neu = analogRead(discharge);
  } while (neu >= alt);  
  Serial.println(F("start reading values"));
  t1 = micros();
  for (int x = 1; x <= N; x++) v[x] = analogRead(discharge);
  t2 = micros();
  digitalWrite(relaisPin,LOW); 
  Serial.println(F("end of reading values")); 
  float dt = (t2 - t1 - t0) / (N - 1);
  Serial.print(F("Total time was dt = "));
  Serial.print(dt);
  Serial.println(F(" microseconds"));
#ifdef PRINT  
  Serial.println(F("The values are"));
  Serial.println("t\tlogs\ty");
#endif  
  float Sx  = 0;
  float Sx2 = 0;
  float Sy  = 0;
  float Sy2 = 0;
  float Sxy = 0;
  for (int x = 1; x <= N; x++) {
    if (v[x] < 15) {
      N = x-1;
      break;
    }
    float y = log(v[x]);
#ifdef PRINT 
    Serial.print(x*dt,0);          // time (microseconds)
    Serial.print(F("\t"));
    Serial.print(point2comma(y));  // log
    Serial.print(F("\t"));
    Serial.println(v[x]);          // raw
#endif
    //Sx  = Sx  + x;
    //Sx2 = Sx2 + x * x;
    Sy  = Sy  + y;
    Sy2 = Sy2 + y * y;
    Sxy = Sxy + y * x;
  }
  Serial.print(F("N = "));
  Serial.println(N);  
  Sx  = N * (N + 1) / 2;
  Sx2 = N * (N + 1) * (2 * N + 1) / 6;
  float m   = (N * Sxy - Sx * Sy) / 
              (N * Sx2 - Sx * Sx);
  float rxy = (Sxy-Sx*Sy/N)/(sqrt(Sx2-Sx*Sx/N)*sqrt(Sy2-Sy*Sy/N));
  Serial.print(F("correlation coefficient: "));
  Serial.println(rxy,5);
  Serial.print(F("m = "));
  Serial.println(m,4);
  Serial.print(F("dt / (m * R) * 1E6 = "));
  Serial.print(-dt / (m * R),4);
  Serial.println(F(" micro Farad"));
}

//----------------------------------------------------

void loop() {}

String point2comma(float x) {
  int i = (int)x;
  String s = String(i) + ",";
  int frac = 1000*x - 1000*i;
  if (frac <  10) s = s + "00" + String(frac); else
  if (frac < 100) s = s + "0" + String(frac); else
  s = s + String(frac);
  return s;
}

The point2comma function was added to offer the opportunity to import the contends of the Serial monitor to spreadsheet software like Excel.




contact: nji(at)gmx.de