Hmmm, powering my board off and on again seems to have cleared that, which is a bit worrying. There must be a register that isn't being set up properly.
Anyway, using my code above with slight amendments, I now get what looks like a "faster" and more consistent reading:
Capacitance = 47.33 nF
Capacitance = 47.33 nF
Capacitance = 47.33 nF
Capacitance = 47.33 nF
Capacitance = 47.34 nF
Capacitance = 47.34 nF
Capacitance = 47.33 nF
Capacitance = 47.33 nF
Capacitance = 47.33 nF
Capacitance = 47.31 nF
Capacitance = 47.34 nF
Capacitance = 47.36 nF
Capacitance = 47.33 nF
Previously I was getting something like 47.9 nF.
Unless my calculations are out, that would be accounted for by the time taken to service the interrupt (say, 2 or 3 uS). Since we are dividing by 10000, that accounts for the decimal place being out by around 5 (well, almost). Maybe my reference voltage was slightly different.
Re-testing with the older sketch, and not touching the reference voltage, I get:
Capacitance = 47.51 nF
Capacitance = 47.51 nF
Capacitance = 47.56 nF
Capacitance = 47.56 nF
Capacitance = 47.57 nF
Capacitance = 47.56 nF
Capacitance = 47.58 nF
So the improved one is about 0.2 nF lower, which is about right for servicing an interrupt (2 uS).
Now incorporating the suggested voltage divider with fixed value resistors, and allowing for that in the sketch, I have this:
/*
Capacitance meter
Author: Nick Gammon
Date: 2 July 2013
Pulse pin (D2): Connect to capacitor via 10K resistor (Rc)
Reference voltage connected to D7 (AIN1) as per below.
Measure pin (D6 - AIN0) connected to first leg of capacitor, other leg connected to Gnd.
Like this:
Capacitor to test:
D2 ----> Rc ----> D6 ----> capacitor_under_test ----> Gnd
Reference voltage:
+5V ----> R2 ---> D7 ---> R1 ----> Gnd
*/
const byte pulsePin = 2; // the pin used to pulse the capacitor
const float Rc = 10000.0; // charging resistor
const float R1 = 1000; // between ground and D7
const float R2 = 1800; // between +5V and D7
const float clockRate_us = 16; // 16 MHz
const float k = 1000 / (clockRate_us * Rc * log ((R1 + R2) / R2));
volatile boolean triggered;
volatile boolean active;
volatile unsigned long timerCounts;
volatile unsigned long overflowCount;
ISR (TIMER1_OVF_vect)
{
++overflowCount; // count number of Counter1 overflows
} // end of TIMER1_OVF_vect
ISR (TIMER1_CAPT_vect)
{
// grab counter value before it changes any more
unsigned int timer1CounterValue;
timer1CounterValue = ICR1; // see datasheet, page 117 (accessing 16-bit registers)
unsigned long overflowCopy = overflowCount;
if (active)
{
// if just missed an overflow
if ((TIFR1 & _BV (TOV1)) && timer1CounterValue < 0x7FFF)
overflowCopy++;
// calculate total count
timerCounts = (overflowCopy << 16) + timer1CounterValue; // each overflow is 65536 more
triggered = true;
digitalWrite (pulsePin, LOW); // start discharging capacitor
TCCR1B = 0; // stop the timer
} // end if active
} // end of TIMER1_CAPT_vect
void setup ()
{
pinMode (pulsePin, OUTPUT);
digitalWrite (pulsePin, LOW);
Serial.begin (115200);
Serial.println ("Started.");
ADCSRB = 0; // (Disable) ACME: Analog Comparator Multiplexer Enable
ACSR = _BV (ACIC); // Analog Comparator Input Capture Enable
DIDR1 |= _BV (AIN1D) | _BV (AIN0D); // Disable digital buffer on comparator inputs
PRR = 0;
} // end of setup
void startTiming ()
{
active = true;
triggered = false;
noInterrupts ();
// prepare timer
overflowCount = 0; // no overflows yet
// reset Timer 1
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0; // Counter to zero
// Timer 1 - counts clock pulses
TIMSK1 = _BV (TOIE1) | _BV (ICIE1); // interrupt on Timer 1 overflow and input capture
// get on with it
digitalWrite (pulsePin, HIGH); // start charging capacitor
// start Timer 1, no prescaler
TCCR1B = _BV (CS10) | _BV (ICES1); // plus Input Capture Edge Select
interrupts ();
} // end of startTiming
void finishTiming ()
{
active = false;
Serial.print ("Capacitance = ");
float capacitance = (float) timerCounts * k;
Serial.print (capacitance);
Serial.println (" nF");
triggered = false;
delay (3000);
} // end of finishTiming
void loop ()
{
// start another test?
if (!active)
startTiming ();
// if the ISR noted the time interval is up, display results
if (active && triggered)
finishTiming ();
} // end of loop
I am now getting this output:
Capacitance = 46.04 nF
Capacitance = 46.05 nF
Capacitance = 46.01 nF
Capacitance = 46.01 nF
Capacitance = 45.98 nF
Capacitance = 46.01 nF
Capacitance = 45.99 nF