Jump to content

Banner.jpg.b83b14cd4142fe10848741bb2a14c66b.jpg

Cloud and Rain Sensor


Gina

Recommended Posts

Just tried 220pF and reading 452 or 460 pF.

A bit later...  Added 47pF across the 220pF and it made no difference whatsoever :(

If I were to use this method of measurement it seems it would need quite a lot of rain to alter the reading - 25% coverage at least, so I'm going to try the other way.

Adding various ceramic capacitors by hand is rather tedious - I could do with a capacitance box :D  I guess I could make one up.  Hmmm...

Link to comment
Share on other sites

  • Replies 61
  • Created
  • Last Reply

This is the logic of the "pump" method.

  1. Discharge C1 ready for new measurement
  2. Delay
  3. While voltage across C1 is below threshold
  4.     Set count to zero
  5.     Charge C2
  6.     Delay to allow C2 to charge
  7.     Transfer charge from C2 to C1
  8.     Delay to allow C2 to discharge into C1
  9.     Check if threshold exceeded
  10. end-of-while-loop.

count gives the capacitance ratio.

Here is more detail on some of the above steps :-

1.  Set both digital pins to OUTPUT and logic 0

5.  Set pin D8 to INPUT (high resistance) and D7 to OUTPUT logic 1

7.  Set pin D7 to INPUT and D8 to OUTPUT logic 0

9.  Check if voltage on A0 is above 63%

post-13131-0-45167900-1432824071_thumb.j

Link to comment
Share on other sites

Putting this logically, the main loop looks like this :-      (DUT is Device Under Test in this case a capacitance of 100pF upwards)

  1. Discharge both capacitors ready for measurement cycle with wait.
  2. Zero the count
  3.     WHILE voltage below threshold {
  4.         Charge DUT and wait
  5.         Transfer charge and wait
  6.         Increment count
  7.     }
  8. Display the count and value of DUT.

This loop would be run for each measurement.

Link to comment
Share on other sites

Here is my first attempt at a sketch for the charge pump capacitance meter.  It compiles but doesn't produce any output :grin:

// Pump type low capacitance meter - Gina Davis 2015-05-28 1750// File name Capacitance_Meter_Pump_Type_01// // Device Under Test (DUT) is charged to 5v through a resistor// Charge in DUT is transferred to a reference capacitor// Charge builds up in steps in reference capacitor, partly discharging DUT// This is allowed to happen a number of times until the charge on the//   reference capacitor has built up to a predefined level by reading voltage// Cycles are counted and the count indicates the ratio of capacitance values// The above is reapeated to take multiple measurements as required#define analogPin      0    // analog pin for measuring capacitor voltage#define chargePin      7    // pin to charge the DUT capacitor#define bottomPin      8    // pin to control the reference capacitorint refCap = 47000;         // Reference capacitor value in pFint count = 0;//void disghargeAll() {  pinMode(chargePin, OUTPUT);  digitalWrite(chargePin, LOW);    pinMode(bottomPin, OUTPUT);  digitalWrite(bottomPin, LOW);  delay(1);}void chargeC2() {  pinMode(bottomPin, INPUT);  pinMode(chargePin, OUTPUT);  digitalWrite(chargePin, HIGH);  delay(1);    }void transferCharge(){  pinMode(chargePin, INPUT);  pinMode(bottomPin, OUTPUT);  digitalWrite(bottomPin, LOW);  delay(1);    }void setup(){  disghargeAll();  Serial.begin(9600);             // initialize serial transmission for debugging}void loop(){  disghargeAll();  count = 0;  while(analogRead(analogPin) < 648){   // 63% of 1023 (full-scale voltage)     chargeC2();    transferCharge();    count ++;  }  Serial.print("Count = ");   Serial.print(count);  if (count > 0) {     Serial.print(" ");    Serial.print(refCap / count);    Serial.println(" picoFarads");  }  else { Serial.println(" Overflow"); }} 
Link to comment
Share on other sites

I'd better calculate the delay required to let the capacitors charge and discharge.

I'm using a series resistor of 1K2 so the time constant for a 100pF capacitor is 1.2 x 10^3 x 10^-10 = 1.2 x 10^-7 = 12 microseconds - way below the 1ms delay I've given it.  The reference capacitor is discharged by the full force of the Arduino.  Maybe I ought to add a discharge resistor to reduce the current to below 40mA.  5v @ 40mA = 125 ohms.  If I used 150R the TC for the ref cap would be 150 x 47 ns = 7ms.  I'll change the "discharge all" delay to 100ms :D  And add a 150R resistor.

Now to the expected count and time to get a result.  Count will be something greater than 47000 / 100 ie 470.  As the reference capacitor is pumped with charge from the DUT, the voltage rises and the DUT is not fully discharged - only by the difference in voltages.  At the end of the count the DUT will be adding only 100-63% of it's charge per count. ie. 27%.  The delay added in each cycle is 2ms so the measurement time will be between around 1-3s.  (If the charge transfer were only 27% it would take 3.7s to reach trigger level - the real time will be somewhere between that and a second).

Link to comment
Share on other sites

// RCTiming_capacitance_meter//   Paul Badger 2008  Modified by Gina Davis 2015 for low capacitance.// Demonstrates use of RC time constants to measure the value of a capacitor //// Theory - A capcitor will charge, through a resistor, in one time constant, // defined as T seconds where//    TC = R * C// //    TC = time constant period in seconds//    R = resistance in ohms//    C = capacitance in farads////  The capacitor's voltage at one time constant is 63.2% of the charging voltage.////  Hardware setup://  Test Capacitor between common point and ground//  Test Resistor between chargePin and common point//  220 ohm resistor between dischargePin and common point/  Wire between common point and analogPin (A/D input)//#define analogPin      0          // analog pin for measuring capacitor voltage#define chargePin      13         // pin to charge the capacitor#define dischargePin   11         // pin to discharge the capacitor#define resistorValue  1000000.0F // charging resistor value                                  // F means compliler it's a floating point valueunsigned long startTime;unsigned long elapsedTime;float picoFarads;//void setup(){  pinMode(chargePin, OUTPUT);     // set chargePin to output  digitalWrite(chargePin, LOW);    Serial.begin(9600);             // initialize serial transmission for debugging}//void loop(){  digitalWrite(chargePin, HIGH);  // set chargePin HIGH and capacitor charging  startTime = micros();  while(analogRead(analogPin) < 648){ // 647 is 63.2% of 1023, ie. full-scale voltage   }  elapsedTime= micros() - startTime;// convert microseconds to seconds ( 10^-6 ) and Farads to pF ( 10^12 ),= 10^6  picoFarads = ((float)elapsedTime / resistorValue) * 1000000;     Serial.print(elapsedTime);       // print the value to serial port  Serial.print(" uS    ");         // print units and carriage return  Serial.print((long)picoFarads);  // print the value to serial port  Serial.println(" picoFarads");   // print units and carriage return//   /* dicharge the capacitor  */  digitalWrite(chargePin, LOW);      // set charge pin to  LOW   pinMode(dischargePin, OUTPUT);     // set discharge pin to output   digitalWrite(dischargePin, LOW);   // set discharge pin LOW   while(analogRead(analogPin) > 0){  // wait until capacitor is completely discharged  }//  pinMode(dischargePin, INPUT);      // set discharge pin back to input} 

Things like:

float something = anotherfloat / 10000;

makes me wonder... In other C-languages that would truncate as the divisor is an int. Better be safe than sorry and write:

float something = anotherfloat / 10000.0;

Which would force the arithmetic to be all float and prevent any "integerisation".

/per

Link to comment
Share on other sites

Debugging...  I've put readout within the pumping loop.  The count increases as expected but the voltage goes up to 102 (out of 1023) and stops.

Link to comment
Share on other sites

Things like:

float something = anotherfloat / 10000;

makes me wonder... In other C-languages that would truncate as the divisor is an int. Better be safe than sorry and write:

float something = anotherfloat / 10000.0;

Which would force the arithmetic to be all float and prevent any "integerisation".

/per

It's not dividing by an integer but multiplying but the multiplier is a million and not specified as a floating number.  Guess it should be 1000000.0 to make it a float.  Maybe that method might work after all :D

I'm not having much joy with the second method :(

Link to comment
Share on other sites

The charge pump method doesn't seem to be doing very well either :(  Maybe 100pF is just too small to work with this sort of method.  It will need a MOSFET device due to the very high impedance we are dealing with.  I can't think of anything better than an Arduino.

Link to comment
Share on other sites

I think I might try a CMOS 555 timer.  Maybe the analogue inputs on the Arduino have too much capacitance - 100M seems high enough resistance.

Link to comment
Share on other sites

Back to the charge pump...  I triied changing the reference capacitor from 47nF to 10nF and the voltage count rose to 400 ish before flattening out.  Now if the threshold were reduced to 25% or 30% it should reach the threshold before flattening out.

It worked for a while then stopped and I can't get it to go again.  Must have had enough for today :D

Link to comment
Share on other sites

While my brain was chugging along in the background overnight I came up with another thought :)  An astable multivibrator using a CMOS Schmitt trigger device :D  Very helpfully Neil included a CD4063B Quad Schmitt Trigger chip in the box complete with datasheet on USB stick :)  Looking at the datasheet it looks like this could work, though both R and C will be at the limit.

The Arduino can then read the frequency (I hope).  Looking at the datasheet - typical values of trigger voltages are 3.3v and 1.9v @ 25C.  Formula for cycle time seems to be :-

                  | ( Vp )  ( Vdd-Vn ) |

tA = RC ln | ( ---- )  ( ---------- ) |

                  | ( Vn )  ( Vdd-Vp ) |

Vp = 3.3,  Vn = 1.9, Vdd = 5.  Vdd-Vn = 3.1, Vdd-Vp = 1.7.  So :- Vp/Vn = 3.3/1.9 and the other half is 3.1/1.7 

Altogether = 3.3x3.1/1.9/1.7 (in calculator speak :D) = 3.167 and natural log of that is 1.15 ie. after all that "brain damage" near enough the TC.

TC for R=1M and C = 100p is 10^6 x 10^-10 = 10^-4 = 100us or frequency is !0^4 = 10KHz.  Should be fine :) 

PHEW!! :D

Here's a screenshot from the datasheet.

post-13131-0-12985700-1432892988.jpg

Link to comment
Share on other sites

I knew I bought it for trying with this project but couldn't remember what i was going to do!

I feel guilty for causing you so much grief but it all makes for great reading.

I'm sorry... [emoji12]

Sent from my SM-N9005 using Tapatalk

Link to comment
Share on other sites

Right - so I have a frequency of around 10KHz reducing as the rain collects on the sensor.  I was under the impression that measuring frequency of a square wave was easy on an Arduino but it isn't with simple code.  Googling didn't turn up anything particualrly useful then I remembered I've got the "Arduino Cookbook" and that gives the code to enable an internal counter to count the pulses.  This has the advantage that no processing time is used during the timing interval.

Link to comment
Share on other sites

I think so - I have the output connected to a small piezo-electric sounder and it makes a high pitch whistle which goes lower when I put another capacitor across the 100pF.  I still can't find my oscilloscope :(  I came across it while clearing up a while back and put it where I thought I could find it - HA HA :mad:

Link to comment
Share on other sites

I'm not used to entering code by hand from a book :D...

// uses pin 5 on 168/328

//

const int hardwareCounterPin = 5;  // input pin fixed to internal timer

const int ledPin = 13;                           // LED on Uno - we'll use this to show when the timer is operating

//

const int samplePeriod = 1000;    // sample period in ms (set to one second)

unsigned int count;

//

void setup ()

{

  Serial.begin(9600);

  pinMode(ledPin, OUTPUT);

//  hardware counter setup

  TCCR1A=0;                         // reset timer/counter control register

}

//

void loop()

  digitalWrite(ledPin, LOW);

  delay(samplePeriod);

  digitalWrite(ledPin, HIGH);

// start counting

  bitSet(TCCR1B ,CS12);  // Counter Clock source is external pin

  bitSet(TCCR1B ,CS11);  // Clock on rising edge

  delay(samplePeriod);

// stop counting

  TCCR1B = 0;

  count = TCNT1;

  TCNT1 = 0;        // reset hardware counter

  if (count > 0)  {  Serial.Println(count); }

}

Later...  Copied to Arduino IDE and debugged  - now running :)  Here's the display with 100pf at top and 10pf added three quarters of the way down.  A few glitch cycles due to handling but the change can be seen :)

post-13131-0-71431800-1432930188.jpg

And here's the working code :-

//  Hardware Counter - 2015-05-29 2050//  Filename :- Hardware_Counter_01//// uses pin 5 on 168/328//const int hardwareCounterPin = 5;  // input pin fixed to internal timerconst int ledPin = 13;                           // LED on Uno - we'll use this to show when the timer is operating//const int samplePeriod = 1000;    // sample period in ms (set to one second)unsigned int count;//void setup (){  Serial.begin(9600);  pinMode(ledPin, OUTPUT);//  hardware counter setup  TCCR1A=0;                         // reset timer/counter control register}//void loop(){   digitalWrite(ledPin, LOW);  delay(samplePeriod);  digitalWrite(ledPin, HIGH);// start counting  bitSet(TCCR1B ,CS12);  // Counter Clock source is external pin  bitSet(TCCR1B ,CS11);  // Clock on rising edge  delay(samplePeriod);// stop counting  TCCR1B = 0;  count = TCNT1;  TCNT1 = 0;        // reset hardware counter  if (count > 0) {     Serial.println(count);}}
Link to comment
Share on other sites

Correction to above - 10pF capacitor was not making proper contact so I turned the oscillator off and soldered the 10pF across the 100pF. 

Here is the result.

post-13131-0-91158700-1432930958.jpg

This is better - the count has dropped as it should and count ratio is 1.116 which fits well enough with increasing C from 100pF to 110pF :)

This is looking good :)  I'll do some tests with other values though just to prove this isn't a fluke.

Link to comment
Share on other sites

I've added a 22pF to the 100pf and 10pF so a nominal total of 132pF a ratio of 1.32.

Old count with 100pF = 16723   New count = 12424  giving a ratio of 1.346.

Note that the capacitors I'm using for this test are small disc ceramics with (I think) 10% tolerance and not designed to be accurate - they're basically for decoupling.

I think I'll add code to display the capacitance based on the count for 100pF :D

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. By using this site, you agree to our Terms of Use.