Mbed capacitance meter

21 Oct 2011

Hi everyone,

I'm new here, and fairly new to electronics. I've been programming for a couple of decades, mostly in Perl, PHP, and so on. I've taken some C courses, but that was too long ago to think about.

I had read online about all the fun that people are having with Arduino, and was inspired. I started reading about the great number of people that are transitioning from 8-bit up to 32-bit micro-controllers and then I started reading up on the LPC Expresso boards. This is when I found Mbed and ordered one.

I've so far done some little projects with the Mbed, including Hello World, a bunch of "blink or dim these LEDs" projects, a basic voltmeter (amazingly accurate on an "AA" cell), and so on. I've built a nice little power supply that takes 9V in from a wall-wart and brings it down to a nice 5V to run the Mbed. I've also hooked up a 40x4 LED display and that works (mostly) fine. I'm impressed and excited to hone my skills and have spent a ton of my spare time learning more about electronics. I'm hooked.

I would like to build a capacitance meter. I found something for an Arduino here: http://arduino.cc/it/Tutorial/CapacitanceMeter and tried to build that. I carefully followed the schematic as closely as I could, and wrote some code to measure the voltage on the capacitor; if the capacitor is close to 0V, then my code turns on a DigitalOut pin to charge it up. The problem I have is that as soon as the charge pin comes on, the voltage read pin "sees" the 3.3 V and assumes the capacitor is charged, then turns off.

I'm stuck. Not sure whether I screwed up wiring up my breadboard, in my code, or both.

Any tips, thoughts, or information would be very much appreciated.

Chris

22 Oct 2011

I think the problem I had was that I was using a "DigitalOut" pin to output the voltage to charge the capacitor. I've since changed to pin18 and have it set as "AnalogOut" now, and the project is working better.

That said, I'm getting an occasional false voltage reading when checking the voltage of the capacitor. It will read (for example) 0.76, 0.77, 0.78, 0.79, (then once in a while an obviously wrong value such as) 2.9, 0.80, 0.81, 0.82, etc.

Why am I getting this occasional false reading, and what can I do to avoid this problem?

22 Oct 2011

Hi, Chris. Interesting little circuit, using the mbed. I would drive the resistor and capacitor with a DigitalOut and read the capacitor with an AnalogIn, just as the Arduino link shows. The neat thing about AnalogIn is that it is ratiometric. That is, it does not measure voltage in volts, but instead gives a reading that is a decimal fraction of Vout (nominally 3.3 V), so readings will vary from 0.00 to 0.99, or possibly 1.0. That means all you have to do is time how long it takes to go from 0.0 to 0.63, and that is one RC time constant. Then divide the time by the resitance to get the capacitance. The beauty is that if Vout varies a little (or even a lot), say to 3.28 V, the capacitor has still charged to 63% of that. If Vout is a little high, say 3.35 V, the same applies; the capacitor has still charged to 63% of the supply, and the time represents one RC time constant.

Having not personally built the circuit, I am curious about how well changing a pin from DigitalOut to DigitalIn and back again works. That is being done to achieve switching action. I would have used a couple of transistors, but the DigitalOut/In switching, if it works, is much easier.

22 Oct 2011

Hi Bob,

One question I have is "how can I enable or disable a pin on the mbed, within the code?" I certainly know how to declare a pin as AnalogOut, DigitalIn, or whatever, but I don't know how to disable the function of a pin once the code is running.

Cheers, Chris

24 Oct 2011

Today I wired up the capacitance meter circuit. My first version did not use a dischage pin. It discharged the capacitor through the same large-value resistor used for charging. For charging/discharging, I defined a variable named "source" of type DigitalOut. That pin is wired to the free end of the resistor. Another variable, "capacitor", of type AnalogIn, has its pin wired to the junction of the capacitor and resistor. "source" should initially be set to 0 to keep the capacitor discharged (remember, the C programming language does not initialize numerical variables to 0 as some other languages do, so you have to do it). Then "source" is set to 1, to start charging the capacitor, and a timer is started. A while loop continuously checks for "capacitor" to reach 0.632 (that is, 63.2%). When that happens, the timer is stopped, and the timer value read in microseconds. Dividing the time in microseconds by the resistance in Ohms gives the capacitance in microfarads. Then "source" is again set to 0 to discharge the capacitor.

For large-valued capacitors (electrolytics), discharging through the same large-valued resistor might prove to take too much time, so in the second version I defined a variable named "discharge" of type DigitalInOut, and connected the pin to the resistor-capacitor junction using a 100 ohm resistor. The pin is configured as an output by: discharge.output(); followed by discharge = 0; to initially keep the capacitor discharged. Then, just before turning on "source", "discharge" is reconfigured as in input with no internal pullup/pulldown by: discharge.input(); and then discharge.mode(PullNone); As before, a polling while loop checks for "capacitor" to equal or exceed 0.632, after which the capacitance is calculated, and the capacitor is discharged by turning the "discharge" pin back into a digital output, written to 0. The "source" can be left "on" all the time, since it is separated by a rather large value of resistance (I used a 100K, 1% resistor), or you can turn the source on and off at the appropriate times.

01 Nov 2011

Sorry for the delay in getting back to the forum, have been busy at work on a couple of huge time-sensitive projects.

Bob, how accurate do you think your project is at measuring capacitance?

Any chance you can post your source code?

03 Nov 2011

The results are surprisingly good for such a simple circuit. Here is a table of capacitors I measured with the mbed circuit, and also measured with a multimeter and a capacitance meter. (The capacitance meter is not on any calibration schedule, so it probably hasn't been calibrated since it left the factory.)

/media/uploads/bprier/capacitance_readings.gif

I have rounded all values to two or three significant figures for easier comparison. Perhaps the most surprising part is how close the measured capacitor values are to nominal, but then again most of these were good quality timing caps.

As far as sources of error in the mbed circuit, I measured the 100K, 1% resistor I used in my circuit with a 6-1/2 digit meter (calibrated yearly). Set to five significant digits, the meter gave a value of 100,320 ohms. Multiplying by that slightly higher value, rather than the 100,000 I used in my mbed program, would give slightly higher values for the mbed capacitance readings (they would be higher by 0.32%). I was also curious about how close to the 3.3 V "rail" the digital output got. It measured 3.318 V when high, and 0.0012 V when low (that is, 1.2 mV). That's pretty impressive.

Here's the code listing:

#include "mbed.h"

//Global constants
const double resistance = 100000;  // 100K

// Global variables
DigitalOut source(p5);
DigitalInOut discharge(p6);
AnalogIn capacitor(p20);

int main()
{
    Timer t;
    double capacitance;
 
    // Turn off source
    source = 0;
    
    // Discharge capacitor
    discharge.output();
    discharge = 0;
    wait_ms(50);

    // Reset timer
    t.reset();
    
    // Disable discharge pin
    discharge.input();          //reconfigure pin as an input
    discharge.mode(PullNone);   //configure with no internal pullup/pulldown

    // Turn on source voltage,
    // and start timer
    source = 1;
    t.start();
    
    //Continuously read capacitor until 63.2% charged
    while(capacitor.read() < 0.632)
        ; //do nothing
        
    t.stop();
    
    capacitance = t.read_us()/resistance;  //C will be in uF, since time is in us
    printf("%e\n", capacitance);           //send value to TeraTerm for display

    // Turn off source
    source = 0;
    
    // Discharge capacitor
    discharge.output();
    discharge = 0;
    wait_ms(50);

} //end main()

Each time you press and release the mbed reset button the programs runs, and a single capacitance reading will be sent to the terminal emulator (I used TeraTerm). You could loop the program and average readings, but I wanted to see how repeatable individual readings were. With the non-electrolytic caps the readings were identical each time I ran it.

03 Nov 2011

Bob,

Thanks for posting the code and your detailed table. Interesting that the 4.7 uF capacitor was apparently the most difficult to measure for both the mbed and the multimeter, but your capacitance meter seemed to nail it. I wonder what the differences are.

I will give this a try when I have some time to see if I end up with results similar to yours.

Thanks again!

Chris

03 Nov 2011

Bob,

Had a bit of time to play with this today, and while it generally works, I have a problem. I started using your code almost in its entirety, but added to it for debugging and troubleshooting.

The problem I have is that I occasionally get anomalies when reading the value of the capacitor within the charge loop. When the false reading comes in, the code assumes that the capacitor is charged to 0.632 and exits the loop, does the math, and gives a horribly incorrect value for the capacitor.

I've modified the code to give debugging data whenever it gets an obviously incorrect value, and made the code run 10 times before exiting (I got tired of pressing the little button). I've also adjusted the charge loop exit criteria in hope of ignoring these strange readings.

My code and the output is attached to this message (assuming I figured out how to do that).

I'm running my mbed from my system's USB port. I hope that neither my system nor my mbed are at fault, but really don't know what the solution is.

Here's a pic of my circuit: /media/uploads/Wyleyrabbit/mbed_cap1.jpg

And here is my code: /media/uploads/Wyleyrabbit/cap1.txt

Any help or tips would be much appreciated.

04 Nov 2011

Oh, and here is the output from a run that lists each bad read. /media/uploads/Wyleyrabbit/cap1log.txt

04 Nov 2011

Chris, it's a little hard to tell from your photo, since it is shot at an angle, but your mbed seems to be plugged into positions 2 through 21 of the breadboard. There appears to be a wire in position 2, which would be GND, so that is correct. And then you have wires in positions 6, 7 and 21, which would correspond to pins 5, 6 and 20 of the mbed, and the program. Even though the wiring appears to be correct, why don't you make it easy on yourself and plug the mbed into positions 1 through 20?

Have you tried testing capacitors with lower values? I would recommend, as a sanity check, trying capacitors with values close to the ones I used, and using my exact code. Then return to using the 470 uF cap. The largest cap I measured had a value one-tenth of the one you're using. For a 470 uF cap I would use a 10K or even a 1K charging resistor. That way, instead of a 47 second charge time, you would have a 4.7 or 0.47 second time. I'm glad to see that you changed my 50 ms discharge time to 1 second, since one RC is 47 ms with a 100 ohm resistor and 470 uF cap.

I am puzzled by the data in each of your 10 runs. It seems to miss the 0.632 point (which I can explain) and continue to charge. That makes sense, but then it drops down and ramps back up...repeatedly...until mysteriously bailing out of the loop with exactly 0.632 and a time in microseconds that appears right!?

One problem I see is that your loop does not handle the case for "meter == 0.634". If weird things weren't happening I'd say that that is not critical, because it will soon be greater than 0.634, and that case is provided for, but I'd plug that hole anyway. Another thing I see is that the exit condition for the while loop is "charge == true". The only place that can occur is if the value of "meter" is in the range [0.632, 0.634). If that is missed, the loop should run forever. What puzzles me is that it eventually bails out.

Another problem is the printf statements inside of what should be a tight loop which should only read the AnalogIn pin. Printing over the USB to a terminal emulator is extremely slow compared to normal code execution. If you've ever written a program that prints to the computer screen and loops heavily (like when debugging) it can take seemingly forever. Turn off the code that prints to the console, and the program finishes quickly. I'm wondering if the capacitor dischages somewhat during the terminal printing. I would put a meter on the source pin to see if it fluctuates. An analog meter is better for such a job; you can see the needle move, and how much. It's hard to do that on a digital meter when the value is fluctuating.

Let me (us) know how it goes.

04 Nov 2011

Bob,

I have rebuilt my circuit with your recommendations. I have no idea why I had the mbed sitting on row 2, but this does make it easier. Thank you for the (what should have been obvious to me) tip. Here's a pic of my new circuit: /media/uploads/Wyleyrabbit/mbed_cap2.jpg

I'm using a 10K charge resistor, and a 300 ohm discharge resistor. I modified your code to reflect my 10K charge resistor, and extended the discharge time to a full 3 seconds (just to be extra sure). Other than that, the code I tested with is exactly your code.

I tested with a 10 uF capacitor, and I ran the program 25 times and got wildly inconsistent results:

Quote:

Rated capacitor value: 10 uF Charge resistor: 10K

2.855000e-01 1.789000e+00 9.099400e+00 9.925700e+00 9.669400e+00 5.722000e+00 1.112100e+00 7.688500e+00 4.368500e+00 1.353110e+01 1.087350e+01 4.154700e+00 2.886400e+00 3.569000e-01 1.002560e+01 1.603600e+00 3.145060e+01 4.859600e+00 1.888900e+00 9.409000e-01 1.164270e+01

I'm now at a loss. This shouldn't be the code that's at fault. Is there something horribly wrong with the way I built my circuit? Could this be some sort of grounding issue?

Any tips from you or anyone would be helpful.

cheers, Chris

04 Nov 2011

I just tried the same code, same capacitor, on a different computer. Same very inconsistent results.

Quote:

1.459260e+01 4.618500e+01 4.740350e+01 1.441470e+01 4.928440e+01 2.699030e+01 4.930570e+01 4.928450e+01 4.927690e+01 4.927010e+01 4.928440e+01 1.466400e+01 4.921310e+01 4.218050e+01 4.917030e+01 4.927010e+01 4.926270e+01 4.924880e+01 4.920610e+01 4.928420e+01 4.928410e+01 4.927010e+01 4.927020e+01

I don't have a second mbed to test with, and am out of ideas.

Chris

04 Nov 2011

hi,..

I noticed that the original poster only went up to 4.7 uF max, and that was a bit inaccurate,.

I wonder if 10 uF is a problem ?

could you try the original posters values for caps and resistors ? just to see if you could get that working ?

Just a suggestion.

cheers

Dave

04 Nov 2011

Hi David,

Unfortunately, the smallest capacitor I have is 10 uF. I can measure that with reasonable accuracy, as long as I use error checking within my code AND use a small 1.5K resistor which decreases the likelihood of a false reading.

I'd still love to know why I occasionally get false readings though. Is my Mbed defective?

Chris

04 Nov 2011

Ultimately, I'd like to do something like this: http://www.parallax.com/Portals/0/Downloads/docs/cols/nv/vol1/col/nv27.pdf

Would it even be possible to build a water level meter with an Mbed?

I found a video on YouTube from a company that seems to do something similar for motorhomes: http://www.youtube.com/watch?v=G-3hO1nnfSo&feature=player_embedded

Any thoughts?

05 Nov 2011

in passing..

when I was at school we built the classic "sense when a mug is full of water and buzz a buzzer circuit" hardware isn't my forte, but I seem to remember a darlington pair ?

I *wonder* if you could make up a "tape" that is segmented, and sense how many segments are wet ?

The clever capacitance system seems like it is going to depend on the liquid, bit of salt, or maybe hard water instead of soft water? and it's going to go haywire.

Our oil tank has a gadget that claims to do it by bouncing a signal off the oil surface. I think it's probably just a range finder ? (there's one in the cookbook running off am mbed), you have to tell it how deep your tank is on little dip switches, and then it makes up it's own arbitrary units.

just my thoughts, cos it's 2 in the morning here, and I just can't sleep tonight.

05 Nov 2011

Chris,

I finally tried some larger-valued capacitors: a 10 uF, 100 uF and 470 uF. The reason I did not start off with them is electrolytics are not meant to be precise. They are meant to act like the air tank on an air compressor, or a battery, just a reserve supply. Plus they don't measure the same two times in a row. I had to re-assemble my circuit, which only took a minute, after which I re-measured one of the 0.1 uF caps from the other day. It was exactly the same to four significant digits!

Here are the electrolytics I measured today:

The 10 uF cap. (using a 100K charge resistor) measured 10.9 uF. The 100 uF cap. (using 100K, 10K, 1K) measured 119 uF, 116 uF and 118 uF. The 470 uF cap/ (using 100k, 10K, 1K) measured 517 uF, 498 uF and 506 uF. (Each value posted is an average of three readings.)

I did not have time to check these on the multimeter and capacitance meter, but these values look good. If you look in an electronic parts catalog it is common for electrolytic caps to have a tolerance of +/-20% in value.

Getting back to your circuit, the layout looks correct. I would use a smaller value discharge resistor to ensure the cap is fully discharged. I use 100 ohms, which is safe because even when the cap is fully charged to 3.3 V and the discharge pin is low the most current that flows is (3.3 - 0.0)/100 or 33 mA. The mbed can source or sink 40 mA, so we are okay. The same can be said for using a 100 ohm charge resistor for large caps of 10,000 uF and above. Initially the cap is 0 V, so the current pours in as if it were a short circuit, limited only by the resistor value. The initial charging current would be 33 mA and then taper off from there as the voltage on the cap increases. Some of your posted values are below 10 uF, meaning a shorter charging time, which may indicate the cap was not fully discharged. Judging by some of the other values, though, I would say something else is happening.

If you look at the holes in your breadboard just above where the positive lead of the capacitor is inserted you can see the metal contact inside blocking about half of the hole. That's the way they should look. The metal contact also has a semi-circular notch to help it make more contact with wires and component leads. Now look at some of the other holes in the vicinity of your resistors. The holes appear empty. This can happen if a large diameter wire or lead has been jammed in, forcing the contact back. I would pull out your wires and resistors one-by-one and then take a straight piece of solid, 22 AWG wire (or a new, straight resistor) and test each hole for contact by inserting the wire and then gently pulling it part way out and then back in again, trying to feel the drag of the metal contact on the wire.

Bad contacts would explain the flakey readings you are getting. If the charging circuit is not in contact some of the time, the program has to run longer to get up to 63.2%, resulting in a larger timer value and calculated capacitance value. If the AnalogIn "sense" wire is making poor contact, the program will really be confused. One loop it could be reading nothing, and the next loop it could be over the limit.

14 Nov 2011

Hello,

i think Chris have a different problem then the tolerance of electrolytic capacitors.

I also have this problems by reading analogue values with the mbed.

For tests i put a known DC voltage to the analogue input pin, measured by a multimeter and an oscilloscope. The measured value was quite well constant. The mbed in 98% measures the proper value and in the rest of the 2% he measures really completely random values! But the next value measured was absolutely correct again.

I also still did not have any solution for that random values occurrences, and i did not know from where they are feed in! I´m sure that my analogue value did not make such random jumps in between.

15 Nov 2011

Thanks for commenting, dedo.

My mbed seems to be working fine, but I am learning on another forum topic http://mbed.org/forum/mbed/post/14563/ that others are having trouble like you report. I need to dig out my second mbed and try it, and do some more experimenting.

18 Nov 2011

Hi Dave,

David Styles wrote:

I *wonder* if you could make up a "tape" that is segmented, and sense how many segments are wet ?

The clever capacitance system seems like it is going to depend on the liquid, bit of salt, or maybe hard water instead of soft water? and it's going to go haywire.

Our oil tank has a gadget that claims to do it by bouncing a signal off the oil surface. I think it's probably just a range finder ? (there's one in the cookbook running off am mbed), you have to tell it how deep your tank is on little dip switches, and then it makes up it's own arbitrary units.

Here's where the magic comes in to play. From what I've read and seen on youtube, it's possible to sense liquid levels through a non-conductive container by treating the entire thing as a capacitor. So, the foil tape goes on the outside of the container and never comes in contact with the liquid contained within. Apparently this technique works wonderfully well, but doesn't work at all if the container is metal.

Thoughts?

Chris

18 Nov 2011

Hi Dedo,

dedo T wrote:

I also have this problems by reading analogue values with the mbed.

For tests i put a known DC voltage to the analogue input pin, measured by a multimeter and an oscilloscope. The measured value was quite well constant. The mbed in 98% measures the proper value and in the rest of the 2% he measures really completely random values! But the next value measured was absolutely correct again.

I also still did not have any solution for that random values occurrences, and i did not know from where they are feed in! I´m sure that my analogue value did not make such random jumps in between.

I still haven't gotten to the bottom of these random reads. Maybe I have a defective mbed? How would I tell?

Chris

02 Dec 2011

Hi everyone,

I am very excited to be writing this forum entry.

I read in a different forum thread (the one the Bob pointed out (thanks Bob!), here: http://mbed.org/forum/mbed/post/14563/) that other people were having possibly related consistency problems reading voltage with the mbed and that the problems may be related to code within the mbed library. The fix is to use the beta mbed library and recompile against that. I have been testing the same code as before, compiled with the beta mbed library on some pretty large capacitors and am getting no bad reads...I mean NONE. Let's see: measuring a (rated) 1000 uF capacitor is taking ~ 5.2 million reads and I'm getting zero bad reads, after several runs of the code. What a difference!

Kudos to the mbed team for squishing this bug!

Chris

08 Jan 2012

Hi all,

I am using library V34 still have some random value's on the analog input. Are the modifications of the above mentioned beta version library intergrated in version V34?

Thanks, Gerrit

12 Jan 2012

Hi,

I think there is more to it than that beta library alone. I have a project that does lots of analog reading, and I can get clean signals, one of the simplest things to do is to tie off any unused analog ins as well, by declaring them digital and setting them low,

here's some testing that was done by one of the mBed team to show how to get clean ADC.

http://mbed.org/users/chris/notebook/Getting-best-ADC-performance/#c2288

cheers,

Dave.

15 Jan 2012

Hi all,

After some googling, I have found a page that details perhaps the very circuit one would need to non-invasively measure liquid levels in a (non-conductive) container. Non-invasive is key, as what I really want to accurately measure are the holding tanks on my RV - the fresh water needs to stay clean and the other tanks are ummm...icky. This circuit looks like it could accurately measure the volume of fluid in the (plastic) tanks via strips of aluminum foil stuck to the outside of the thanks. That would be perfect!

Have a look at this site: http://soulysolar.mudventions.com/?p=681 and this diagram: http://soulysolar.mudventions.com/wp-content/uploads/2011/06/Oscillator.png

Apparently the circuit is a "Schmitt Trigger Oscillator". The person who wrote the blog post I linked to used his arduino to do the math, I'm hoping there could be something similar for the mbed.

I would love to be able to do something like this and connect it through my mbed.

Anyone have any experience with such circuits or suggestions?

Cheers, Chris

16 Jan 2012

This is a continual measurement, of frequency, not voltage,

For this type of circuit, you need to count how many pulses/second. Which has the potential for much higher resolution & repeatable. As opposed to the voltage crossing a threshold, like the above (as far as I am aware, I have not fully read through)

Hope this helps

Ceri

16 Jan 2012

Chris Yuzik wrote:

Hi all,

After some googling, I have found a page that details perhaps the very circuit one would need to non-invasively measure liquid levels in a (non-conductive) container. Non-invasive is key, as what I really want to accurately measure are the holding tanks on my RV - the fresh water needs to stay clean and the other tanks are ummm...icky. This circuit looks like it could accurately measure the volume of fluid in the (plastic) tanks via strips of aluminum foil stuck to the outside of the thanks. That would be perfect!

Have a look at this site: http://soulysolar.mudventions.com/?p=681 and this diagram: http://soulysolar.mudventions.com/wp-content/uploads/2011/06/Oscillator.png

Apparently the circuit is a "Schmitt Trigger Oscillator". The person who wrote the blog post I linked to used his arduino to do the math, I'm hoping there could be something similar for the mbed.

I would love to be able to do something like this and connect it through my mbed.

Anyone have any experience with such circuits or suggestions?

Cheers, Chris

You could try a 'time of flight' measurement using ultrasonics. The speed through liquid is slower than air and you should be able calculate the level of the fluid using the time taken to bounce signals off the bottom of the tank.

This is getting a little off topic though isn't it?

23 Jan 2012

My apologies, I didn't realize that I was straying off topic. I thought this forum section was for discussing electronics and related projects, especially if the project would be using the mbed. Am I incorrect?

06 Jul 2015

I do not think using the ADC to measure low capacitance values is the best approach. When I needed to measure very small capacitance changes in humidity sensors I found it was better to use an analog comparator than a ADC. If you use the ADC you run into the impedance limit of the ADC circuit which limits the accuracy or response rates at low capacitance values. I think this is at least partially responsible for the erratic behavior you saw.

Using a comparator, You drive the circuit to zero V and measure the time it takes to charge the capacitor through a resistor from 0V to a value greater than the compare voltage. Most CPU have built in comparator circuits but a external comparator chip can deliver more channels and can tolerate higher compare transition voltages 8V which makes the circuit less sensitive to noise especially with remote sensors.

After some experimentation I found that my CPU allowed us to skip the comparator and measure the time required to transition from logic 0 to logic 1. I was able to use an interrupt on the change to rise high and it worked nearly as the comparator provided the wire length from the CPU to the sensor was very short.

You essentially use one IO pin to draw the circuit to 0V and then turn it to logic 1. Measure the time it takes charge through a resistor by enough to transition the sense pin to logic low to high which we detect using an interrupt. You charge the circuit through something like a 1 meg resistor but the resistor is sized to match the capacitor you are measuring and your desired sample frequency. The longer it takes to transition from logic high the higher the capacitance. This approach allows use of very high resistance to keep energy cost of measurement low and to accurately measure very low capacitance changes in small capacitance sensors. I found the pin state transition time was too variable in the CPU I was using at the time to use one pin but a single drive pin can be used for many sens pins.

Here is the original article http://correctenergysolutions.com/electronics/cap-humidity-sensor-circuit/ - If there is interest then I will make a new circuit and new mbed software for the KL46Z. I have used the same approach to measure the salt concentration in brine solutions, measure fluid levels, measure fluid thickness, measure presence / absence of fluid and distance to fluid across an air gap in an non-contact fashion. Warning there is a flaw in this drawing and my diptrace computer crashed before I had time to fix it.

To improve accuracy you run it the rise/fall cycle in a loop and average the charge times. An even better approach is to measure the number of cycles you can run in a given amount of time so it becomes a frequency counter where frequency drops as capacitance increases.

When depleting the capacitor to zero and measuring the rise time it allows a zero loss circuit during times of non-measurement since the driver pin is turned off in high impedance mode when the circuit is not active. It is important to ensure that when measuring larger capacitors that you protect the driver pin or when you set it low to drain the circuit or too much current from the capacitor can burn out the pin. To avoid that risk I found that is was easiest to use a relatively high value resistor between drive pin and the sense pin so it is essentially impossible to discharge at a rate high enough to damage the MPU. I typically like to see these circuits draw under 0.05ma when driving or discharging through a CPU drive pin. The high resistance causes a problem that the discharge needs more time to return to 0 V. I could have calculated this time but I found that it was easy to derive a pause time experimentally by starting with a large pause between readings and then decreasing it until we detected a shrinking charge time which indicated incomplete discharge. Once we found the minimum discharge time window we just increased it by a safety margin such as 2X and stored that value as a calibration value for that sensor circuit. The high resistance between the sense and drive pins can slow down the sense rate but humidity sensors were plenty fast at 200 htz.

It is not strictly necessary to drive the circuit to 0V when using the frequency count method as long as the amount of discharge time is greater than the rise time and remains constant for every cycle. You end up with a baseline voltage with humps rising to the logic detection threshold. Some capacitance sensors like our humidity sensors are destroyed if you apply a DC voltage to them for an extended period of time. I generally just use the return to 0V strategy but some fluid sensing works better at a higher base voltage in your sense plate. When allowing the circuit to carry a baseline offset voltage you must ignore the initial charge time when the circuit is first powered.

Some CPU chips leak more form the sense pin than others. Most CPU I have tested worked fine for the humidity sensors with drive resistors as high as 5 Meg but there where a few that had leakage so high that we couldn't use more than a few hundred K.

Other work on measuring capacitance: http://ww1.microchip.com/downloads/en/AppNotes/01014a.pdf http://embedded-lab.com/blog/?p=4400 http://www.electronics-diy.com/lc_meter.php

Impedance (Total Resistance Limits for ADC circuits) http://www.ti.com/lit/an/spna088/spna088.pdf

ADC Design Limits Both confirm that total impedance will be an issue when trying to measure low capacitance RC time using a ADC. http://www.freescale.com/files/microcontrollers/doc/app_note/AN2438.pdf http://www.st.com/web/en/resource/technical/document/application_note/DM00050879.pdf

Note: When measuring larger capacitors we can use the ADC and I have done so. The advantage in that context is I only need to charge the capacitor by a small amount and then take a sample. If I know it was fully empty when starting and how long it was charging and what the value of my charge resistor was I can compute the exact capacity from voltage even when it is only a fraction full. So far I find the need to measure tiny changes in small capacitance device more often.