/* Capacitance Meter Original code: tmd3 on Arduino forum http://forum.arduino.cc/index.php?topic=174338.0 post#21 Slight changes and improvements: Dmitry Reznikov, 2015 Defaults: capacitor pin 7, voltage reference pin 6; these can be switched - see macros definitions below. Capacitor to be measured between capacitor pin and GND. Resistor, value = Rc, beween capacitor pin and cPin. Resistor Rd, value < Rc/5 & > 200, between dPin and capacitor pin. cPin ----> Rc ----> capacitor pin ----> capacitor_being_tested ----> GND +5v ----> R2 ----> voltage reference pin ----> R1 ----> GND capacitor pin ----> Rd ----> dPin */ // *** Define setup section - change according to your layout #define smallRc 10000.0 // default Rc resistance to measure 1nF and up #define bigRc 1000000.0 // bigger Rc resistance to measure pF capacitors #define Rd 510.0 // drain resistor check your resistors with a multimeter #define R1 984.0 // to GND to get exact values for better measurement #define R2 1994.0 // to 5v #define clockRate_us 16.0 #define dPin 8 // drain, any pin will do, 8 by default #define cPinNF 9 // test voltage pin for small resistor (nF meter), default 9 #define cPinPF 10 // test voltage pin for big resistor (pF meter), default 10 // you can change these to pins 3 and 4, see macros below // if other pins are used, add/change port manipulation macros below #define setupNonFpin 12 // connect this pin to GND to disable nF mode #define setupNopFpin 11 // connect this pin to GND to disable pF mode #define pFmodeWait 10 // cycles to wait before changing to pF mode (default 10) // *** the following macros start timer with either falling or rising edge. // *** falling: reference voltage on pin 6, measured capacitor on pin 7 // *** rising: reference voltage on pin 7, measured capacitor on pin 6 #define START_TIMER TCCR1B = (1< jitMax) {jitMax = C;} Serial.print("Testing... "); // show the jitter on big capacitor for a sec; maybe restart is needed PRINT_TAB; Serial.print(C*1000,3); Serial.print(" nF "); PRINT_TAB; Serial.print((C*1000000),2); Serial.print(" pF "); PRINT_NEW_LINE; adjustmentCounter--; if (adjustmentCounter == 0) { Serial.print("Jitter: "); Serial.print((jitMin*1000000),2); Serial.print(" to "); Serial.print((jitMax*1000000),2); Serial.println(" pF "); Serial.println("Ready"); } }; } void displayResults() { if (pFmode) // small capacitor meter { C = C - pFadjustment; // substract 'stray capacitance' Serial.print(" **** "); PRINT_TAB; Serial.print(C*1000,3); Serial.print(" nF "); PRINT_TAB; Serial.print((C*1000000),2); Serial.print(" pF "); PRINT_NEW_LINE; if (((C < 0.0000005) | (C > 0.002)) && (!NonFmode)) // switch to nF mode if needed { pFmode = false; pFmodeCounter=0; k = 1/(clockRate_us*smallRc*log((R1+R2)/R2)); pinSelect = smallCap; }; } else // big capacitor meter { C = C - nFadjustment; // substract 'stray capacitance' Serial.print(C,2); Serial.print(" uF "); PRINT_TAB; Serial.print((C*1000),3); Serial.print(" nF "); PRINT_TAB; Serial.print(" **** "); PRINT_NEW_LINE; if (((C < 0.002) && (C > 0.0000008)) && (!NopFmode)) // switch to pF mode if needed { pFmodeCounter++; if (pFmodeCounter > pFmodeWait) // some delay before switch to avoid false triggers {pFmode = true; k = 1/(clockRate_us*bigRc*log((R1+R2)/R2)); pinSelect = bigCap; pFmodeCounter = 0; }; } }; } void clearPrint() { PRINT_NEW_LINE; delay(1000); Serial.print(" "); PRINT_NEW_LINE; } void checkSettings() { MCUCR &= ~(1 << PUD); // enable pullup registers pinMode(setupNonFpin, INPUT_PULLUP); pinMode(setupNopFpin, INPUT_PULLUP); if ((digitalRead(setupNonFpin)==LOW) && (!NonFmode)) { Serial.print("Disabling nF mode... "); NonFmode = true; pFmode = true; k = 1/(clockRate_us*bigRc*log((R1+R2)/R2)); pinSelect = bigCap; pFmodeCounter = 0; clearPrint(); } else if ((digitalRead(setupNonFpin)==HIGH) && (NonFmode)) { Serial.print("Enabling nF mode... "); NonFmode = false; clearPrint(); } else if ((digitalRead(setupNopFpin)==LOW) && (!NopFmode)) { Serial.print("Disabling pF mode... "); NopFmode = true; pFmode = false; k = 1/(clockRate_us*smallRc*log((R1+R2)/R2)); pinSelect = smallCap; pFmodeCounter = 0; clearPrint(); } else if ((digitalRead(setupNopFpin)==HIGH) && (NopFmode)) { Serial.print("Enabling pF mode... "); NopFmode = false; clearPrint(); } MCUCR |= (1 << PUD); // disable pullup registers } void setup() { Serial.begin(115200); Serial.println("Starting up"); // check the mode control pins and display the programmed resistor values pinMode(setupNonFpin, INPUT_PULLUP); pinMode(setupNopFpin, INPUT_PULLUP); if (digitalRead(setupNonFpin)==LOW) {NonFmode = true;} if (digitalRead(setupNopFpin)==LOW) {NopFmode = true;} if (NonFmode && NopFmode) {Serial.println("Mode change disabled"); modeChange = false; NonFmode = false; NopFmode = false;} Serial.print("nF resistor: "); Serial.print(smallRc); if (NonFmode) {Serial.print(" (disabled)");} Serial.println(); Serial.print("pF resistor: "); Serial.print(bigRc); if (NopFmode) {Serial.print(" (disabled)");} Serial.println(); // k is the multiplier used to calculate capacitance based on resistor values // it changes later in the code with mode changes k = 1/(clockRate_us*smallRc*log((R1+R2)/R2)); MCUCR |= (1 << PUD); // Globally disable pullup resistors TCCR1B = 0; // Noise Canceler off; Normal mode; falling edge; stopped TCCR1A = 0; // Normal mode; TIMSK1 = (1 << ICIE1) | (1 << TOIE1); // Input Capture and Overflow interrupts DIDR1 |= (1< 0) // calculating 'stray capacitances' on the first run {calibration();} else {displayResults();} // start discharging dischargeTime = 1 + (uint16_t)(10.0*Rd*C/1000.0); delay(dischargeTime); // Wait at least 10 time constants if (dischargeTime < 250) { delay(250-dischargeTime); // Wait some more to limit printing } if ((adjustmentCounter == 0) && modeChange) checkSettings(); } ISR(TIMER1_CAPT_vect) { TCCR1B = 0; // Stop Timer1 - CS12:CS10 = 0 TIFR1_Copy = TIFR1; // Get overflow interrupt status TIFR1 = (1 << TOV1); // Clear overflow ICR_Copy = ICR1; // Get the ICR ICR_Flag = 1; // Set the flag } ISR(TIMER1_OVF_vect) { TOV1_Ctr++; // Bump the overflow counter }