Question about Capacitance Meter

I found a Arduino Capacitance Meter design.

Here is the origin page: http://www.circuitbasics.com/how-to-make-an-arduino-capacitance-meter/
and the third Circuit

schematic:

code:

const int OUT_PIN = A2;
const int IN_PIN = A0;
const float IN_STRAY_CAP_TO_GND = 24.48;
const float IN_CAP_TO_GND  = IN_STRAY_CAP_TO_GND;
const float R_PULLUP = 34.8;  
const int MAX_ADC_VALUE = 1023;

void setup()
{
  pinMode(OUT_PIN, OUTPUT);
  pinMode(IN_PIN, OUTPUT);
  Serial.begin(9600);
}

void loop()
{
    pinMode(IN_PIN, INPUT);
    digitalWrite(OUT_PIN, HIGH);
    int val = analogRead(IN_PIN);
    digitalWrite(OUT_PIN, LOW);

    if (val < 1000)
    {
      pinMode(IN_PIN, OUTPUT);

      float 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
    {
      pinMode(IN_PIN, OUTPUT);
      delay(1);
      pinMode(OUT_PIN, INPUT_PULLUP);
      unsigned long u1 = micros();
      unsigned long t;
      int digVal;

      do
      {
        digVal = digitalRead(OUT_PIN);
        unsigned long u2 = micros();
        t = u2 > u1 ? u2 - u1 : u1 - u2;
      } while ((digVal < 1) && (t < 400000L));

      pinMode(OUT_PIN, INPUT);  
      val = analogRead(OUT_PIN);
      digitalWrite(IN_PIN, HIGH);
      int dischargeTime = (int)(t / 1000L) * 5;
      delay(dischargeTime);   
      pinMode(OUT_PIN, OUTPUT);  
      digitalWrite(OUT_PIN, LOW);
      digitalWrite(IN_PIN, LOW);

      float 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(")"));
    }
    while (millis() % 1000 != 0)
      ;    
}

I think it uses input resistance (about 100M) of Arduino adc to build a RC circuit. And calculate capacitance with charge time and voltage.Is that correct?

But the equation “float capacitance = (float)val * IN_CAP_TO_GND / (float)(MAX_ADC_VALUE - val);” dose not look like RC charging equation.

Could someone explain it? :confused:

Read the code again. The "R" resistance is clearly there to see.

 float capacitance = -(float)t / R_PULLUP
                              / log(1.0 - (float)val / (float)MAX_ADC_VALUE);

I think it uses input resistance (about 100M) of Arduino adc to build a RC circuit. And calculate capacitance with charge time and voltage.Is that correct?

As far as I know, that "100M resistance" isn't necessarily connected to 5V (as a pull-up) or to ground (as a pull-down). It's just an approximate "load" so you can calculate the required drive/source impedance and estimate noise immunity, etc.

raschemmel:
Read the code again. The “R” resistance is clearly there to see.

 float capacitance = -(float)t / R_PULLUP

/ log(1.0 - (float)val / (float)MAX_ADC_VALUE);

yes, I notice that and it fits my guess(while I think pull up resistance should be 20k not 34.8k in the code), which makes me really confused is the part before that measure Capacitance in pF.

here:

pinMode(IN_PIN, INPUT);
    digitalWrite(OUT_PIN, HIGH);
    int val = analogRead(IN_PIN);
    digitalWrite(OUT_PIN, LOW);

    if (val < 1000)
    {
      pinMode(IN_PIN, OUTPUT);

      float 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(") "));
    }

The 34.8 probably came from dividing 5 volts by the current out of the pulled up input pin. I measured 128 uA, about 39k.

When I measured the pullup before writing this sketch I found it to be ~40kΩ.

From figure 35-17 of the ATmega328P datasheet, it seems it should be ~35kΩ:

The pull-up resistor is not suitable, its probably an on-chip p-FET, and not particularly linear, and varies from chip to chip and pin-to-pin.

Use an external precision resistor for best results

i have actually designed a capacitance meter using an UNO and a 555 timer in astable mode that measures wide range of values and also works as a frequency counter and signal generator the unfortunate part I haven`t posted it yet its still breadboarded but has been tested. not sure if anyone is interested. Values are printed to serial monitor.

rogertee: i have actually designed a capacitance meter using an UNO and a 555 timer in astable mode that measures wide range of values and also works as a frequency counter and signal generator the unfortunate part I haven`t posted it yet its still breadboarded but has been tested. not sure if anyone is interested. Values are printed to serial monitor.

Of course we would!! post it up in the Exhibition / Gallery section