Leaf Wetness
-
Leaf wetness is important to know to detect for crops the neet to make some treatments to avoid some diseases (tomatoes, grapes...)...
With soil humidity and temperature, it is an element important to monitor your crops.
In order to make it, some parts are needed:
- a rain sensor whicl looks like to work as the Davis expensive one, this one is double sided and inexpensive.
- a box enclosure that can work in the outside
- an arduino with radio (and good software ;-))
- and a source of energy.
or that last point, I'm wondering how to make it since I have both 5V and 3.3V arduini, and 2xAAA or 3xAA batteries holders.
-
From this document here is the caracteristic of the leaf wetness response to events:
-
I'll try to power a 3.3V mini pro with a 3xAA batteries holders, and have it lowered to 3.3V with an AMS1117.
Sensor resistance seems to lower when there is humidit on the holder as expected. I have 735 as analogRead when it is dry.
-
First test yesterday, device is well powered, device presentation ok, but afterward nothing was mesured... to be investigated on connexions...
-
hmmm... difficult to make it work on batteries... AND the gas sensors overloading the radio.... now I have it functional.
-
What do you mean the gas sensor overloaded the radio?
-
@ServiceXp just that I have a Mega sketch with 7 sensors reporting too frequently one one side, and on the other the weservice call was too slow, making me think of no transmission, but it was delayed in fact...
-
Some experiments:
- I left it on a window border, it varied by one ohm on the night.
- radio close is ok with the basic antenna.
- i'll try to see to put it further outside, at the moment there are more than 10°C difference along with wet cars on the morning. I fear the rain drop may not be enough sensible...
There is an alternative to the expensive davis one: LEAF WETNESS SENSOR
I'll modify the sketch to report a percentage, as other humidity sensors would do.
- 200 KOmhs = very dry leaf
- 20 KOmhs = slew fog
- 5 KOhms = heavy rain
About oxydation, dfrobot has one ground probe with this explanation:
Immersion Gold which protects the nickel from oxidation. Electroless nickel immersion gold (ENIG) has several advantages over more conventional (and cheaper) surface platings such as HASL (solder)
-
some returns:
- from Sept 11th to 15th, the batteries (3*1.5V) went from 4.5V to 3.2 as mesured today, it stopped emitting on sept 15th
- the leaf sensor shows heavy signs of oxydation without any rain during the period... this is a real problem with all those copies around... that is not a very viable solution...
I've seen another product from Spain at Liebllium that I guess I will test for I haven't found any other item...
-
@epierre said:
heavy signs of oxydation
You're definitely not the first to report this.... I've read many negative reviews of these cheap sensors.
-
@Yveaux but finding good one seems to be .... very difficult... I've spoken of immersive gold... will try to see if those are better....
-
@epierre any idea why your sensor lasted this short?
How often did it report its value to the gateway? Was it sleeping in between? Any other sensors connected?
-
@Yveaux several ideas:
- it reported every 10000
- it has no other sensor (this was my first try on batteries...)
- I had an AMS1117 in entry but I didn't needed it
- I haven't hacked the 3.3V core with the websites @a-lurker ideas
I'm waiting for the batteries from my other post because using so fast batteries is not environment friendly...
Has there been simulation of energy usage for those arduini ? e.g. for a spark core it isadvertized at 500mW
-
I've finally received from cooking hacks the leaf wetness sensor board that should be better than the one from china...
It is the one from hobby boards:
I guess I can recycle the lectronic from the cheap one on this one ?
-
It doesn't look much different that the china-ones. Is it gold-plated or something?
-
yes it is, from the hobby board site it is $2, but it is a quarter the china's size.
sorry I missed your point, it is gold plated, immersion gold.
-
Ok, so I made some adjustments from my last try:
- hobbyboard immersion gold sensor
- I kept the comparator from the other sensor to facilitate work with the arduino
- I've added a 18650 LiOn battery (5000mAh) to have an extended life cycle
Here is the sketch:
https://github.com/empierre/arduino/blob/master/LeafWetnessSensor.inoWhat I can say, is that it is very sensitive. It is now outside live in the cold.
This could be used for a leak sensor easily.
-
so my 5000mAh lasted outside... 4 days... btw I didn't remove all leds from the comparator that could be an improvement and the outside weather is quite cold.
I had a reading every 30 secs, way to quick surely...
@hek is there a way to power the radio only when necessary ? I guess the gw.sleep could be a gw.sleep and a gw.wakeup and manage the delay outside ?
-
gw.sleep() sleeps the radio as well. What do you mean by power down radio? Like cutting power using digital pin?
-
@hek said:
gw.sleep() sleeps the radio as well. What do you mean by power down radio? Like cutting power using digital pin?
yes, now you combine sleep for the radio and delay, what I mean is to have loop() run without radio, and if a transmission is needed to have a command that power it.If you have a long dry period, a device on battery will consume a lot of power having the radion on and off, if it is always off until a sensor finds something, that would save more power, no ?
-
Wake only on interrupt?
-
In my idea, a value above 0 would mean sending the info, an interrupt could be generated this way ?
-
Hey,
I am a newbie (in the forum) and in the arduino/sensors development. I bought the Leaf Wetness from cooking-hacks.com. Can I connected it to my Arduino via Analog input? Is it easy?
-
@elisavetgrig Welcome to the forum. The answer is yes to both questions. Given that the sensor is a resistive element, you need to build a voltage divider. Google "voltage divider" Arduino and you'll find lots of examples.
Cheers
Al
-
Measuring the current with DC doesn't seem to be the ideal solution:
thread
-
@FotoFieber That thread is regarding soil moisture measurements which is different than leaf wetness. For soil, capacitive is the best way to go IMHO.
Cheers
Al
-
-
ok...Thank you... I will try the "voltage divider" and I will see what will happen!
-
-
Did you mean something like the figure above? Or I only need to connect one resistor to one wire and the other wire to another pin in the Arduino?
-
@elisavetgrig You're missing the connections to a voltage source and ground. You also only need one resistor as the wetness sensor is the 2nd resistor in the voltage divider circuit. Take a look at this: http://homepage.cs.uri.edu/faculty/hamel/workshops/as220-sept-09/sensors-voltage-dividers.html.
Cheers
Al
-
You are right! I thought that I missing something... always there are Data connection, VCC connection and GND.. and I had only one! I made another dummy scheme... Is that better?
-
@elisavetgrig Take a look at the second diagram of the link I posted. Right now you show the GND pin connected to the Analog pin and Vcc is also connected to the same spot, so that's not going to work.
Cheers
Al
-
I based in the second diagram... i think that I understand it...
-
@elisavetgrig As I mentioned a few posts ago and how it's shown in the diagram on that link, is that you only need one resistor. The leaf wetness sensor becomes the other resistor in the circuit. In your last diagram, you have both the terminals of the wetness sensor connected to ground. Think of the wetness sensor as a resistor, with each of the terminals representing one leg of a regular resistor.
Cheers
Al
-
OK... So I need only one resister... I think that "Scheme 2" is closer to the solution...
-
@epierre how is the gold plating holding out on the sensor?
Is there pitting and would you'd recommend this over the style in the store?
How is the battery life with this setup?Thanks
-
Hello,
gold plating is a must have for outdoor.
I am now regarding to have something more robust in time , I'm waiting for a light with movement with solar pannel to modify it for it.
-
In the case described there is a constant battery drain when there is "wetness" (moisture) on the sensor. This also implies an electrolytic process which takes care of eroding your sensor. No matter if you use gold plating or not.
To avoid both you can supply the sensor during measurement only -and- reverse te polarity each time.
An example ketch which takes care of measuring three moisture sensors which relies on this principle.
(the actual measurement is in the "ReadMoistureValues()" routine)
/* PROJECT: MySensors / Floor moisture sensor - measures moisture PROGRAMMER: AWI DATE: june 7, 2015/ last update: june 9, 2015 FILE: AWI_FloorMoisture.ino LICENSE: Public domain Hardware: tbd .- ATmega328p board w/ NRF24l01 and MySensors 1.4 (later: Temp & Humidity - HTU21) Special: program with Arduino Pro 3.3V 8Mhz SUMMARY: Moisture by analog read a polarity switching voltage divider between (high/ low) Remarks: Fixed node-id */ #include <SPI.h> #include <MySensor.h> #include <Wire.h> // I2C #define batteryVoltagePin A0 #define MoistureHighPin 3 #define MoistureLowPin 4 #define Moisture1ReadPin A1 #define Moisture2ReadPin A2 #define Moisture3ReadPin A3 #define BuzzerPin 5 #define LedPin 6 // MySensors Child ID's #define MOISTURE1_CHILD_ID 5 // Moisture 1 #define MOISTURE2_CHILD_ID 6 // Moisture 2 #define MOISTURE3_CHILD_ID 7 // Moisture 3 // #define MOISTURE4_CHILD_ID 8 // Moisture 4 // MySensors messages MyMessage moisturePercentageMsg1(MOISTURE1_CHILD_ID, V_HUM); // Percentage MyMessage moisturePercentageMsg2(MOISTURE2_CHILD_ID, V_HUM); // Percentage MyMessage moisturePercentageMsg3(MOISTURE3_CHILD_ID, V_HUM); // Percentage // MySensors instantiate MySensor gw(9,10); // board, 3.3v (pin default 9,10) // Reference values for ADC and Battery measurements const float VccMin = 1.0*3.5; // Minimum expected Vcc level, in Volts. Example for 1 rechargeable lithium-ion. const float VccMax = 1.0*4.2; // Maximum expected Vcc level, in Volts. float VccReference = 3.3 ; // voltage reference for measurement (=vcc) unsigned long SLEEP_TIME = 60000; // 10 sec sleep time between reads (seconds * 1000 milliseconds) // **** class for Moisture measurement ***** // attaches an analog input to a data structure for measurements // measures % of full scale voltage and scales the range of actual values // stores current/ min & max values for the sensor class MoistureSense { public: // Create an instance of MoistureSense and initialize (digital & input pin and reference values) MoistureSense(uint8_t ReadPin, int LowValue, int HighValue) ; // attach to pin and init void ReadHigh(); // Read moisture if positive void ReadLow(); // Read moisture with polarity inverted // average the low/ high readings ang get the moisture percent value uint8_t MoisturePercent(); void ResetMinMax(); // reset min & max values protected: uint8_t _ReadPin ; // Hardware Analog Pin number int _CurMoisture, _MaxMoisture, _MinMoisture, _Low, _High, _HighValue, _LowValue ; uint8_t _curState; }; // to create an instance of MoistureSense and initialize (input pin and reference values) MoistureSense::MoistureSense(uint8_t ReadPin, int LowValue, int HighValue) { // attach to pins and init _ReadPin = ReadPin; _LowValue = LowValue; _HighValue = HighValue; _CurMoisture = _MaxMoisture = _MinMoisture = NULL ; // min & max in percent } void MoistureSense::ReadHigh() // Read moisture with high polarity (in relation to Gnd) { _High = analogRead(_ReadPin); } void MoistureSense::ReadLow() // Read moisture with low polarity (in relation to Vcc) { _Low = 1024 - analogRead(_ReadPin); } void MoistureSense::ResetMinMax() // Reset min & max values { _MinMoisture = _MaxMoisture = _CurMoisture; } uint8_t MoistureSense::MoisturePercent() // average the low/ high readings ang get the moisture percent value { uint8_t reading = constrain(map((_Low + _High)/2, _LowValue, _HighValue, 0, 100),0,100); // average map to the 0-100% range _MinMoisture = min(reading, _MinMoisture); // set min and max values _MaxMoisture = max(reading, _MaxMoisture); } // Instantiate moisture sensor objects MoistureSense Moisture1(Moisture1ReadPin, 0, 1024); MoistureSense Moisture2(Moisture2ReadPin, 0, 1024); MoistureSense Moisture3(Moisture3ReadPin, 0, 1024); void setup(){ // MySensors setup (baud 115200) gw.begin(NULL, 21); // fixed node 21, (final: connected to repeater 3 (living))" // Send the sketch version information to the gateway and Controller gw.sendSketchInfo("AWI FloorMoisture 21", "1.0"); gw.present(MOISTURE1_CHILD_ID, S_HUM); // Present Moisture sensors as humidity gw.present(MOISTURE2_CHILD_ID, S_HUM); // Present Moisture sensors as humidity gw.present(MOISTURE3_CHILD_ID, S_HUM); // Present Moisture sensors as humidity Serial.print("AWI Moisture Started "); pinMode(BuzzerPin,OUTPUT); // Setup intermittent buzzer & light pinMode(LedPin,OUTPUT); } void loop(){ // Serial.println("Moisture Percentages"); ReadMoistureValues(); gw.send(moisturePercentageMsg1.set(Moisture1.MoisturePercent())); // MySensors Send (V) gw.send(moisturePercentageMsg2.set(Moisture2.MoisturePercent())); // MySensors Send (V) gw.send(moisturePercentageMsg3.set(Moisture3.MoisturePercent())); // MySensors Send (V) gw.sendBatteryLevel(batteryPercentage()); // show local alarm if moisture > 20% if ((Moisture1.MoisturePercent()>20) || (Moisture2.MoisturePercent()>20) || (Moisture3.MoisturePercent()>20) || (batteryPercentage() < 10)) { MoistureAlarm(); } gw.sleep(SLEEP_TIME); // low power for sleep time } unsigned ReadMoistureValues() // read all moisturevalues { pinMode(MoistureLowPin, OUTPUT); // first set all pins to measurement(non floating) mode pinMode(MoistureHighPin, OUTPUT); digitalWrite(MoistureLowPin, LOW); // Set polarity on voltage divider high and read the values digitalWrite(MoistureHighPin, HIGH); delayMicroseconds(100); Moisture1.ReadLow(); delayMicroseconds(100); Moisture2.ReadLow(); delayMicroseconds(100); Moisture3.ReadLow(); delayMicroseconds(100); digitalWrite(MoistureLowPin, HIGH); // reverse polarity on voltage divider and read values digitalWrite(MoistureHighPin, LOW); delayMicroseconds(100); Moisture1.ReadHigh(); delayMicroseconds(100); Moisture2.ReadHigh(); delayMicroseconds(100); Moisture3.ReadHigh(); delayMicroseconds(100); pinMode(MoistureLowPin, INPUT); // reset pins to floating, to avoid power leakage pinMode(MoistureHighPin, INPUT); Serial.print("Moist1: "); Serial.print(Moisture1.MoisturePercent()); Serial.print(" , Moist2: "); Serial.print(Moisture2.MoisturePercent()); Serial.print(" , Moist3: "); Serial.print(Moisture3.MoisturePercent()); Serial.println(); } unsigned MoistureAlarm() // If moisturelevel to high, sound & show local alarm { digitalWrite(MoistureLowPin, HIGH); digitalWrite(MoistureHighPin, HIGH); delay(100); // sound & light for 100ms, uses a lot of power, so no no need for power down digitalWrite(MoistureLowPin, LOW); digitalWrite(MoistureHighPin, LOW); } // get Battery Voltage & charge current // assumes a balanced voltage divider on Battery and uses the Vcc as reference (3.3V in this case) // Parameters: // - VccMin = minimum battery voltage // - VccMax = maximum battery voltage // - VccReference = reference voltage for ADC uint8_t batteryPercentage() { float batteryVoltage = ((float)analogRead(batteryVoltagePin)* VccReference/1024) * 2; // actual voltage is double Serial.print("Batt: "); Serial.print(batteryVoltage); Serial.print("V ; "); return(constrain(map(batteryVoltage, VccMin, VccMax, 0, 100),0,100)); // and map to the 0-100% range }
-
This is a great idea to get less erosion!
-
@AWI your sketch has 3 sensors ? do you use a special wiring or you just get through high and low ?
The sketch on soil humidity does this but with two pins to make kind of AC current, but it needs also some gypsum to protect the electrodes.
. Leaf wetness is not immersed by nature hopefully
-
@epierre It has 3 sensors with copper wiring. It switches the polarity of the voltage divider (1 Mohm in series with the "sensor") and measures the voltage over the sensor. Actualy it is a moisture alarm for a sensitive wooden floor.
and I learned something today
"Gypsum is a soft sulfate mineral composed of calcium sulfate dihydrate, with the chemical formula CaSO4·2H2O"
-
@AWI You can call it also "Plaster of Paris"
When immersed you need to protect it whatever you do : http://vanderleevineyard.com/1/category/vinduino/1.html
-
@awi going back to you above sketch, what is your wiring ?
#define MoistureHighPin 3 #define MoistureLowPin 4 #define Moisture1ReadPin A1 #define Moisture2ReadPin A2 #define Moisture3ReadPin A3
-
Hello,
I guess it is the same as Vinduino :
with their test code:
// This program tests 3 soil sensor inputs and prints bias caused by galvanic effects // Copyright (C) 2015, Reinier van der Lee // www.vanderleevineyard.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 // 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. #include <math.h> // Conversion equation from resistance to % // Setting up format for reading 3 soil sensors #define NUM_READS 10 // Number of sensor reads for filtering long buffer[NUM_READS]; int index; typedef struct { // Structure to be used in percentage and resistance values matrix to be filtered (have to be in pairs) int moisture; long resistance; } values; const long knownResistor = 1500; // Constant value of known resistor in Ohms int supplyVoltage; // Measured supply voltage int sensorVoltage; // Measured sensor voltage values valueOf[NUM_READS]; // Calculated moisture percentages and resistances to be sorted and filtered int i; // Simple index variable void setup() { // initialize serial communications at 9600 bps: Serial.begin(115200); // initialize the digital pins as an output. // Pin 6,7 is for sensor 1 pinMode(6, OUTPUT); pinMode(7, OUTPUT); } void loop() { measure(1,6,7,1); Serial.print ("\t"); Serial.println (average()); long read1 = average(); measure(1,7,6,0); Serial.print ("\t"); Serial.println (average()); long read2= average(); long sensor1 = (read1 + read2)/2; Serial.print ("resistance bias =" ); Serial.println (read1-read2); Serial.print ("sensor bias compensated value = "); Serial.println (sensor1); Serial.println (); delay (3000); } void measure (int sensor, int phase_b, int phase_a, int analog_input) { // read sensor, filter, and calculate resistance value // Noise filter: median filter for (i=0; i<NUM_READS; i++) { // Read 1 pair of voltage values digitalWrite(phase_a, HIGH); // set the voltage supply on delayMicroseconds(25); supplyVoltage = analogRead(analog_input); // read the supply voltage delayMicroseconds(25); digitalWrite(phase_a, LOW); // set the voltage supply off delay(1); digitalWrite(phase_b, HIGH); // set the voltage supply on delayMicroseconds(25); sensorVoltage = analogRead(analog_input); // read the sensor voltage delayMicroseconds(25); digitalWrite(phase_b, LOW); // set the voltage supply off // Calculate resistance // the 0.5 add-term is used to round to the nearest integer // Tip: no need to transform 0-1023 voltage value to 0-5 range, due to following fraction long resistance = (knownResistor * (supplyVoltage - sensorVoltage ) / sensorVoltage)-457 ; delay(1); addReading(resistance); Serial.print (resistance); Serial.print ("\t"); } } // Averaging algorithm void addReading(long resistance){ buffer[index] = resistance; index++; if (index >= NUM_READS) index = 0; } long average(){ long sum = 0; for (int i = 0; i < NUM_READS; i++){ sum += buffer[i]; } return (long)(sum / NUM_READS); }
and my hall of fame and shame of sensors I've tried :