Measuring pF capacitance change in an EAP

Hi, im having a bit of trouble getting stable readings from an Electroactive Polymer (EAP) sensor Im using. Basically, it behaves as a variable capacitor when stretched. The capacitance range is between c. 1.24nF - 2.2nF, so not lots to go on.

Im using an astable 555 timer circuit to send a frequency to the arduino. As I know accurately the resistors Im using as R1 and R2, I should be able to calculate the capacitance of the EAP sensor.

It works to a degree, but is not consistant. Obviously environmental changes will affect it, but Ive tried to write some calibration code to sort that. Even still, the readings can jum around a litte, and when the EAP goes from stretched to unstretched the values returned are minus?!

ill apologise for my hastily written scruffy code in advance, but hopefully you can get the jist of it.

If anyone has any ideas as to how to make this more accurate and stable that would be amazing!

PS. ive tried altering previous example of arduino cap measuring (http://arduino.cc/en/Tutorial/CapacitanceMeter) but i dont think the setup is accurate enough

#include <FreqCounter.h>

//freq input pin digital 5

#define R1 22000                                          //precise value measured with an ohm-meter 
#define R2 3260

unsigned long frq;
float cap;
float capMax;
float capMin;
float newCap;
int changeConst = 1000;
int outputVal;
int newOutputVal;
int analogOut = 9;
int baseline;



void setup() {

  analogWrite(analogOut, 255);
  delay(200);
  analogWrite(analogOut, 0);

  Serial.begin(9600);
  baseline = autocalibrate();                             //call autocalibrate function to set baseline value
  Serial.print("baseline Value is: ");
  Serial.println(baseline);
  capMax = (baseline + changeConst);                      //make an estimate of the max cap change for mapping use
}



void loop() {

  // wait if any serial is going on
  FreqCounter::f_comp=10;                                 // Freq Calibration value
  FreqCounter::start(1000);                               // 1000 ms Gate Time

  while (FreqCounter::f_ready == 0) 
    frq=FreqCounter::f_freq;
  Serial.print("freq: ");
  Serial.println(frq);

  cap = 1440000000000.0/((R1+R2)*frq*1.0);                //1.44*1000000000000 is used to get the result in pF
  newCap = (cap-baseline);
  Serial.print("Change in capacitance: ");
  Serial.print(newCap);
  Serial.println("pF");

  outputVal = map(cap, baseline, capMax, 0, 255);         //map the change in capacitance to 0-255 range to work with
  newOutputVal = constrain(outputVal, 0, 255);            //constrain the output to positive values between 0-255
  Serial.print("mapped value: ");
  Serial.println(newOutputVal);
  analogWrite(analogOut, newOutputVal);                   //PWM output for LED brightness

  //delay(20);
}  

int autocalibrate(){
  const int numberVals = 5;                               
  int capVals[numberVals];
  int i = 0;
  int total = 0;
  int averageCap;

  FreqCounter::f_comp=10;                               // freq Calibration value
  FreqCounter::start(1000);                             // 1000 ms Gate Time

  while (FreqCounter::f_ready == 0) 
    frq=FreqCounter::f_freq;
  cap = 1440000000000.0/((R1+R2)*frq*1.0);              //1.44*1000000000000 is used to get the result in pF


  for(i=0; i < numberVals; i++){                      //itterate through the array

    FreqCounter::f_comp=10;                               // freq Calibration value
    FreqCounter::start(1000);                             // 1000 ms Gate Time

    while (FreqCounter::f_ready == 0) 
      frq=FreqCounter::f_freq;
    cap = 1440000000000.0/((R1+R2)*frq*1.0);              //1.44*1000000000000 is used to get the result in pF

    if(cap > 1000){                                          //as long as there is a positive capacitance...
      capVals[i] = cap;                                   //...store value in array
      Serial.println(capVals[i]);                         //print capacitance values to serial monitor
      total = total + capVals[i];                         //re-adjust the running total
    }
  }

  averageCap = total/4;                                   //calculate average cap vale(discarding frist value)
  //for some reason the first value is always 0?!
  return averageCap;                                      //return the average cap val
}

First, when I do Serial.print() I put a delay(200) after that in order to flush the uart buffer as it may disrupt the measurements coming afterwards. The negative values you get are probably coming from the fluctuations against the baseline.
I would calibrate with a stable ~1.5nF (you must know its value precisely) capacitor (ie switched in with a relay or a nfet) each time I am going to measure and based on that I would adjust the calculation.
So:

  1. calibrate against precise capacitor
  2. calculate parameters (basically you want to calculate an "RCAL"=k*(R1+R2) - RCAL will incorporate any changes in temperature and Vcc as well)
  3. do measure EAP
  4. goto 1

Last time I worked with 555 during Falklands, but it seems to me the capacitance calculus is not correct.. Pls double check..

cap = 1440000000000.0/((R1+R2)frq1.0);

thanks for the suggestions pito - Ill give it a go and post my results online to let you know how I get on

if(cap > 1000){                                          //as long as there is a positive capacitance...
      capVals[i] = cap;                                   //...store value in array
      Serial.println(capVals[i]);                         //print capacitance values to serial monitor
      total = total + capVals[i];                         //re-adjust the running total
    }
  }

  averageCap = total/4;

There is "IF" statement, but you always divide by 4, so if there some values below <1000 thay 'd not be counted and overall summ divided by 4 'd be %25 off.
Other things, try to implement averaging code in the main routine as well, with high coefficient. Averaging let say over 100 values you may get 10 times better accuracy, just use right type of variables (long or unsigned long) to avoid overflow.

Hey,

where did you buy EAP?

Thanks,
Gabor