So far we have covered aquaponics/Hydroponics automation and control, we also have a soil based system to use as a comparison.

It is best if we automate this system too, Just so we have an accurate measurement of water used and the moisture level of the soil during the grow.

 

Probe Choices:

There are two main types of probes on the market for a reasonable price:

>Capacitive sensors [long lasting]

>Resistive Sensors [Cheap, but degrade]

 

This script will work for both types of probes.

[My probe draws a max of 35ma, that is very close to the arduino 40ma max rating, check yours does not exceed this on the spec sheet]

 

The pinout:

 

pinout

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

 

How to use:

>Wire up following pinout as a guide [moisture sensor can change, so use the pin descriptions on the board. you want to use analog output not digital]

>Place soil and temperature sensor in very dry soil [very dry!] click up on the lvd buttons and make a note of the ADC readout

>On same ADC readout, soak the soil with water and make a not of the ADC readout

>Plug these ADC values into the top of the code and reload to the board

>Thats it, leave the probe in the soil for as long as you like to log data about the soil [min/max temperature and moisture levels]

 

 

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.

 

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;

 

 

//********************** 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 , HIGH );

  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()

{

GetMoisture();

GetTemp();         

Log();

read_LCD_buttons();

Uptime():

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

delay(100); //Stops us entering the GETEC loop twice

}

//************************************** 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(){

 

 

 

 

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;

;}

//************************** 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 subject:

>Making the moisture probes last longer

>Automated watering

>A Long Lasting Diy Probe? [You can probably guess what this will be made from]

>Logging water usage