How to: soil moisture measurement?

OK, I found a couple of problems in your code.

In the code I posted, int SoilMoisture() is a function, but you are trying to use it as a subroutine (i.e not using the returned value, but calling it for its 'side effects').

But that doesn't matter because you never invoke the subroutine anyway.

But even if you had called it, it still wouldn't work, because the CPU never gets to the side effect moisture=reading which you added to the very end of the routine, right after return reading.

Kinda looks like you're getting in a hurry ;D

Try this...

/* Soil Moisture measurement v0.1 20091017
Simple circuit
Not calibrated at this moment

Started by Mike Rice, October 14, 2009
Modified by M.A. de Pablo, October 17, 2009

Circuit:
To connect two nails and a 10 KOhms resistor as shown:

digital 2---*
|

/
\ R1
/
|
|
analog 0----*
|
|
*----> nail 1

----> nail 2
|
|
|
digital 3---

*/

#define moisture_input 0
#define divider_top 2
#define divider_bottom 3

int moisture; // analogical value obtained from the experiment

int SoilMoisture(){
int reading;
// set driver pins to outputs
pinMode(divider_top,OUTPUT);
pinMode(divider_bottom,OUTPUT);

// drive a current through the divider in one direction
digitalWrite(divider_top,LOW);
digitalWrite(divider_bottom,HIGH);

// wait a moment for capacitance effects to settle
delay(1000);

// take a reading
reading=analogRead(moisture_input);

// reverse the current
digitalWrite(divider_top,HIGH);
digitalWrite(divider_bottom,LOW);

// give as much time in 'reverse' as in 'forward'
delay(1000);

// stop the current
digitalWrite(divider_bottom,LOW);

return reading;
}

void setup () {
Serial.begin(9600);

}

void loop (void) {
moisture=SoilMoisture(); // assign the result of SoilMoisture() to the global variable 'moisture'
Serial.print("Soil moisture: ");
Serial.print(moisture); // print the analogical measurement of the experiment
// later i will improve here a calculation for derive Soil Moisture in %
Serial.println();
delay(1000);
}

In addition to fixing the bugs, I corrected the polarity from my original post (my bad :-[). My original code came from an irrigation project, and 'reading' was to be a partial indication of how desirable it would be to add water (in combination with some other factors).


Grumpy Mike you are right about the electrolysis. This code basically generates a low frequency, low duty cycle AC excitation signal, and employs a synchronous demodulator to extract the data point.

Since it is AC, the harmful effects of both electrolysis and migration are reduced, and since it is a low duty cycle the effects of any residual DC offsets are further reduced, by an amount equal to the duty cycle. Also reduces power consumption, by the way.

In the original project the uC would suspend for an hour (unless interrupted), take readings and then go back to sleep. The old 6805 was not as quick as an Atmega 328, and the ADC080 was kinda slow too, but still the overall duty cycle was on the order of 1 part in 10 million.