Capacitative Measurement

For my final project I am making an automatic plant watering pot. For that there will be a water storage tank to hold water for pumping into the soil. I want the tank to have way to measure the water level in the tank so it can light up if the water level is too low. For this weeks lab my goal was to test out making a water level sensor on a disposable water bottle.

The water level meter measure the capacitance to determine the water level. In order to determine what outputs went occured with what water levels, i modeled the situation with an equation that I could put into the code. In order to derive that equation I took five hundred data points and used linearition methods.

meter

Build:

  1. Cut two 1.5 centimeter wide strips of copper tape for the height of your bottle
  2. Sauter 22 gauge wire to the end of each
  3. Put electrical tape over the connections
  4. Take off the backing of the copper tape and tape the strips onto the bottle vertically
  5. Plug one wire into digital pin 4 on the arduino and the other into analog zero

The the circuit is complete.

Calibration:

Download this arduino code onto the arduino to begin calibration…

  • Data Collection:
  1. Empty the bottle and run the code with the serial monitor (0 percent full or for our purposes 0.00)
  2. Copy the first 100 data points from the serial monitor and put them into column E of the excel sheet
  3. Fill the bottle to be a quarter full and clear the serial monitor (25 percent full or for our purposes 0.25)
  4. Copy the first 100 data points from the serial monitor and put them into column D of the excel sheet
  5. Fill the bottle to be a half full and clear the serial monitor (50 percent full or for our purposes 0.50)
  6. Copy the first 100 data points from the serial monitor and put them into column C of the excel sheet
  7. Fill the bottle to be a 3 quarters full and clear the serial monitor (75 percent full or for our purposes 0.75)
  8. Copy the first 100 data points from the serial monitor and put them into column B of the excel sheet
  9. Fill the bottle to be full and clear the serial monitor (100 percent full or for our purposes 1.00)
  10. Copy the first 100 data points from the serial monitor and put them into column A of the excel sheet
  • Average each column of data using the AVERAGE function on Excel (this also works on google sheets)
  • Make a table of water level vs output (water levels should be 0.00-1.00 and need to matched up with their corresponding averages)
  • Graph the data and determine what parent function it best matches, then once you figure it out, linearize the data set
  • Take a best-fit of the linearized data set

If you don’t know how to linearize, check out this link!

When I was trying to linearize my data I had trouble at first because I was convinced that the data represented a root function so my linearization wasn’t quite working out. I decided to try linearizing it as a cube root function which gave me a much more linear line that I ended up using

  • Take the best fit and solve for the water level, this is the equation that needs to be put into the code for the next section

Measuring Water Level

Download this arduino code to begin water level measurement…

  • Replace the return in the waterLevelCalc() method with whatever your equation is for max accuracy

My Water Level Sensor

Here is a picture of my excel graphs. The one on the left is the graph of the original data and the one on the right is the graph of the linearized data. As you can see, my R^2 value of 0.9918 is very close to 1 so my data shows a strong linear correlation between the cube root of the water level(x-axis) and the capacitance(y-axis).

graphs

Here is my work for solving for the water level

equation

Click to download my Excel file

There were some pros and cons of measuring water level this way…

Pros:

  • gives an estimate for any water level
  • allows use of a mathematical equation that can easily be altered

Cons:

  • after a couple runs, the water level meter loses accuracy (probably from water droplets or other factors)
  • long calibration process

For my water level meter for the final project, what I will probably do is have a meter at the top of the tank and a meter at the bottom and then measure the difference between their capacitance to determine if the water level is running low in order to avoid having to recalibrate all the time.

potSketch

Code

These are the two programs I used.

Calibration


//rx_tx03  Robert Hart Mar 2019.
//  Program to use transmit-receive across space between two conductors.
//  One conductor attached to pin4, one to A0
//
//  This program has a function "tx_rx() which returns the value in a long integer.
//
//  Optionally, two resistors (1 MOhm or greater) can be placed between 5V and GND, with
//  the signal connected between them so that the steady-state voltage is 2.5 Volts.
//
//  Signal varies with electric field coupling between conductors, and can
//  be used to measure many things related to position, overlap, and intervening material
//  between the two conductors.
//
long result;   //variable for the result of the tx_rx measurement.
void setup() {
  pinMode(4, OUTPUT);     //Pin 4 provides the voltage step
  Serial.begin(9600);
}
/**
 * measures capacitance for 100 samples and averages data to reduce noise
 * @return average out inputs from capacitive measurement
 */
long tx_rx() {        //Function to execute rx_tx algorithm and return a value
  //that depends on coupling of two electrodes.
  //Value returned is a long integer.
  int read_high;
  int read_low;
  int diff;
  long int sum;
  int N_samples = 100;    //Number of samples to take.  Larger number slows it down, but reduces scatter.
  sum = 0;
  for (int i = 0; i < N_samples; i++) {
    digitalWrite(4, HIGH);             //Step the voltage high on conductor 1.
    read_high = analogRead(A0);        //Measure response of conductor 2.
    delayMicroseconds(100);            //Delay to reach steady state.
    digitalWrite(4, LOW);              //Step the voltage to zero on conductor 1.
    read_low = analogRead(A0);         //Measure response of conductor 2.
    diff = read_high - read_low;       //desired answer is the difference between high and low.
    sum += diff;                       //Sums up N_samples of these measurements.
  }//for (int i = 0; i < N_samples; i++)
  return sum / N_samples;
}                         //End of tx_rx function.
void loop() {
  result = tx_rx();
  Serial.println(result);
}//loop

Measurement w/ Completed Meter


//rx_tx03  Robert Hart Mar 2019.
//  Program to use transmit-receive across space between two conductors.
//  One conductor attached to pin4, one to A0
//
//  This program has a function "tx_rx() which returns the value in a long integer.
//
//  Optionally, two resistors (1 MOhm or greater) can be placed between 5V and GND, with
//  the signal connected between them so that the steady-state voltage is 2.5 Volts.
//
//  Signal varies with electric field coupling between conductors, and can
//  be used to measure many things related to position, overlap, and intervening material
//  between the two conductors.
//
long result;   //variable for the result of the tx_rx measurement.
void setup() {
  pinMode(4, OUTPUT);     //Pin 4 provides the voltage step
  Serial.begin(9600);
}
/**
 * measures capacitance for 100 samples and averages data to reduce noise
 * @return average out inputs from capacitive measurement
 */
long tx_rx() {        //Function to execute rx_tx algorithm and return a value
  //that depends on coupling of two electrodes.
  //Value returned is a long integer.
  int read_high;
  int read_low;
  int diff;
  long int sum;
  int N_samples = 100;    //Number of samples to take.  Larger number slows it down, but reduces scatter.
  sum = 0;
  for (int i = 0; i < N_samples; i++) {
    digitalWrite(4, HIGH);             //Step the voltage high on conductor 1.
    read_high = analogRead(A0);        //Measure response of conductor 2.
    delayMicroseconds(100);            //Delay to reach steady state.
    digitalWrite(4, LOW);              //Step the voltage to zero on conductor 1.
    read_low = analogRead(A0);         //Measure response of conductor 2.
    diff = read_high - read_low;       //desired answer is the difference between high and low.
    sum += diff;                       //Sums up N_samples of these measurements.
  }//for (int i = 0; i < N_samples; i++)
  return sum / N_samples;
}                         //End of tx_rx function.
/**
 * uses capacitance to estimate water level
 * @param capacitance measurement
 * @return expected water level
 */
 double waterLevelCalc(long capacitance){
  double waterLevel=0;
  waterLevel= pow(((capacitance-62.988)/645.07),3);
  return (double)(waterLevel* 100);
 }//String waterLevelCalc(long int capacitance){
void loop() {
  result = tx_rx();
  Serial.println(waterLevelCalc(result));
  //delay(100);
}//loop

Temperature Sensor

labeledTempSensor Temperature Sensor:

  1. The left pin of the temperature senor needs to be connected to 5V
  2. The middle pin needs to be connected to be connected to analog pin 0
  3. The right pin needs to be connected to ground

More details for how to use a temperature sensor can be found here