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:
[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.