The main problem with the probes in the soil is the degradation from electrolysis of the probe material, you can either buy a capacitive probe or a gold plated resistive probe but maybe we can use a few tricks in the software to prolong the probe life?

We dont need thousands of readings from the moisture sensor, one reading every 5 minutes will probably suffice for most applications. So lets only power the sensor up for those readings.

 

This Code is suited for long term measurements, use the previous code if you want a portable device that gives instant readings.

 

The pinout:

p

[note mistake on pinout for probe, Should be Analog:A8 Ground:A9  Power A12]

 

This is the code I will be using to compare degradation, in this code we take a reading every 5 minutes and only power the probe for the measuring time, this could improve probe life greatly.

Calibrate the probe using the last blog:

Blog:17 - Automated Soil Moisture Measurement

 

 

The Script

we are using a modified onewire and dallas library, [can be downloaded from www.michaelratcliffe.com] if your temperature does not read well, use a 10K pull up on temp data line.

Take the calibration values you got from the last blog and use them in this script

 

This script will only take one reading every 5 minutes, or when you press the right button on the LCd shield.

 

Header 1

 

 

/*

   Soil Moisture Measurment

 

   28/8/2015  Michael Ratcliffe  Mike@MichaelRatcliffe.com

   

   

          This program is free software: you can redistribute it and/or modify

    it under the terms of the GNU General Public License as published by

    the Free Software Foundation, either version 3 of the License, or

    (at your option) any later version.

 

 

    This program is distributed in the hope that it will be useful,

    but WITHOUT ANY WARRANTY; without even the implied warranty of

    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

    GNU General Public License for more details.

 

 

    You should have received a copy of the GNU General Public License

    along with this program.  If not, see <http://www.gnu.org/licenses/>.

  

    Parts:

    -Arduino - Uno/Mega

    -5v Relay

    -Water Solenoid

    -Soil moisture probe [Capacitive or resitive, doesnt matter]

    -LCD shield with buttons [DFRobot is pretty cheap]

 

 

    See www.MichaelRatcliffe.com/Projects for a Pinout and user guide or consult the Zip you got this code from

    or Search Element14 for Adapted_Greenhouse home page [lots of info here]

 

*/

//************************ Libraries needed **************************************************************//

 

 

// Both below Library are custom ones [ SEE READ ME In Downloaded Zip If You Dont Know how To install] Use them or add a pull up resistor to the temp probe

 

 

#include <OneWire.h>

#include <DallasTemperature.h>

#include <LiquidCrystal.h> //Standard LCD Lbrary

 

//************************* User Defined Variables ********************************************************//

 

 

 

 

//************* Moisture Probe Related *****************************************//

#define Soil_Pin A8

#define Soil_PWR A12

#define Soil_GND A9

 

 

//Power up the script and take note of ADC readings related to probe places in dry soil and watter logged soil

int Dry_Soil=100;

int Wet_Soil=600;

 

 

 

 

 

 

//************ Temp Probe Related *********************************************//

#define ONE_WIRE_BUS 26           // Data wire For Temp Probe is plugged into pin 10 on the Arduino

const int TempProbePossitive =22;  //Temp Probe power connected to pin 9

const int TempProbeNegative=24;    //Temp Probe Negative connected to pin 8

OneWire oneWire(ONE_WIRE_BUS);// Setup a oneWire instance to communicate with any OneWire devices

DallasTemperature sensors(&oneWire);// Pass our oneWire reference to Dallas Temperature.

 

 

 

 

//***************************** END Of Recomended User Inputs *****************************************************************//

float Soil_T=0;

float Soil_M=0;

int ADC_Reading=0;

int Reading=0;

 

 

//********************** Some Variables For Loging Min/Max Values ********************************//

float MinM=100;

float MaxM=0;

float MinT=100;

float MaxT=0;

 

 

 

 

// select the pins used on the LCD panel

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

 

 

// define some values used by the panel and buttons

int lcd_key     = 0;

int adc_key_in  = 0;

int button =0;

#define btnRIGHT  1

#define btnUP     2

#define btnDOWN   3

#define btnLEFT   4

#define btnSELECT 5

#define btnNONE   6

 

 

 

 

//**********************Some Stuff For Uptime **************************************************//

 

 

//************************** Just Some basic Definitions used for the Up Time LOgger ************//

long Day=0;

int Hour =0;

int Minute=0;

int Second=0;

long Rollover=0;

int HighMillis=0;

int Readings=0;

int Screen=0;

int buttonLast=0;

 

 

//*********************************Setup - runs Once and sets pins etc ******************************************************//

void setup()

{

  Serial.begin(9600);

  pinMode(TempProbeNegative , OUTPUT ); //seting ground pin as output for tmp probe

  digitalWrite(TempProbeNegative , LOW );//Seting it to ground so it can sink current

  pinMode(TempProbePossitive , OUTPUT );//ditto but for positive

  digitalWrite(TempProbePossitive , HIGH );

 

  //********Setting Soil Probe Pins ************//

  pinMode(Soil_Pin,INPUT);

  pinMode(Soil_PWR,OUTPUT);

  pinMode(Soil_GND, OUTPUT);

  digitalWrite(Soil_PWR , LOW );

  digitalWrite(Soil_GND , LOW );

 

 

  delay(100);// gives sensor time to settle

  sensors.begin();    //Temperature Probe

  delay(100);

 

 

  Serial.println("Soiul Moisture Measurment");

  Serial.println("By: Michael Ratcliffe  Mike@MichaelRatcliffe.com");

  Serial.println("Free software: you can redistribute it and/or modify it under GNU ");

  Serial.println("");

  Serial.println("Make sure Probe and Temp Sensor are in Ssoil");

  Serial.println("");

  Serial.println("Adjust Dry and wet values in code");

 

lcd.begin(16, 2);              // start the library

lcd.setCursor(0,0);

delay(1000);

lcd.print("Arduino Soil");

lcd.setCursor(0,1);

delay(1000);

lcd.print("Mike Ratcliffe");

lcd.setCursor(0,1);

delay(1000);

lcd.setCursor(0,1);

lcd.print("Free Software   ");

delay(1000);

lcd.setCursor(0,1);

lcd.print("Mike Ratcliffe");

delay(1000);

  lcd.setCursor(0,0);

lcd.print("To Navigate         ");

  lcd.setCursor(0,1);

lcd.print("Use Up-Down     ");

delay(3000);

 

 

 

};

 

 

//******************************************* End of Setup **********************************************************************//

 

 

 

 

//************************************* Main Loop - Runs Forever ***************************************************************//

//Moved Heavy Work To subroutines so you can call them from main loop without cluttering the main loop

void loop()

{

//Runs every 5 minutes [thats what 300000 millis means]

if((millis()%300000<=10000 && Reading==0)|| button==1){

Reading=1;

GetMoisture();

};

if(millis()%300000>=20000){

Reading=0;

};

 

 

 

 

GetTemp();         

Log();

read_LCD_buttons();

Uptime();

PrintReadings();   // Cals Print routine [below main loop]

delay(100);

 

 

}

//************************************** End Of Main Loop **********************************************************************//

 

 

 

 

 

 

//************ This Loop Is called From Main Loop to get Soil Temperature************************//

void GetTemp(){

 

 

 

 

sensors.requestTemperatures();// Send the command to get temperatures

Soil_T=sensors.getTempCByIndex(0); //Stores Value in Variable

 

 

 

 

;}

//************************** End OF Tmperature Function ***************************//

 

 

 

 

 

 

//************ This Loop Is called From Main Loop to get Soil Moisture************************//

void GetMoisture(){

 

 

//Turning probe on for measurment and delaying a little to get stable reading

digitalWrite(Soil_PWR , HIGH );

delay(200);

 

ADC_Reading=analogRead(Soil_Pin);

// Map only gives integers, we will need to modify to get better readings  [thats what all the *100 are about

Soil_M = map(ADC_Reading*100, Dry_Soil*100, Wet_Soil*100, 0, 100*100);

Soil_M=Soil_M/100;

Readings=1;

 

 

//Turning Probe back off

digitalWrite(Soil_PWR , LOW );

 

 

;}

//************************** End OF Moisture Function ***************************//

 

 

 

 

 

 

 

 

 

 

//***This Loop Is called From Main Loop- Prints to serial usefull info ***//

void PrintReadings(){

 

 

if (button>=1||Readings==1) {

  Readings=0;

                    

                      if(Screen==1){

                      lcd.setCursor(0,0);

                      lcd.print("Arduino EC-PPM   ");

                      lcd.setCursor(0,1);

                      lcd.print("M:               ");

                      lcd.setCursor(2,1);

                      lcd.print(Soil_M);

                      lcd.setCursor(9,1);

                      lcd.print(Soil_T);

                      lcd.print("'C");

                      }

                    

                      else if(Screen==2){

                      lcd.setCursor(0,0);

                      lcd.print("ADC Readout            ");

                      lcd.setCursor(0,1);

                      lcd.print("                    ");

                      lcd.setCursor(0,1);

                      lcd.print(ADC_Reading);

                    

                   

                        

                      }

                       else if(Screen==3){

                      lcd.setCursor(0,0);

                      lcd.print("Mn:              ");

                       lcd.setCursor(3,0);

                       lcd.print(MinM,0);

                       lcd.setCursor(9,0);

                      lcd.print(MinT);

                      lcd.print("'C");

                      lcd.setCursor(0,1);

                      lcd.print("Mx:               ");

                      lcd.setCursor(3,1);

                      lcd.print(MaxM,0);

                      lcd.setCursor(9,1);

                      lcd.print(MaxT);

                      lcd.print("'C");

                    

                       }

                        else if(Screen==4){

                   

                      lcd.setCursor(0,0);

                      lcd.print("Uptime Counter:              ");

                    

                      lcd.setCursor(0,1);

                      lcd.print("                                     ");//Clearing LCD

                      lcd.setCursor(0,1);

                      lcd.print(Day);

                      lcd.setCursor(3,1);

                      lcd.print("Day");

                      lcd.setCursor(8,1);

                      lcd.print(Hour);

                      lcd.setCursor(10,1);

                      lcd.print(":");

                      lcd.setCursor(11,1);

                      lcd.print(Minute);

                      lcd.setCursor(13,1);

                      lcd.print(":");

                      lcd.setCursor(14,1);

                      lcd.print(Second);

                    

                    

                       }

 

 

  

};

 

 

 

 

};

 

 

 

 

void read_LCD_buttons(){

  adc_key_in = analogRead(0);      // read the value from the sensor

// my buttons when read are centered at these valies: 0, 144, 329, 504, 741

// we add approx 50 to those values and check to see if we are close

if (adc_key_in > 1000)  button =0;

 

 

else if (adc_key_in < 50)   button =1;

else if (adc_key_in < 250)  button =2;

else  if (adc_key_in < 450)  button =3;

else if (adc_key_in < 650)  button =4;

else if (adc_key_in < 850)  button =5;

 

 

if(button==2&&buttonLast!=button){

Screen++;

}

else if (button==3&&buttonLast!=button){

Screen--;

};

if (Screen>=4) Screen=4;

if(Screen<=1) Screen=1;

 

 

buttonLast=button;

};

 

 

//******************************* LOGS Min/MAX Values *******************************//

void Log(){

 

  if(Soil_M>=MaxM)  MaxM=Soil_M;

  if(Soil_M<=MinM)  MinM=Soil_M;

 

  if(Soil_T>=MaxT) MaxT=Soil_T;

  if(Soil_T<=MinT) MinT=Soil_T;

}

 

 

//**************************** Uptime Counter ********************************************//

void Uptime(){

//** Checks For a Second Change *****//

//** Making Note of an expected rollover *****// 

if(millis()>=3000000000){

HighMillis=1;

 

 

}

//** Making note of actual rollover **//

if(millis()<=100000&&HighMillis==1){

Rollover++;

HighMillis=0;

}

                        

long secsUp = millis()/1000;                     

Second = secsUp%60;

Minute = (secsUp/60)%60;

Hour = (secsUp/(60*60))%24;

Day = (Rollover*50)+(secsUp/(60*60*24));  //First portion takes care of a rollover [around 50 days]

                  

};

 

 

 

 

 

 

 

 

 

 

 

Future Blogs on this topic:

It would be beneficial if we tested the degradation of a permanently on probe vs a reading powered on version and a capacitive one in there too. A blog on this will be up in a few months [its a long test]

 

And a blog on our diy probe.