/* Capacitance measurement code by Jonathan Nethercott https://wordpress.codewrite.co.uk/pic/2014/01/25/capacitance-meter-mk-ii/ Other code from LiquidCrystal Library - Hello World Measures capacitance and displays the results on a 24x2 serial LCD display with KS0073 LCD driver chip. MeasureCapacitor_Uno_ks0073a V1.0 by Tony Wills, no rights reserved. */ // include the library code: #include // initialize the library with the number of the pins // sclk, mosi, miso (optional), ss) LiquidCrystal_ks0073 lcd(7, 11, 10); int l; int rows = 2; int cols = 24; char pulse = '*'; // Capacitor under test. // Note that for electrolytics the first pin (in this case A5) // should be positive, the second (in this case A0) negative. const int OUT_PIN = A5; const int IN_PIN = A0; //Capacitance between IN_PIN and Ground //Stray capacitance value will vary from board to board. //Calibrate this value using known capacitor. const float IN_STRAY_CAP_TO_GND = 24.48; const float IN_CAP_TO_GND = IN_STRAY_CAP_TO_GND; //Pullup resistance will vary depending on board. //Calibrate this with known capacitor. const float R_PULLUP = 34.8; //in k ohms const int MAX_ADC_VALUE = 1023; void setup() { pinMode(OUT_PIN, OUTPUT); //digitalWrite(OUT_PIN, LOW); //This is the default state for outputs pinMode(IN_PIN, OUTPUT); //digitalWrite(IN_PIN, LOW); // set up the LCD's number of columns and rows: lcd.begin(cols, rows); Serial.begin(9600); // cap1.ShowDebug(true); lcd.print("Capacitor test"); } void loop() { //Capacitor under test between OUT_PIN and IN_PIN //Rising high edge on OUT_PIN pinMode(IN_PIN, INPUT); digitalWrite(OUT_PIN, HIGH); int val = analogRead(IN_PIN); digitalWrite(OUT_PIN, LOW); float capacitance = 0; if (val < 1000) { //Low value capacitor //Clear everything for next measurement pinMode(IN_PIN, OUTPUT); digitalWrite(IN_PIN, LOW);//ajw //Calculate and print result capacitance = (float)val * IN_CAP_TO_GND / (float)(MAX_ADC_VALUE - val); Serial.print(F("Capacitance Value = ")); Serial.print(capacitance, 3); Serial.print(F(" pF (")); Serial.print(val); Serial.println(F(") ")); } else { //Big capacitor - so use RC charging method //discharge the capacitor (from low capacitance test) pinMode(IN_PIN, OUTPUT); digitalWrite(IN_PIN, LOW);//ajw delay(1); //Start charging the capacitor with the internal pullup pinMode(OUT_PIN, INPUT_PULLUP); unsigned long u1 = micros(); unsigned long u2 = u1; unsigned long t; int digVal; //Charge to a fairly arbitrary level mid way between 0 and 5V //Best not to use analogRead() here because it's not really quick enough do { digVal = digitalRead(OUT_PIN); u2 = micros(); t = u2 > u1 ? u2 - u1 : u1 - u2; } while ((digVal < 1) && (t < 400000L)); pinMode(OUT_PIN, INPUT); //Stop charging //Now we can read the level the capacitor has charged up to val = analogRead(OUT_PIN); //Serial.print(u1);Serial.print(" ");Serial.println(u2);//ajw //Discharge capacitor for next measurement digitalWrite(IN_PIN, HIGH); int dischargeTime = (int)(t / 1000L) * 5; delay(dischargeTime); //discharge slowly to start with pinMode(OUT_PIN, OUTPUT); //discharge remainder quickly digitalWrite(OUT_PIN, LOW); digitalWrite(IN_PIN, LOW); //Calculate and print result capacitance = -(float)t / R_PULLUP / log(1.0 - (float)val / (float)MAX_ADC_VALUE); Serial.print(F("Capacitance Value = ")); if (capacitance > 1000.0) { Serial.print(capacitance / 1000.0, 2); Serial.print(F(" uF")); } else { Serial.print(capacitance, 2); Serial.print(F(" nF")); } Serial.print(F(" (")); Serial.print(digVal == 1 ? F("Normal") : F("HighVal")); Serial.print(F(", t= ")); Serial.print(t); Serial.print(F(" us, ADC= ")); Serial.print(val); Serial.println(F(")")); capacitance *= 1000; //scale for my output routine } char buffer[8]; float cap = capacitance; //cap1.Measure(); lcd.setCursor(0, 1); if (cap >= 0) { int exponent = int(log10(cap)); long mantissa = round(cap / pow(10, (exponent - 2))) * pow(10, (exponent - 2)); if (cap >= 1000000) { //lcd.print(mantissa/1000000.0);lcd.print(" uF"); dtostrf(mantissa / 1000000.0, 8, (2 - (exponent - 6)), buffer); lcd.print(buffer); lcd.print(" uF"); } else if (cap >= 200000) { //lcd.print(mantissa/1000000.0);lcd.println(" uF"); dtostrf(mantissa / 1000000.0, 8, 3, buffer); lcd.print(buffer); lcd.print(" uF"); } else if (cap >= 1000) { //lcd.print(mantissa/1000.0);lcd.println(" nF"); dtostrf(mantissa / 1000.0, 8, (2 - (exponent - 3)), buffer); lcd.print(buffer); lcd.print(" nF"); } else { //lcd.print(mantissa/1.0);lcd.println(" pF"); dtostrf(mantissa / 1.0, 8, 0, buffer); lcd.print(buffer); lcd.print(" pF"); } } else { lcd.print("-----------"); } pulse = '*' + ' ' - pulse; lcd.print(pulse); delay(1000); // Wait for 1 second, then repeat }