MySensors Library & Examples  2.3.2-36-g2e00bf6
SoilMoistSensor.ino
1 /*
2  * The MySensors Arduino library handles the wireless radio link and protocol
3  * between your home built sensors/actuators and HA controller of choice.
4  * The sensors forms a self healing radio network with optional repeaters. Each
5  * repeater and gateway builds a routing tables in EEPROM which keeps track of the
6  * network topology allowing messages to be routed to nodes.
7  *
8  * Created by Henrik Ekblad <[email protected]>
9  * Copyright (C) 2013-2020 Sensnology AB
10  * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
11  *
12  * Documentation: http://www.mysensors.org
13  * Support Forum: http://forum.mysensors.org
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * version 2 as published by the Free Software Foundation.
18  *
19  *******************************
20  *
21  * DESCRIPTION
22  *
23  * Arduino soil moisture based on gypsum sensor/resistive sensor to avoid electric catalyse in soil
24  * Required to interface the sensor: 2 * 4.7kOhm + 2 * 1N4148
25  *
26  * Gypsum sensor and calibration:
27  * DIY: See http://vanderleevineyard.com/1/category/vinduino/1.html
28  * Built: Davis / Watermark 200SS
29  * http://www.cooking-hacks.com/watermark-soil-moisture-sensor?_bksrc=item2item&_bkloc=product
30  * http://www.irrometer.com/pdf/supportmaterial/sensors/voltage-WM-chart.pdf
31  * cb (centibar) http://www.irrometer.com/basics.html
32  * 0-10 Saturated Soil. Occurs for a day or two after irrigation
33  * 10-20 Soil is adequately wet (except coarse sands which are drying out at this range)
34  * 30-60 Usual range to irrigate or water (except heavy clay soils).
35  * 60-100 Usual range to irrigate heavy clay soils
36  * 100-200 Soil is becoming dangerously dry for maximum production. Proceed with caution.
37  *
38  * Connection:
39  * D6, D7: alternative powering to avoid sensor degradation
40  * A0, A1: alternative resistance measuring
41  *
42  * Based on:
43  * "Vinduino" portable soil moisture sensor code V3.00
44  * Date December 31, 2012
45  * Reinier van der Lee and Theodore Kaskalis
46  * www.vanderleevineyard.com
47  * Contributor: epierre
48  */
49 
50 // Copyright (C) 2015, Reinier van der Lee
51 // www.vanderleevineyard.com
52 
53 // This program is free software: you can redistribute it and/or modify
54 // it under the terms of the GNU General Public License as published by
55 // the Free Software Foundation, either version 3 of the License, or
56 // any later version.
57 
58 // This program is distributed in the hope that it will be useful,
59 // but WITHOUT ANY WARRANTY; without even the implied warranty of
60 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
61 // GNU General Public License for more details.
62 
63 // Enable debug prints to serial monitor
64 #define MY_DEBUG
65 
66 // Enable and select radio type attached
67 #define MY_RADIO_RF24
68 //#define MY_RADIO_NRF5_ESB
69 //#define MY_RADIO_RFM69
70 //#define MY_RADIO_RFM95
71 //#define MY_PJON
72 
73 #include <math.h> // Conversion equation from resistance to %
74 #include <MySensors.h>
75 
76 // Setting up format for reading 3 soil sensors
77 #define NUM_READS (int)10 // Number of sensor reads for filtering
78 #define CHILD_ID 0
79 
80 MyMessage msg(CHILD_ID, V_LEVEL);
81 uint32_t SLEEP_TIME = 30000; // Sleep time between reads (in milliseconds)
82 
83 long buffer[NUM_READS];
84 int idx;
85 
87 typedef struct {
88  int moisture;
89  long resistance;
90 } values;
91 
92 const long knownResistor = 4700; // Constant value of known resistor in Ohms
93 
94 int supplyVoltage; // Measured supply voltage
95 int sensorVoltage; // Measured sensor voltage
96 
97 values valueOf[NUM_READS]; // Calculated moisture percentages and resistances to be sorted and filtered
98 
99 int i; // Simple index variable
100 
101 void setup()
102 {
103  // initialize the digital pins as an output.
104  // Pin 6,7 is for sensor 1
105  // initialize the digital pin as an output.
106  // Pin 6 is sense resistor voltage supply 1
107  pinMode(6, OUTPUT);
108 
109  // initialize the digital pin as an output.
110  // Pin 7 is sense resistor voltage supply 2
111  pinMode(7, OUTPUT);
112 }
113 
115 {
116  sendSketchInfo("Soil Moisture Sensor Reverse Polarity", "1.0");
117  present(CHILD_ID, S_MOISTURE);
118 }
119 
120 void loop()
121 {
122 
123  measure(6,7,1);
124  Serial.print ("\t");
125  Serial.println (average());
126  long read1 = average();
127 
128  measure(7,6,0);
129  Serial.print ("\t");
130  Serial.println (average());
131  long read2= average();
132 
133  long sensor1 = (read1 + read2)/2;
134 
135  Serial.print ("resistance bias =" );
136  Serial.println (read1-read2);
137  Serial.print ("sensor bias compensated value = ");
138  Serial.println (sensor1);
139  Serial.println ();
140 
141  //send back the values
142  send(msg.set((int32_t)ceil(sensor1)));
143  // delay until next measurement (msec)
144  sleep(SLEEP_TIME);
145 }
146 
147 void measure (int phase_b, int phase_a, int analog_input)
148 {
149  // read sensor, filter, and calculate resistance value
150  // Noise filter: median filter
151 
152  for (i=0; i<NUM_READS; i++) {
153 
154  // Read 1 pair of voltage values
155  digitalWrite(phase_a, HIGH); // set the voltage supply on
156  delayMicroseconds(25);
157  supplyVoltage = analogRead(analog_input); // read the supply voltage
158  delayMicroseconds(25);
159  digitalWrite(phase_a, LOW); // set the voltage supply off
160  delay(1);
161 
162  digitalWrite(phase_b, HIGH); // set the voltage supply on
163  delayMicroseconds(25);
164  sensorVoltage = analogRead(analog_input); // read the sensor voltage
165  delayMicroseconds(25);
166  digitalWrite(phase_b, LOW); // set the voltage supply off
167 
168  // Calculate resistance
169  // the 0.5 add-term is used to round to the nearest integer
170  // Tip: no need to transform 0-1023 voltage value to 0-5 range, due to following fraction
171  long resistance = (knownResistor * (supplyVoltage - sensorVoltage ) / sensorVoltage) ;
172 
173  delay(1);
174  addReading(resistance);
175  Serial.print (resistance);
176  Serial.print ("\t");
177  }
178 }
179 
180 
181 
182 // Averaging algorithm
183 void addReading(long resistance)
184 {
185  buffer[idx] = resistance;
186  idx++;
187  if (idx >= NUM_READS) {
188  idx = 0;
189  }
190 }
191 
192 long average()
193 {
194  long sum = 0;
195  for (int cnt = 0; cnt < NUM_READS; cnt++) {
196  sum += buffer[cnt];
197  }
198  return (long)(sum / NUM_READS);
199 }
HIGH
#define HIGH
Definition: bcm2835.h:572
sendSketchInfo
bool sendSketchInfo(const char *name, const char *version, const bool requestEcho=false)
loop
void loop()
Main loop.
Definition: SoilMoistSensor.ino:120
LOW
#define LOW
Definition: bcm2835.h:574
values::moisture
int moisture
Moisture.
Definition: SoilMoistSensor.ino:88
presentation
void presentation()
Node presentation.
Definition: SoilMoistSensor.ino:114
MyMessage::set
MyMessage & set(const void *payload, const size_t length)
Set entire payload.
send
bool send(MyMessage &msg, const bool requestEcho=false)
present
bool present(const uint8_t sensorId, const mysensors_sensor_t sensorType, const char *description="", const bool requestEcho=false)
setup
void setup()
Called after node initialises but before main loop.
Definition: SoilMoistSensor.ino:101
sleep
int8_t sleep(const uint32_t sleepingMS, const bool smartSleep=false)
MySensors.h
API declaration for MySensors.
MyMessage
MyMessage is used to create, manipulate, send and read MySensors messages.
Definition: MyMessage.h:289
values
Structure to be used in percentage and resistance values matrix to be filtered (have to be in pairs)
Definition: SoilMoistSensor.ino:87
values::resistance
long resistance
Resistance.
Definition: SoilMoistSensor.ino:89