capacitor meter (SOLVED)

Hi,

I need to build a capacitor meter using a Wemos D1 mini board (I need wifi and small board). I have used this guide (https://www.gammon.com.au/forum/?id=12075) as a starting point. Unfortunately, it did not work. I need to measure 100pf and up.

I have also tried this method (How to Make an Arduino Capacitance Meter) last section but I think the stray capacitance of the Wemos board is way to low.

Would the Wemos board not work at all for this? Or can you give me some guidelines/directions?

All help is welcome, thanks!!

The link to the Gammon page isnt working.

I'll try this method and see what results I get.

.. and if I can understand what it is doing!

I built the capacitance meter from Nick's page and it worked well. Very close to the values shown by my DMM.

it did not work

That statement conveys no useful information. The program does something, just no what you expect. So what does the program actually do? What is the program output? How is that different from what you expect?

Post the code that you used. Post a schematic of your setup.

As promised I tested it, it works really well over a range 20pF - >100uF. I've commented the code so you can see how it works.
For caps below 1000pF it uses "capacitors in series" principle, comparing Cext with Cs
Over 1000pF it uses cap charging through resitor between voltage thresholds. Vc = Vcc (1-exp(-t/RC)

Values of Cstray and Rpullup would need to be measured for accurate results, but work fine on my UNO;
you would need to change them for a different board.

You can measure Rpullup by measuring the voltage on open circuit, then with say a 10k load resisitor.
Cstray by calibrating against a good cap of say 50pF

/* Arduino Uno Capacitance meter
   https://www.circuitbasics.com/how-to-make-an-arduino-capacitance-meter/

   470uF  - 18pF  cap connected between A0 and A2
   for electrolytics + goes to A2
*/
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);  // output defaults to LOW
  pinMode(IN_PIN, OUTPUT);   // output defaults to LOW
  Serial.begin(9600);
}

void loop() {
  pinMode(IN_PIN, INPUT);
  digitalWrite(OUT_PIN, HIGH);
  int val = analogRead(IN_PIN);
  digitalWrite(OUT_PIN, LOW);  //discharge Cext ready for next method
  if (val < 1000) {
    /*
       measuring Cext using the capacitive divider principle
       as the caps are in series the charge is the same on both Q = It; but also charge = CV
       Hence Cs*val = Cext(1023-val)
       whence Cext = val *Cs / 1023 - val
       below val=800 we have an error margin of 1pF
       At val = 992 we have an error margin of 25pF and at val=999 40pF when C = 1000pF
    */
    pinMode(IN_PIN, OUTPUT); //discharge Cs ready for next method

    float capacitance = (float)val * IN_CAP_TO_GND / (float)(MAX_ADC_VALUE - val);

    Serial.print(F("Capacitance Value = "));  //Serial.print(F just puts the string in flash memory
    Serial.print(capacitance, 3);     // 3 places after decimal point? - ridiculous, measurement of pF is not that precise
    Serial.print(F(" pF ("));
    Serial.print(val);
    Serial.println(F(") "));
  }

  else {
    //use RC charging time to measure C
    //t is microseconds, R kohm so C will be in nF
    pinMode(IN_PIN, OUTPUT);  //one side of cap "grounded"
    delay(1);
    pinMode(OUT_PIN, INPUT_PULLUP); //now charging Cext via RPullup
    unsigned long u1 = micros();  //time charging started
    unsigned long t;
    int digVal;

    do {
      digVal = digitalRead(OUT_PIN);  //charging from zero up to Vih which is ABOUT 2.6V
      unsigned long u2 = micros();
      t = u2 > u1 ? u2 - u1 : u1 - u2;
    } while ((digVal < 1) && (t < 400000L));
    //if it times out - at 400msec - digval will not be 1. Hence "highVal";  Threshold is about 100uF

    pinMode(OUT_PIN, INPUT);
    val = analogRead(OUT_PIN); //measure the voltage it has charged to
    //then from val = Vcc(1-exp(t/RC)  -> t =-CRln(1-val/Vcc) -> C = - ( t / R) / ln (1 - val / Vcc)


    //discharge it
    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 = "));
    //next bit is just choosing appropriate units
    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);    //repeat loop every second
}

A WeMos D1 mini (ESP8266) has a completely different A/D (absolute vs. ratiometric),
so don't expect you can just change to that processor without problems.
An ESP32 could be a better starting point.
Leo..

Hi Leo;

the sketch I tested times the charging time for the cap from 0 to ViH - then measures with the ADC.
ViH for the ESP8266 and ESP32 is 0.75 * Vcc = 2.5V which is outside the range of the ADC.

I've looked at the Nick Gammon meter and I beilieve that too is aimed at the earlier arduinos.

While the ESP8266 and ESP32 are great devices the ADC's leave a lot to be desired (such as linearity) and the ESP32 (as I found out) can be a challenge for "beginners".

I'd suggest the OP gets a nano and a breadboard, a lot of learning and fun for coppers. However as he "needs" wifi then the WeMOS CAN do the job - but he will need to rewrite a LOT of the sketch- and to make it easier, define the limits of the capacitance he needs to measure.

@marceltim - still there?

Hi,

I didn't get an e-mail notification so I was under the impression that nobody replied :). I got everything working with an Arduino Nano. But I would like to use an ESP like Wemos D1 Mini or Node MCU but I don't get this working for some reason. I also tried the CapacitiveSensor library. Works on the Nano but not on the Wemos :frowning:

I didn't get an e-mail notification so I was under the impression that nobody replied

If it's important enough to you one would expect you would log in to the forum to check your post.

At the top of the page is a box to select whether you get emails.
See my earlier comments you will understand how it works and how to mod the code to work on a different processor.

Thanks for the reply. I have switched on the notifications. But I am not sure I completely follow you. You have tested on a UNO. This works indeed. But did you test this on a Wemos D1 for example as well? Could you tell me how to make the connections?

I fully documented my code as posted above so you should be able to see how it works. Depending on the range of capacitance you need to measure you may be able to delete part of the code.

For caps below 1000pF it uses "capacitors in series" principle, comparing Cext with Cs
Over 1000pF it uses cap charging through resitor between voltage thresholds. Vc = Vcc (1-exp(-t/RC)

Values of Cstray and Rpullup would need to be measured for accurate results, but work fine on my UNO;
you would need to change them for a different board.

You can measure Rpullup by measuring the voltage on open circuit, then with say a 10k load resisitor.
Cstray by calibrating against a good cap of say 50pF

The WEMOS D1 / NodeMCU / ESP8266 only has 1 analog input which would be a problem; the ESP32 WROOM Devkit has several but a bit tricky to use.

You may be better off with this

Hi John,

Thanks for your suggestions. I would like to use ESPHome and integrate the board with Home Assistant. So I am thinking to see if it is working with an ATtiny board and send the data to Wemos.

Or maybe this would be an option:

you need to define the range of capacitance you wish to meassure. Is it some sort of capacitive sensor?

Hi john,

Yes, I am trying to build a rain sensor based on this:

it is about 100pf with no rain, and when it starts raining it increases this value up to about 400 pf.

Hi,

I have build now a smith trigger with an 74hct14 which works fine :slight_smile:

Over a narrow cap range like that you can choose components for an RC oscillator as you say, then just time the pulses.

Problem solved? If so pleasse edit your first post to add "SOLVED" to the title.

Where did you get a "74htc14"?
Some kind of typo there.
Correct family is 74HCT.
Mouser seems to carry 74HCT14, but not Digikey. Odd.
"Schmitt Trigger"

https://www.mouser.com/_/?keyword=74HCT14&gclid=CjwKCAiAudD_BRBXEiwAudakXxMtAAh2Q5v528cyUA1Op9psOnboD5bCkPIbI8AWlthN3eVUCANpCRoCTxMQAvD_BwE

Hi,

This was indeed a typo and I have corrected it. Thanks, everyone for helping with suggestions.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.