One adruino four soil moisture sensors
-
Hi everybody,
I just begin with adruino and mysensors, i dont have my equipement yet (thank ebay) but i try to prepare my code.
I want to make a soil moisture sensor, the tutorial is pretty clear but after some research on the forum an im not sure about how to connect 4 soil moisture sensors.
Can anyone can tell me if my code look ok ? Im a bit a noob and not sure about my Child-id management...
Thanks in adavance !/** * The MySensors Arduino library handles the wireless radio link and protocol * between your home built sensors/actuators and HA controller of choice. * The sensors forms a self healing radio network with optional repeaters. Each * repeater and gateway builds a routing tables in EEPROM which keeps track of the * network topology allowing messages to be routed to nodes. * * Created by Henrik Ekblad <henrik.ekblad@mysensors.org> * Copyright (C) 2013-2015 Sensnology AB * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors * * Documentation: http://www.mysensors.org * Support Forum: http://forum.mysensors.org * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * ******************************* * * REVISION HISTORY * Version 1.0 - Henrik Ekblad * * DESCRIPTION * Example sketch sending soil moisture alarm to controller * http://www.mysensors.org/build/moisture */ #include <SPI.h> #include <MySensor.h> #define DIGITAL_INPUT_SOIL_SENSOR 3 // Digital input did you attach your soil sensor. #define DIGITAL_INPUT_SOIL_SENSOR1 4 // Digital input did you attach your soil sensor. #define DIGITAL_INPUT_SOIL_SENSOR2 5 // Digital input did you attach your soil sensor. #define DIGITAL_INPUT_SOIL_SENSOR3 6 // Digital input did you attach your soil sensor. #define INTERRUPT DIGITAL_INPUT_SOIL_SENSOR-2 // Usually the interrupt = pin -2 (on uno/nano anyway) #define CHILD_ID 0 // Id of the sensor child #define CHILD_ID_1 1 // moist sensor 2 #define CHILD_ID_2 2 // moist sensor 3 #define CHILD_ID_3 3 // moist sensor 4 MySensor gw; MyMessage msg(CHILD_ID, V_TRIPPED); int lastSoilValue = -1; MyMessage msg1(CHILD_ID_1, V_TRIPPED); int lastSoilValue1 = -1; MyMessage msg2(CHILD_ID_2, V_TRIPPED); int lastSoilValue2 = -1; MyMessage msg3(CHILD_ID_3, V_TRIPPED); int lastSoilValue3 = -1; void setup() { gw.begin(); // Send the sketch version information to the gateway and Controller gw.sendSketchInfo("Soil Moisture Sensor", "1.0"); // sets the soil sensor digital pin as input pinMode(DIGITAL_INPUT_SOIL_SENSOR, INPUT); pinMode(DIGITAL_INPUT_SOIL_SENSOR1, INPUT); pinMode(DIGITAL_INPUT_SOIL_SENSOR2, INPUT); pinMode(DIGITAL_INPUT_SOIL_SENSOR3, INPUT); // Register all sensors to gw (they will be created as child devices) gw.present(CHILD_ID, S_MOTION); gw.present(CHILD_ID_1, S_MOTION); gw.present(CHILD_ID_2, S_MOTION); gw.present(CHILD_ID_3, S_MOTION); } void loop() { // Read digital soil value int soilValue = digitalRead(DIGITAL_INPUT_SOIL_SENSOR); // 1 = Not triggered, 0 = In soil with water if (soilValue != lastSoilValue) { Serial.println(soilValue); gw.send(msg.set(soilValue == 0 ? 1 : 0)); // Send the inverse to gw as tripped should be when no water in soil lastSoilValue = soilValue; } int soilValue1 = digitalRead(DIGITAL_INPUT_SOIL_SENSOR1); // 1 = Not triggered, 0 = In soil with water if (soilValue1 != lastSoilValue1) { Serial.println(soilValue1); gw.send(msg.set(soilValue1 == 0 ? 1 : 0)); // Send the inverse to gw as tripped should be when no water in soil lastSoilValue1 = soilValue1; } int soilValue2 = digitalRead(DIGITAL_INPUT_SOIL_SENSOR2); // 1 = Not triggered, 0 = In soil with water if (soilValue2 != lastSoilValue2) { Serial.println(soilValue2); gw.send(msg.set(soilValue2 == 0 ? 1 : 0)); // Send the inverse to gw as tripped should be when no water in soil lastSoilValue2 = soilValue2; } int soilValue3 = digitalRead(DIGITAL_INPUT_SOIL_SENSOR3); // 1 = Not triggered, 0 = In soil with water if (soilValue3 != lastSoilValue3) { Serial.println(soilValue3); gw.send(msg.set(soilValue3 == 0 ? 1 : 0)); // Send the inverse to gw as tripped should be when no water in soil lastSoilValue3 = soilValue3; } // Power down the radio and arduino until digital input changes. gw.sleep(INTERRUPT, CHANGE); }
-
Looks good except interrupt wake from sleep won't work for all soil sensors pins used.
I'd suggest you just sleep for a few hours and read the pins. Plants usually don't require instant watering
-
@hek Oh cool ! thank you a lot for your reply, im glad that's its seems to be ok.
But im really a beginner with arduino, and i need to learn about this awake timer for modifying it, I guess i have to manipuate the variable of the function, maybe one time per hours will be enough (its for an automated growbox)
But if you have time and would like to help me with that, i would be glad and very thankfull !
-
Ok, then replace with
gw.sleep(60L*60L*1000L)
(as sleep time is in milliseconds)
-
@hek thank you a lot ! i will learn and read about it for understand it but thank you very much i will test it as soon as i receive my parts.
-
Hi everbody !
I haved modify this sketch to use analog pin and send moisture in percent every 15min.
Im not sure about my "gw.send", I think it will send the value of the soil but without the sign "%" how can I do that ?
thank very much in advance for those who will look at my code/** * The MySensors Arduino library handles the wireless radio link and protocol * between your home built sensors/actuators and HA controller of choice. * The sensors forms a self healing radio network with optional repeaters. Each * repeater and gateway builds a routing tables in EEPROM which keeps track of the * network topology allowing messages to be routed to nodes. * * Created by Henrik Ekblad <henrik.ekblad@mysensors.org> * Copyright (C) 2013-2015 Sensnology AB * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors * * Documentation: http://www.mysensors.org * Support Forum: http://forum.mysensors.org * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * ******************************* * * REVISION HISTORY * Version 1.0 - Henrik Ekblad * * DESCRIPTION * Example sketch sending soil moisture alarm to controller * http://www.mysensors.org/build/moisture */ #include <SPI.h> #include <MySensor.h> #define ANALOG_INPUT_SOIL_SENSOR A0 // Analog input did you attach your soil sensor. #define ANALOG_INPUT_SOIL_SENSOR1 A1 // Analog input did you attach your soil sensor. #define ANALOG_INPUT_SOIL_SENSOR2 A2 // Analog input did you attach your soil sensor. #define ANALOG_INPUT_SOIL_SENSOR3 A3 // Analog input did you attach your soil sensor. #define INTERRUPT DIGITAL_INPUT_SOIL_SENSOR-2 // Usually the interrupt = pin -2 (on uno/nano anyway) #define CHILD_ID 0 // Id of the sensor child #define CHILD_ID_1 1 // moist sensor 2 #define CHILD_ID_2 2 // moist sensor 3 #define CHILD_ID_3 3 // moist sensor 4 MySensor gw; MyMessage msg(CHILD_ID, V_HUM); int lastSoilValue = 0; MyMessage msg1(CHILD_ID_1, V_HUM); int lastSoilValue1 = 0; MyMessage msg2(CHILD_ID_2, V_HUM); int lastSoilValue2 = 0; MyMessage msg3(CHILD_ID_3, V_HUM); int lastSoilValue3 = 0; int soil = 0; int soil1 = 0; int soil2 = 0; int soil3 = 0; void setup() { gw.begin(); // Send the sketch version information to the gateway and Controller gw.sendSketchInfo("Soil Moisture Sensor", "1.0"); // sets the soil sensor analogique pin as input pinMode(ANALOG_INPUT_SOIL_SENSOR, INPUT); pinMode(ANALOG_INPUT_SOIL_SENSOR1, INPUT); pinMode(ANALOG_INPUT_SOIL_SENSOR2, INPUT); pinMode(ANALOG_INPUT_SOIL_SENSOR3, INPUT); // Register all sensors to gw (they will be created as child devices) gw.present(CHILD_ID, S_HUM); gw.present(CHILD_ID_1, S_HUM); gw.present(CHILD_ID_2, S_HUM); gw.present(CHILD_ID_3, S_HUM); } void loop() { // Read digital soil value int soilValue = analogRead(ANALOG_INPUT_SOIL_SENSOR); // Lecture des valeurs du capteur1 soilValue = constrain(soilValue, 485, 1023); // This is taken from an another project on internet with same type of moisture sensor, i will check this value when i receive my sensors soil = map(soilValue, 485, 1023, 100, 0); if (soil != lastSoilValue) { Serial.print("pot 1 : "); Serial.println(soil); Serial.print("%"); gw.send(msg.set(soil)); // Send in percent lastSoilValue = soil; } int soilValue1 = analogRead(ANALOG_INPUT_SOIL_SENSOR1); // Lecture des valeurs du capteur2 soilValue1 = constrain(soilValue1, 485, 1023); soil1 = map(soilValue1, 485, 1023, 100, 0); if (soil1 != lastSoilValue1) { Serial.print("pot 2 : "); Serial.println(soil1); Serial.print("%"); gw.send(msg1.set(soil1)); // Send in percent lastSoilValue1 = soil1; } int soilValue2 = analogRead(ANALOG_INPUT_SOIL_SENSOR2); // Lecture des valeurs du capteur3 soilValue2 = constrain(soilValue2, 485, 1023); soil2 = map(soilValue2, 485, 1023, 100, 0); if (soil2 != lastSoilValue2) { Serial.print("pot 3 : "); Serial.println(soil2); Serial.print("%"); gw.send(msg2.set(soil2)); // Send in percent lastSoilValue2 = soil2; } int soilValue3 = analogRead(ANALOG_INPUT_SOIL_SENSOR3); // // Lecture des valeurs du capteur4 soilValue3 = constrain(soilValue3, 485, 1023); soil3 = map(soilValue3, 485, 1023, 100, 0); if (soil3 != lastSoilValue3) { Serial.print("pot 4 : "); Serial.println(soil3); Serial.print("%"); gw.send(msg3.set(soil3)); // Send in percent lastSoilValue3 = soil3; } gw.sleep(15L*15L*1000L); // Timer for checkin every 15min }
ps: for those who want, here is the link to the project where i took the code to transform in percent the value http://arduinotronics.blogspot.fr/2014/01/when-do-i-water-my-plants-soil.html
edit
After some research i found some thread on the forum -> here talking about this moisture sensor, thank to @mfalkvidd for his code.
I copy this sketch and modify it for my use : no battery for now and add a "if" to it for checking if the value of the moisture have change since the last check (i hope it will save some battery with sending data just when needed)
I just have one more question if someone know... Can I connect all my sensors (4) to the same power pin (in parallele) ?#include <SPI.h> #include <MySensor.h> #define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5)) #define CHILD_ID_MOISTURE1 0 #define CHILD_ID_MOISTURE2 1 #define CHILD_ID_MOISTURE3 2 #define CHILD_ID_MOISTURE4 3 //#define CHILD_ID_BATTERY 1 #define SENSOR_ANALOG_PIN 0 #define SENSOR_ANALOG_PIN1 1 #define SENSOR_ANALOG_PIN2 2 #define SENSOR_ANALOG_PIN3 3 #define SENSOR_POWER_PIN 8 #define SLEEP_TIME 600000 // Sleep time between reads (in milliseconds) (=10 MINUTES) #define STABILIZATION_TIME 500 // Let the sensor stabilize before reading //#define BATTERY_FULL 3700 // 3,700 millivolts //#define BATTERY_ZERO 1700 // 1,700 millivolts MySensor gw; MyMessage msg(CHILD_ID_MOISTURE1, V_HUM); MyMessage msg2(CHILD_ID_MOISTURE2, V_HUM); MyMessage msg3(CHILD_ID_MOISTURE3, V_HUM); MyMessage msg4(CHILD_ID_MOISTURE4, V_HUM); //MyMessage voltage_msg(CHILD_ID_BATTERY, V_VOLTAGE); int lastsoilValue1 = 0; int lastsoilValue2 = 0; int lastsoilValue3 = 0; int lastsoilValue4 = 0; void setup() { pinMode(SENSOR_POWER_PIN, OUTPUT); gw.begin(); gw.sendSketchInfo("Plant moisture w bat", "1.1"); gw.present(CHILD_ID_MOISTURE1, S_HUM); gw.present(CHILD_ID_MOISTURE2, S_HUM); gw.present(CHILD_ID_MOISTURE3, S_HUM); gw.present(CHILD_ID_MOISTURE4, S_HUM); //delay(250); //gw.present(CHILD_ID_BATTERY, S_CUSTOM); } void loop() { digitalWrite(SENSOR_POWER_PIN, HIGH); // Power on the sensors gw.sleep(STABILIZATION_TIME); //stabilization before mesuring int moistureLevel = (1023 - analogRead(SENSOR_ANALOG_PIN)) / 10.23; // read moisture of the first sensor if (moistureLevel != lastsoilValue1) { //test if moisture is different than before gw.send(msg.set(moistureLevel)); //send to controller moisture level of sensor 1 lastsoilValue1 = moistureLevel; } int moistureLevel1 = (1023 - analogRead(SENSOR_ANALOG_PIN1)) / 10.23; // read moisture of the second sensor if (moistureLevel1 != lastsoilValue2) { //test if moisture is different than before gw.send(msg2.set(moistureLevel1)); //send to controller moisture level of sensor 2 lastsoilValue2 = moistureLevel1; } int moistureLevel2 = (1023 - analogRead(SENSOR_ANALOG_PIN2)) / 10.23; // read moisture of the third sensor if (moistureLevel2 != lastsoilValue3) { //test if moisture is different than before gw.send(msg3.set(moistureLevel2)); //send to controller moisture level of sensor 3 lastsoilValue3 = moistureLevel2; } int moistureLevel3 = (1023 - analogRead(SENSOR_ANALOG_PIN3)) / 10.23; // read moisture of fourth sensor if (moistureLevel3 != lastsoilValue4) { //test if moisture is different than before gw.send(msg4.set(moistureLevel3)); //send to controller moisture level of sensor 4 lastsoilValue3 = moistureLevel3; } //debugging comment it when dont use Serial.print("first plant :"); Serial.println(moistureLevel); Serial.print("second plant :"); Serial.println(moistureLevel1); Serial.print("third plant :"); Serial.println(moistureLevel2); Serial.print("fourth plant :"); Serial.println(moistureLevel3); digitalWrite(SENSOR_POWER_PIN, LOW); //spower off sensors //long voltage = readVcc(); //gw.send(voltage_msg.set(voltage / 1000.0, 3)); // redVcc returns millivolts and set wants volts and how many decimals (3 in our case) //gw.sendBatteryLevel(round((voltage - BATTERY_ZERO) * 100.0 / (BATTERY_FULL - BATTERY_ZERO))); gw.sleep(SLEEP_TIME); } /*long readVcc() { // From http://provideyourown.com/2012/secret-arduino-voltmeter-measure-battery-voltage/ // Read 1.1V reference against AVcc // set the reference to Vcc and the measurement to the internal 1.1V reference #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) ADMUX = _BV(MUX5) | _BV(MUX0); #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) ADMUX = _BV(MUX3) | _BV(MUX2); #else ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); #endif delay(2); // Wait for Vref to settle ADCSRA |= _BV(ADSC); // Start conversion while (bit_is_set(ADCSRA, ADSC)); // measuring uint8_t low = ADCL; // must read ADCL first - it then locks ADCH uint8_t high = ADCH; // unlocks both long result = (high << 8) | low; result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000 return result; // Vcc in millivolts }*/```
-
Hi
I am just in the beginning to build one soil moisture sensor battery powered.Any update from your test?
-
@damien
Is there an update for this sketch to use in V2?