|
| 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-2015 Sensnology AB |
| 10 | + * Full contributor list: https://github.com/mysensors/Arduino/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 mesuring |
| 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 | +#include <math.h> // Conversion equation from resistance to % |
| 64 | +#include <SPI.h> |
| 65 | +#include <MySensor.h> |
| 66 | + |
| 67 | +// Setting up format for reading 3 soil sensors |
| 68 | +#define NUM_READS 10 // Number of sensor reads for filtering |
| 69 | +#define CHILD_ID 0 |
| 70 | + |
| 71 | +MySensor gw; // Arduino initialization |
| 72 | +MyMessage msg(CHILD_ID, V_LEVEL); |
| 73 | +unsigned long SLEEP_TIME = 30000; // Sleep time between reads (in milliseconds) |
| 74 | + |
| 75 | +long buffer[NUM_READS]; |
| 76 | +int index; |
| 77 | + |
| 78 | +typedef struct { // Structure to be used in percentage and resistance values matrix to be filtered (have to be in pairs) |
| 79 | + int moisture; |
| 80 | + long resistance; |
| 81 | +} values; |
| 82 | + |
| 83 | +const long knownResistor = 4700; // Constant value of known resistor in Ohms |
| 84 | + |
| 85 | +int supplyVoltage; // Measured supply voltage |
| 86 | +int sensorVoltage; // Measured sensor voltage |
| 87 | + |
| 88 | +values valueOf[NUM_READS]; // Calculated moisture percentages and resistances to be sorted and filtered |
| 89 | + |
| 90 | +int i; // Simple index variable |
| 91 | + |
| 92 | +void setup() { |
| 93 | + // initialize serial communications at 9600 bps: |
| 94 | + Serial.begin(115200); |
| 95 | + gw.begin(); |
| 96 | + gw.sendSketchInfo("Soil Moisture Sensor Reverse Polarity", "1.0"); |
| 97 | + gw.present(CHILD_ID, S_HUM); |
| 98 | + // initialize the digital pins as an output. |
| 99 | + // Pin 6,7 is for sensor 1 |
| 100 | + // initialize the digital pin as an output. |
| 101 | + // Pin 6 is sense resistor voltage supply 1 |
| 102 | + pinMode(6, OUTPUT); |
| 103 | + |
| 104 | + // initialize the digital pin as an output. |
| 105 | + // Pin 7 is sense resistor voltage supply 2 |
| 106 | + pinMode(7, OUTPUT); |
| 107 | + |
| 108 | + |
| 109 | +} |
| 110 | + |
| 111 | +void loop() { |
| 112 | + |
| 113 | + measure(1,6,7,1); |
| 114 | + Serial.print ("\t"); |
| 115 | + Serial.println (average()); |
| 116 | + long read1 = average(); |
| 117 | + |
| 118 | + measure(1,7,6,0); |
| 119 | + Serial.print ("\t"); |
| 120 | + Serial.println (average()); |
| 121 | + long read2= average(); |
| 122 | + |
| 123 | + long sensor1 = (read1 + read2)/2; |
| 124 | + |
| 125 | + Serial.print ("resistance bias =" ); |
| 126 | + Serial.println (read1-read2); |
| 127 | + Serial.print ("sensor bias compensated value = "); |
| 128 | + Serial.println (sensor1); |
| 129 | + Serial.println (); |
| 130 | + |
| 131 | + //send back the values |
| 132 | + gw.send(msg.set((long int)ceil(sensor1))); |
| 133 | + // delay until next measurement (msec) |
| 134 | + gw.sleep(SLEEP_TIME); |
| 135 | +} |
| 136 | + |
| 137 | +void measure (int sensor, int phase_b, int phase_a, int analog_input) |
| 138 | +{ |
| 139 | + // read sensor, filter, and calculate resistance value |
| 140 | + // Noise filter: median filter |
| 141 | + |
| 142 | + for (i=0; i<NUM_READS; i++) { |
| 143 | + |
| 144 | + // Read 1 pair of voltage values |
| 145 | + digitalWrite(phase_a, HIGH); // set the voltage supply on |
| 146 | + delayMicroseconds(25); |
| 147 | + supplyVoltage = analogRead(analog_input); // read the supply voltage |
| 148 | + delayMicroseconds(25); |
| 149 | + digitalWrite(phase_a, LOW); // set the voltage supply off |
| 150 | + delay(1); |
| 151 | + |
| 152 | + digitalWrite(phase_b, HIGH); // set the voltage supply on |
| 153 | + delayMicroseconds(25); |
| 154 | + sensorVoltage = analogRead(analog_input); // read the sensor voltage |
| 155 | + delayMicroseconds(25); |
| 156 | + digitalWrite(phase_b, LOW); // set the voltage supply off |
| 157 | + |
| 158 | + // Calculate resistance |
| 159 | + // the 0.5 add-term is used to round to the nearest integer |
| 160 | + // Tip: no need to transform 0-1023 voltage value to 0-5 range, due to following fraction |
| 161 | + long resistance = (knownResistor * (supplyVoltage - sensorVoltage ) / sensorVoltage) ; |
| 162 | + |
| 163 | + delay(1); |
| 164 | + addReading(resistance); |
| 165 | + Serial.print (resistance); |
| 166 | + Serial.print ("\t"); |
| 167 | + } |
| 168 | +} |
| 169 | + |
| 170 | + |
| 171 | + |
| 172 | +// Averaging algorithm |
| 173 | +void addReading(long resistance){ |
| 174 | + buffer[index] = resistance; |
| 175 | + index++; |
| 176 | + if (index >= NUM_READS) index = 0; |
| 177 | +} |
| 178 | + |
| 179 | +long average(){ |
| 180 | + long sum = 0; |
| 181 | + for (int i = 0; i < NUM_READS; i++){ |
| 182 | + sum += buffer[i]; |
| 183 | + } |
| 184 | + return (long)(sum / NUM_READS); |
| 185 | +} |
0 commit comments