Capacitance meter using the Photon


#21

Anyone have any suggestions of how to multiply a resistance range. How to change 0- 10 k ohm resistance to 0-1000 K ohm resistance. Putting 100 variable resistors in series seems an expensive approach. Is there a circuit that can do the same thing?

Note: It looks like my range of timing is between about 13,000,000 microseconds and 90 microseconds. Since at some point above the top end 13,000,000 (us) the Photon breaks and shows a solid green LED, and at the bottom end 90 (us) seems to be the duration of one loop.

I am thinking about 3 ways to auto adjust the charging resistance to detect a greater range of unknown capacitors.

  1. If I charge the capacitor using PWM, I can then adjust the power sent to the unknown capacitor which should allow me to charge a greater range of capacitors

  2. If I could find a digital potentiometer board it would be easy to auto adjust the charging resistance and auto adjust the calibration constant. Unfortunately I can’t seem to find any digital potentiometer boards that have a large resistance range. Here is something with a 0 - 10 K ohm range. http://www.uctronics.com/x9c103s-digital-potentiometer-module-3-5v-for-arduino.html?feedback=1

  3. Manually adjust the charging resistance using a potentiometer with analog sensor such as the link below unfortunately this is also only in the 0-10 K ohm range.

Any suggestions?


#22

Why would you need 100 variable resistors? Given the wide range of timings that are useful, I would think that 8 to 16 fixed resistors would be enough to give you good readings over a wide range of capacitance values. You could use something like a CD4067 16 channel demultiplexer to switch between the resistors (taking into account the ~100 ohm resistance of the 4067 itself).

Another approach to measuring the capacitance would be to use a 555 timer (or the CMOS equivalent). You would probably only need a few resistors to cover the range of capacitance values that you want. For instance, using 1 megohm resistors for the two timing resistors would give a frequency of 481 kHz with a 1pF capacitor, and a frequency of 0.481 Hz for a 1 microfarad capacitor. I don’t know whether this would be any more accurate or simple than what you’re doing now.


#23

If you used PWM, then wouldn’t you also need to add a series diode, otherwise when the 1010101010, etc, bit stream was zero it would discharge the capacitor wouldn’t it?

Multiple charging resistors, something like 100K, 1M, 10M on three different digital pins sounds like it’s worth trying. Do you need transistors? Can you not just set the unused pins to input?

I don’t know about solid green. Perhaps it’s because the photon hasn’t connected to the wifi/cloud for too long, though I thought that tended to flash green/cyan. I don’t use the cloud much. Can you manually control the wifi/cloud, so that you temporarily disengage them while measuring the capacitor?


#24

Since your not switching from output to input I don’t think that will discharge the cap but if it does I will know why.

Never thought of that you are probably correct. The while loop will totally control the Photon and cause a loss of cloud connectivity since Particle.process() is probably not being called. That should be an easy fix, thanks @timx for the tip.

Looks interesting https://www.digikey.com/catalog/en/partgroup/cd74hc4067-analog-digital-mux-breakout-board/56866

I think you are correct. Output LOW should deactivate them and input LOW should connect them, just have to coordinate two pins for each resistor pair since I would have to shut down the old circuit and activate the new circuit. Good idea,


#25

Good news. Adding Particle.process(); in my charging while loop solved the dead photon solid green LED issue (Thanks for the idea @timx )

Bad news:PWM for charging capacitors is out of the question. Not because it discharges the cap, but because it does not seem to be a linear relationship. I start charging at PWM 255 and then reduce the amount if the microseconds are not long enough, this simulates slowing the capacitor charging.

Well nothing really happens until I get down to about PWM 40 and then the charging of the capacitor dramatically slows down. Not sure if it is supposed to be a logarithmic relationship but it sure looks like one. Anyway, I have stopped using PWM and am back to @timx suggestion of controlling the resistance using digital pins. Just have to get my brain around how the circuit would look.

Here is my circuit:

How can I replace the 100 K ohm resistor with a 1 M ohm resistor using only the digital pins? (probably figure this out at 3 am this morning :unamused:)


#26

Have you considered something like this



#27

That looks much better than what I was able to find. Thanks @ScruffR . I think I will order a few of those. Great price. ($1.50)

So I ordered a few of those today, but while I am waiting for the shipment I am still confused how to make @timx digital pin controlled 3 resistors.

As a test I tried connecting an LED with three different resistors in parallel and then switching pins from input_pulldown digitalRead (to disable it) to setting one at a time to output low (to enable it in the circuit) but did not get the expected results. The LED is very dim and flashes quickly instead of the 2 second delay I had between switching on resistors. I know the circuit is wrong, just not sure how to fix it. If I put the resistors in series I am not sure how to bipass them.

Here is my circuit

and here is my code

void setup() {

pinMode(D0, OUTPUT);
digitalWrite(D0, HIGH);  // attempt to turn LED on

}

void loop() {

resetAll();
pinMode(D2, OUTPUT);
digitalWrite(D2, LOW);
Particle.publish("LOW","D2", 60, PRIVATE);
delay(2000);

resetAll();
pinMode(D3, OUTPUT);
digitalWrite(D3, LOW);
Particle.publish("LOW","D3", 60, PRIVATE);
delay(2000);

resetAll();
pinMode(D4, OUTPUT);
digitalWrite(D4, LOW);
Particle.publish("LOW","D4", 60, PRIVATE);
delay(2000);

}

void resetAll(){

pinMode(D2,INPUT_PULLDOWN);
digitalRead(D2);

pinMode(D3,INPUT_PULLDOWN);
digitalRead(D3);

pinMode(D4,INPUT_PULLDOWN);
digitalRead(D4);

}


#28

I hope you haven’t damaged anything with that circuit. When D0 is HIGH and D2 is LOW, for instance, you are essentially bypassing your 10k ohm resistor (its in parallel with a wire, a zero ohm resistor), effectively connecting your LED directly to ground (D2 in the output low state) with no current limiting resistor; that’s not a good thing.

If I understand what you’re trying to do, you want those connections to D2, D3, and D4 to be on the other side of the resistors, and eliminate the connection to ground. If you want the LED turned on through the 10k resistor, you should have D2 LOW, and D3 and D4 set as input (high impedance). Also, the 100 ohm resistor is probably not big enough to keep the current under the max of 25 mA that the pins can source and sink.

Your other circuit above (with the capacitor in it) is correct I think. You can add more resistors between a GPIO pin and the common point where the two resistors you show are connected together (along with the capacitor and the yellow line to A0). The resistor you want to charge the capacitor through should have its GPIO pin set to OUTPUT HIGH, and all the others should be set to INPUT.


#29

Wow. thanks @Ric for spending the time on the explanation and great circuit diagrams. I was a little lost on the circuit. Can someone explain why I don’t need to use INPUT_PULLDOWN or INPUT_PULLUP and I also did not need to do digitalRead(D2);. Just setting the pins to INPUT seems to be enough. The below sketch works fine

void setup() {

    pinMode(D0, OUTPUT);
    digitalWrite(D0, HIGH);  // attempt to turn LED on

}

void loop() {

    resetAll();
    pinMode(D2, OUTPUT);
    digitalWrite(D2, LOW);
    Particle.publish("LOW","D2", 60, PRIVATE);
    delay(2000);
    
    resetAll();
    pinMode(D3, OUTPUT);
    digitalWrite(D3, LOW);
    Particle.publish("LOW","D3", 60, PRIVATE);
    delay(2000);
    
    resetAll();
    pinMode(D4, OUTPUT);
    digitalWrite(D4, LOW);
    Particle.publish("LOW","D4", 60, PRIVATE);
    delay(2000);
    
    resetAll();
    Particle.publish("All","OFF", 60, PRIVATE);
    delay(2000);

}

void resetAll(){
    
    pinMode(D2,INPUT);
    pinMode(D3,INPUT);
    pinMode(D4,INPUT);
    
}

#30

The purpose of setting the pins to INPUT is to effectively disconnect the resistors that are connected to those pins. In input mode, the pin has a high impedance that limits the current through those resistors to a very low level, not quite the same as totally disconnecting them, but close enough. If you use INPUT_PULLDOWN or INPUT_PULLUP you are connecting the resistors to ground or 3.3 volts, respectively, through a ~40kOhm resistor, which is something you don’t want to do in this case. I’m not sure why you had the digitalRead in the first place; you would only use that if you were interested in seeing the voltage on that pin, but you’re not, you are only using those pins to either connect or disconnect your resistors from the circuit.


#31

So with some minor changes my capacitance meter code is working fine. I just have to wait until I get back to school to test it with some really small capacitors using some really larger resistors. Nice part with this code is that I can set calibration constants for each of the 3 resistors to get the values more accurate for the range that the resister is going to be used. That part (the calibration constant) might be a bit tricky to set when my digital potentiometers arrive.


#32

There are other varieties out there. I think you wanted >10k? There is a selection of 100k ones at Newark/Element 14 that talk over I2C or SPI or whatever.


#33

That is a nice seqway into my next topic, the Photon test PCB. Has anyone made one?


#34

I just need some bigger resistors to test the code at the pF level.

Here is what I have at the moment but putting 14 x 470 K ohm resistors in series is still not big enough

https://go.particle.io/shared_apps/592f3a98b0c51c3ee2000f3d


#35

According to this:

Multiplying the resistance in ohms against the capacitance in farads gives you how many seconds it takes to charge to 63.2%.

As an example, for a 30pf capacitor and 6.58M of resistors (14*470k) the time constant would be: 0.0001974 seconds, which is 197 microseconds. However, in your code you have set a threshold of approximately 25% (A0Cutoff = 1000/4095) of charge so your circuit actually triggers much sooner than that.

This graph illustrates the exponential charging curve for a resistor and capacitor in series. (The preview doesn’t show the correct diagram. Find the graph named “capacitor voltage step-response”)

I wonder whether it’s worth trying increasing A0Cutoff to 2588 or 3542, corresponding to 1t and 2t respectively. That might help a little for low value capacitors by letting them charge for longer and therefore more sets of 90uS loops.

I don’t know about increasing the value of your charging capacitors. There much surely be some limit at which internal resistance or leakage becomes significant enough to skew the readings, but I don’t have the experience of ADC to know when/whether that occurs.


#36

I would not try such large resistors in this application with adding an op-amp to buffer the inputs since the ADC inputs on the ST Micro parts in Particle devices are not buffered. The ADC works in such a way that relatively low resistance must be used (say 20k ohm) or the ADC itself can become a significant current source charging the capacitor.


#37

@bko, I totally agree and suggested this near the beginning of this thread. Impedance (not resistance) is not something folks are very familiar with, especially in context of ADCs. No one stopped to ask WHY Atmel has a front-end op-amp on their ADCs!


#38

@peekay123 and @bko do you guys have a solution or should I just not run the program with any resistor over 20 K ohm?

Is any of this dangerous for the Photon, or is it just going to give bad readings?

What is strange is that I am getting good readings between:
1000 uF – 0.000050 uF


#39

@rocksetta, @bko and I both indicated that you should add a unity gain op-amp buffer! This will provide the impedance isolation needed. :wink:


#40

Looking how to do that. Finding info here:

and here:

https://www.facstaff.bucknell.edu/mastascu/eLessonsHTML/OpAmps/OpAmp3Note1Buffer.html

So the basic circuit looks fairly easy

https://www.facstaff.bucknell.edu/mastascu/eLessonsHTML/OpAmps/OpAmp3A01.gif

Using @Ric slightly changed Capacitor test circuit where would this unity gain op-amp buffer go and what chip would you suggest if it isn’t just a simple transistor.