💬 Soil Moisture Sensor

  • Admin

    This thread contains comments for the article "Soil Moisture Sensor" posted on MySensors.org.

  • There is something in the sketch I do not understand

     * Connection:
     * D6, D7: alternative powering to avoid sensor degradation
     * A0, A1: alternative resistance mesuring
    void setup() {
      // initialize the digital pins as an output.
      // Pin 6,7 is for sensor 1
      // initialize the digital pin as an output.
      // Pin 6 is sense resistor voltage supply 1
      pinMode(6, OUTPUT);    
      // initialize the digital pin as an output.
      // Pin 7 is sense resistor voltage supply 2
     pinMode(7, OUTPUT);    

    What is this for?

  • Hardware Contributor

    I think the code is written for a self made sensor and the pictures show a binary sensor...

  • Mod

    @Martin-Tellblom the pins on the sensor can corrode by electrolysis. By alternating polarity, corrosion might be prevented (I am not sure that it makes a difference in practice though).

    Some discussion on the topic is available in https://forum.mysensors.org/topic/2147/office-plant-monitoring/ (very long thread with lots of information)

    As @FotoFieber points out, the alternating polarity is for a different sensor than the one shown in the wiring guide. We should decide which version to use and stick to one version in the example. I'm not sure which one we should use though.

  • Is there any updated sketch to use with the Soil Moisture Sensor shown in the pictures?

  • Plugin Developer

    The moisture sensor should be presented as S_MOISTURE not S_HUM.

  • Dous this sketch belong to this sensor ? pin 6,7 and a1 or a0 are not connected.....

  • Yeah. It would be great if someone can tell us about the hardware and wiring used in this sketch.

  • Henrik
    Yes could you please confirm how the nano is connected to the sensors ,soil sensors please ,yes 5+ 0- pin 3 ?? or in your sketch pin 6 7 ? to were
    or a0 a1 please how?? pin 6 to pin 3 on nano ?? it just not clear ??

  • Plugin Developer

    For some people it might be worthwhile to look at the Mi Flora sensor, a pretty awesome $10 bluetooth sensor that measures moisture, soilhealth, light and temperature, and lasts a year on one coin cell battery. Its protocol has been reverse engineered, and now a lot of scripts offer all kinds of integrations, including connecting it to MQTT servers or Domoticz.



  • Hero Member

    @alowhum Thanks for the info. I have one of these and I would like to somehow integrate it with my other sensors. Maybe it would be possible to build a MySensors Bluetooth GW node to connect to the Mi Flora.

  • For those who are using the analogue soil moisture sensor in combination with a nano

    Connect the output of the sensor to the A0 of the nano
    connect the gnd of the sensor to the gnd on the nano
    connect th vcc of the sensor to 3v3 on the nano

    the sketch that works for me:
    // Enable debug prints to serial monitor
    #define MY_DEBUG

    // Enable and select radio type attached
    #define MY_RADIO_NRF24
    #define CHILD_ID 0

    #include <MySensors.h>
    // Here we are setting up some water thresholds that we will
    // use later. Note that you will need to change these to match
    // your soil type and environment. It doesn't do much for me because I'm using domoticz
    int thresholdUp = 400;
    int thresholdDown = 075;
    MyMessage msg(CHILD_ID, V_LEVEL);
    unsigned long SLEEP_TIME = 30000;

    // We are setting up the pin A0 on the redboard to be our sensor
    // pin input:
    int sensorPin = A0;

    void presentation()
    present(CHILD_ID, S_MOISTURE);

    void loop()
    int sensorValue;
    sensorValue = analogRead(sensorPin);

    //send back the values
    // delay until next measurement (msec)

  • My two cents. A soil moisture sensor that requires no extra hardware (not counting electric wire). Highly inspired by everything I've read in this thread. Comments welcome.
    Excuse the long post.

     Name:		MYS_MoistureSensor.ino
     Created:	5/25/2017 1:04:35 PM
     Author:	Rob
     Soil moisture measuring by using stainless steel rods (or any other conductor).
     Probably the simplest project ever, since only a MySensors-node and some wire is needed to set things up.
     The sketch alternates current during measuring to prevent corrosion of the rods due to electrolyses.
     Odd readings may occur when starting (eg. increasing soil moisture for no apparent reason), please just allow the electrodes to settle down in the soil.
     No extra hardware needed. 
     I use an Arduino Mini 3V3, powered on two AA cells. It is suggested you set the fuses for a lower Brown Out Detection (BOD). But anything goes.
     Just tie D4 and A0 together to one rod, and D5 and A1 to another rod. This is sensor one.
     For the second sensor tie D6 and A2 together to one rod, and D7 and A3 to another rod.
     Connect a pushbutton between GND and D3 if you need a button that makes the node report immediately (can be omitted)
     Measurement are taken every minute and send to the gateway if different from the previous reading.
     In case of no changes, the node reports itself every four hours.
     The output is between 0 (dry) and 100 (wet).
     Can also be used as a depth moisture sensor with three sensor zones; in that case use one (common) long rod and three smaller sensors along
     the height of the rod and configure the sketch accordingly.
    	 sensors[0] = { 4, A0, 5, A1, -1, false };
    	 sensors[1] = { 4, A0, 6, A2, -1, false };
    	 sensors[2] = { 4, A0, 7, A3, -1, false };
    #include "Header.h"
    // Enable debug Serial.prints to serial monitor
    //#define MY_DEBUG 
    #if defined MY_DEBUG
    #define Sprintln(a) (Serial.println(a))
    #define Sprint(a) (Serial.print(a))
    #define Sprintln(a)
    #define Sprint(a)
    // Enable and select radio type attached
    #define MY_RADIO_RFM69
    #define MY_RFM69_FREQUENCY RF69_868MHZ
    #define MY_IS_RFM69HW
    // Use PA_LOW for RF24+PA (Power Amplifier)
    //#define MY_RF24_PA_LEVEL RF24_PA_LOW
    //#define MY_RF24_PA_LEVEL RF24_PA_MAX
    #define MY_NODE_ID 4
    #include <MySensors.h>
    #define ACK 0        // = false
    #define CHILD_ID 1
    #define REPORTNOWSWITCH_PIN 3    // Arduino Digital I/O pin for button/reed switch (must be an interrupt pin!)
    #define SENSOR1_ROD1_DIGITAL 4
    #define SENSOR1_ROD1_ANALOG A0
    #define SENSOR1_ROD2_DIGITAL 5
    #define SENSOR1_ROD2_ANALOG A1
    #define SENSOR2_ROD1_DIGITAL 6
    #define SENSOR2_ROD1_ANALOG A2
    #define SENSOR2_ROD2_DIGITAL 7
    #define SENSOR2_ROD2_ANALOG A3
    #define SLEEP_IN_MS 60000		// every minute a new measurement
    #define EVERY_15_MINUTES (3600000/4/SLEEP_IN_MS)
    #define EVERY_4_HOURS (3600000*4/SLEEP_IN_MS) 
    #define NUM_READS (int)10		// Number of sensor reads for filtering
    int countLoops;
    int8_t interruptedBy = -1;
    int oldBatLevel;
    float oldTemperature;
    int output_value;
    /// Included in Header.h:
    //typedef struct {
    //	int digital_input_a;
    //	int analog_input_a;
    //	int digital_input_b;
    //	int analog_input_b;
    //	int level;
    //	bool connected;
    //} sensorWiring;
    sensorWiring sensors[NUM_MOISTURE_SENSORS];
    MyMessage msgMoistureSensor(CHILD_ID, V_LEVEL);
    MyMessage msgChipTemp(CHILD_ID_TEMPERATURE, V_TEMP);
    void before()
    	// All buttons as input-pullup as per ATMEGA recommendation to use less power (and more safety) 
    	// (http://electronics.stackexchange.com/questions/43460/how-should-unused-i-o-pins-be-configured-on-atmega328p-for-lowest-power-consumpt)
    	for (int i = 1; i <= 8; i++)
    		pinMode(i, INPUT_PULLUP);
    	// Now explicity set pins as needed
    	// Setup report-now switch, activate internal pull-up
    	// Initialize sensor variables
    	// Connect Digital pin 4 to Analog input A0 and a metal rod
    	// Connect Digital pin 5 to Analog input A1 and another metal rod.
    	// Connect Digital pin 6 to Analog input A2 and a metal rod
    	// Connect Digital pin 7 to Analog input A3 and another metal rod.
    	for  (int i = 0; i<NUM_MOISTURE_SENSORS; i++)
    		sensors[i].connected = testSensorConnections(sensors[i]);
    void setup()
    void presentation() {
    	sendSketchInfo("Moisture Sensor", "1.1", ACK);
    	for (int i = 0; i < NUM_MOISTURE_SENSORS; i++)
    		if (sensors[i].connected) present(CHILD_ID+i, S_MOISTURE, ACK);
    void loop()
    	bool reportNow = (interruptedBy == digitalPinToInterrupt(REPORTNOWSWITCH_PIN));
    	if (reportNow)
    		// Little trick for debouncing the switch
    		attachInterrupt(digitalPinToInterrupt(REPORTNOWSWITCH_PIN), debounce, RISING);
    		Sprintln(F("Report now switch pressed"));
    		countLoops = 0;
    	for (int i = 0; i < NUM_MOISTURE_SENSORS; i++)
    		if (sensors[i].connected)
    			output_value = measure(sensors[i]);
    			if ((sensors[i].level != output_value) || reportNow)
    				sensors[i].level = output_value;
    				send(msgMoistureSensor.setSensor(CHILD_ID+i).set(output_value), ACK);
    	// Every fifteen minutes; poll temperature
    	if (countLoops%EVERY_15_MINUTES==0 || reportNow) 
    		float newTemp = readTemp();
    		if (oldTemperature != newTemp || reportNow)
    			send(msgChipTemp.set(newTemp, 1), ACK);
    			oldTemperature = newTemp;
    		int batLevel = getBatteryLevel();
    		if ((oldBatLevel != batLevel) || reportNow) // ...but only when changed, or when button is pressed; 
    			sendBatteryLevel(batLevel, ACK);
    			oldBatLevel = batLevel;
    	// So you know I'm alive
    	if (countLoops == EVERY_4_HOURS)
    		countLoops = 0;
    	interruptedBy = sleep(digitalPinToInterrupt(REPORTNOWSWITCH_PIN), FALLING, SLEEP_IN_MS);
    // Connect Digital pin 'digital_input_a' to Analog input 'analog_input_a' and a metal rod,
    // do the same for b
    long measure(sensorWiring sensor)
    	long total = 0;
    	int reading_a = 0;
    	int reading_b = 0;
    	for (int i = 0; i<NUM_READS; i++) {
    		// Left to right
    		reading_a = measureOneDirection(sensor.digital_input_a, sensor.digital_input_b, sensor.analog_input_a);
    		// Right to left
    		reading_b = measureOneDirection(sensor.digital_input_b, sensor.digital_input_a, sensor.analog_input_b);
    		total += reading_a + reading_b;
    	return map(total / (2 * NUM_READS), 1023, 0, 0, 100);
    long measureOneDirection(int digital_input_1, int digital_input_2, int analog_input_1)
    	pinMode(digital_input_2, OUTPUT);
    	digitalWrite(digital_input_2, LOW);
    	pinMode(digital_input_1, INPUT_PULLUP);
    	long reading = analogRead(analog_input_1);
    	pinMode(digital_input_1, INPUT);     // High impedance                 
    	pinMode(digital_input_2, INPUT);     // High impedance                 
    	Sprint(F("measureOneDirection - Reading "));
    	return reading;
    // test the connections of both rods of a sensor
    boolean testSensorConnections(sensorWiring moistureSensor)
    	return (testSensorConnection(moistureSensor.digital_input_a, moistureSensor.analog_input_a) && testSensorConnection(moistureSensor.digital_input_b, moistureSensor.analog_input_b));
    //  test if digital pin is connected to correct analog pin
    boolean testSensorConnection(int digital_input, int analog_input)
    	pinMode(digital_input, OUTPUT);
    	digitalWrite(digital_input, HIGH);                        
    	long reading_1 = analogRead(analog_input);   
    	digitalWrite(digital_input, LOW);                      
    	long reading_2 = analogRead(analog_input);   
    	pinMode(digital_input, INPUT);     // High impedance                 
    	Sprint(F("testSensorConnection - Reading1 "));
    	Sprint(F("testSensorConnection - Reading2 "));
    	bool correct = ((reading_1 == 1023) && (reading_2 == 0));
    	return correct;
    float readTemp() 
    #if defined (xxMY_RADIO_RFM69) && !defined(MY_RFM69_NEW_DRIVER)
    	return _radio.readTemperature(-3);
    	// Read 1.1V reference against MUX3  
    	return (readMUX(_BV(REFS1) | _BV(REFS0) | _BV(MUX3)) - 125) * 0.1075f;
    long readMUX(uint8_t aControl) 
    	long result;
    	ADMUX = aControl;
    	delay(20); // Wait for Vref to settle
    	// start the conversion
    	ADCSRA |= _BV(ADSC) | _BV(ADIE);
    	set_sleep_mode(SLEEP_MODE_ADC);    // sleep during sample
    	// reading should be done, but better make sure
    	// maybe the timer interrupt fired 
    	while (bit_is_set(ADCSRA, ADSC));
    	// Reading register "ADCW" takes care of how to read ADCL and ADCH.
    	result = ADCW;
    	return result;
    // Battery measure
    int getBatteryLevel()
    	int results = (readVcc() - 2000) / 10;
    	if (results > 100)
    		results = 100;
    	if (results < 0)
    		results = 0;
    	return results;
    } // end of getBandgap
    // when ADC completed, take an interrupt 
    long readVcc() {
    	long result;
    	// Read 1.1V reference against AVcc
    	result = readMUX(_BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1));
    	result = 1126400L / result; // Back-calculate AVcc in mV (1024 steps times 1100 mV (1.1V) = 1126400L)
    	return result;
    // Utter nonsense, but needed for attaching an interrupt to...
    void debounce() {

  • The greatest problem with these sensors is electrolysis and subsequent oxidation, due to the DC current flowing through the sensor in a humid environment.
    There are some solutions: Most of the circuits that supposedly feed the sensor with A are bogus as it is apulsed DC at best..
    One could try a capacitive sensor...... in theory very good but in practice plagued by issues.

    What I have done is to remove constant current from the sensor by feeding it from a transistor that I can switch on and off. I take a measurement every 2-6 hrs and switch the current off in between. Makes a huge difference

  • Next logic step is flipping polarity like here: http://gardenbot.org/howTo/soilMoisture/

  • @rollercontainer That is definitely a good solution too, but I think gardenbot approaches it a bit too complicated from the software side when he points out that you get two readings with different values that 'need to be smoothed'

    I'd say do this:
    Both pins LOW when you are not taking a reading. That restperiod can be hours.
    When you are ready to take a reading:
    make one pin HIGH, take a reading and discard that one
    Flip the voltage, take another reading (to balance the time) and use that one
    Both pins LOW again

  • @Ed1500 This is exactly what I've done with the sketch I posted earlier in this thread.
    Use two inputs per sensor. Flip polarity for every reading and then rest in a high impedance state so as not to corrode the measuring rods (just some copper wire in my case). This has the added benefit of using the least power.
    Has been working like a charm for a couple of months now. Still planning to make a couple extra for the garden.

  • @RobKuipers sensible, good sketch. Truthfully, with just the very short reading alone (I do say a milisecond or less per 4 hours), the sensor hardly corrodes. I have two galvanized nails that I have in the soil for 4 seasons. Yes, not silky smooth anymore but really no trace of electrolysis, even one made from a clotheshanger that still is doing well

  • Did this sketch / wiring / sensor work for anyone? I read that more than I had questions about the pin 6 and 7 but those pins aren't connected in the wiring diagram. If anyone have any ideas on what to change to get it working it would be great to know!

  • The sketch does not correspond to the sensor shown in the images. It is much better to use the 2-pin sensors and drive them directly using digital outputs. Search for FC28 (better) or YL-69 in ebay or amazon. I use a voltage divider with a 10k resistor

    I've been using the alternating polarity approach on about 20 sensors, with perfect results and no signs of corrosion after around 6 months. I run some tests to determine the effect of measuring time and finally came up with 5ms with no averaging. The batteries last for months; I'm not sure how many since I haven't yet had to replace any (status led removed from 3.3v arduino mini pro board).

    As a reference, I tested a rain sensor (same principle) with no alternating current and as soon as a drop of water touched the tracks, small bubbles were produced with indicated that electrolysis was taking place. The effect could be seen on the tracks after just a couple of minutes.

    I'm attaching my sketch below. It reports battery level in addition to moisture. It uses the development branch of the mysensors library in order to use the new version of the rfm69 drivers with RSSI ATC - which btw works more than perfect.

    I'm using Domoticz which includes a predefined device for moisture. This device uses the centibar scale, so I calibrated my sensors in % moisture and then convert to cb.

    #define MY_RADIO_RFM69
    #define MY_RFM69_NEW_DRIVER   // ATC on RFM69 works only with the new driver (not compatible with old=default driver)
    #define MY_IS_RFM69HW
    #define MY_RFM69_FREQUENCY RFM69_868MHZ
    #define MY_RFM69_ATC_TARGET_RSSI_DBM (-70)
    #define MY_RFM69_NETWORKID  100
    #define MY_PARENT_NODE_ID 0
    #define MY_DEBUG 
    #include <MySensors.h>
    #include <SPI.h>
    #include <Vcc.h>
    #include <Streaming.h>
    #include <math.h>
    #define VERSION "1.1"
    /* Measurement probe connected to pins shown below
    I avoided using pins 2 and 3 because they are reserved for IRQ (potential future use) - 2 is also used by the RFM69 module.
    Although this may not actually have a noticeable effect, I also avoided 5 and 6 because they support PWM and hence are a bit slower.
    #define PIN_ALIM1 4                                   // Connect to input of resistor
    #define PIN_ALIM2 7                                   // Connect to input of measuring probe
    #define PIN_LECTURA A0
    #define AGUA_DIR 780.0
    #define AGUA_INV 160.0
    #define AIRE_DIR 0.0
    #define AIRE_INV 1023.0
    #define TIEMPO_LECTURA 5
    #define SLEEP_TIME_1h 3132000 // 1 h = 1*60*60000 = 3600000 ms -13% = 3132000 ms(my arduinos show a delay of 8s/min = 13%)
    #define SLEEP_TIME_2h 6264000 // 2 h = 2*60*60000 = 7200000 ms -13% = 6264000 ms
    #define SLEEP_TIME_3h 9396000 // 3 h = 3*60*60000 = 10800000 ms -13% = 9396000 ms
    // Battery calibration (Li-ion)
    const float VccMin   = 3.0;                         // Minimum expected Vcc level, in Volts.
    const float VccMax   = 4.2;                         // Maximum expected Vcc level, in Volts.
    const float VccCorrection = 3.82/3.74;              // Measured Vcc by multimeter divided by reported Vcc
    #define CHILD_MOIST_ID 1
    MyMessage msgmoist(CHILD_MOIST_ID, V_LEVEL);
    Vcc vcc(VccCorrection);
    float oldresultcb=0;
    int oldbat=0, count=0;
    void presentation(){
      sendSketchInfo("Sensor de humedad", VERSION);
      present(CHILD_MOIST_ID, S_MOISTURE, "Humedad suelo");
      pinMode(PIN_LECTURA, INPUT);
      pinMode(PIN_ALIM1, OUTPUT);
      pinMode(PIN_ALIM2, OUTPUT);
    void loop()
      unsigned int value1, value2;
      float result1, result2, resultp, resultcb;
    //Measurement of moisture
      digitalWrite(PIN_ALIM1, HIGH);
      digitalWrite(PIN_ALIM2, LOW);
      result1=constrain(value1/(AGUA_DIR-AIRE_DIR)*100.0, 1, 100);
      digitalWrite(PIN_ALIM1, LOW);
      digitalWrite(PIN_ALIM2, HIGH);
      digitalWrite(PIN_ALIM1, LOW);
      digitalWrite(PIN_ALIM2, LOW);
    /*Conversion from % moisture to cb taken from http://lieth.ucdavis.edu/Research/tens/98/SmtPub.htm
    Another option https://www.researchgate.net/figure/260321179_fig1_Fig-1-Relation-curve-between-water-tension-cb-and-soil-moisture-percentage
    The scale used in Domoticz is explained here http://www.irrometer.com/basics.html and can be checked in file domoticz/main/RFXNames.cpp
      0-10 Saturated Soil. Occurs for a day or two after irrigation 
      10-20 Soil is adequately wet (except coarse sands which are drying out at this range) 
      20-60 Usual range to irrigate or water (most soils except heavy clay soils). 
      60-100 Usual range to irrigate heavy clay soils 
      100-200 Soil is becoming dangerously dry
      resultcb=constrain(square((-2.96699+351.395/resultp)),0,200);                           //Equation fit using stat software
    //Send the data
      if ((oldresultcb!=resultcb) || (count==4)) send(msgmoist.set((unsigned int)resultcb));
    //Measure battery voltage here since it has been under change recently (more reliable)
      float v = vcc.Read_Volts();  
      int p = vcc.Read_Perc(VccMin, VccMax);
      if ((p!=oldbat) || (count==4)) sendBatteryLevel(p);
    //Save the last values and reset the counter
      if (count==4) count=0;
    #ifdef MY_DEBUG
      Serial << "Value1=" << value1 << " " << result1 << endl << "Value2=" << value2 << " " << result2 << endl << "Result = " << resultp << "% (" << resultcb << "cb)" << endl;
      Serial << "VCC = " << v << " Volts" << endl << "VCC% = " << p << " %" << endl;
      sleep(SLEEP_TIME_2h, true);  

    And this is how it looks in Domoticz:

    alt text

    I hope this helps.

  • @manutremo sensors ordered and I'm looking forward to try it! Just a quick question; where did you connect the resistor? Thanks,


  • @peternilsson75 With the sketch I posted back in May, you just need two pieces of conductive wire. No resistor or amplifier needed. 🙂

  • Hey @RobKuipers I am trying to reuse your sketch as a water leakage sensor, but I got stopped at the Header.h file. Can you please share its content?

    I am also considering using two pieces of wire (on a ribbon strip though, just to peal isolation at strategic places).
    I will use it on battery and I was thinking on measuring every minute or so, and send a heartbeat every half hour/hour with battery status.
    Do you have any other tips about converting the sketch to water leak?
    Thanks for the sketch btw!

  • @dakipro the content of header.h is

    typedef struct {
    int digital_input_a;
    int analog_input_a;
    int digital_input_b;
    int analog_input_b;
    int level;
    bool connected;
    } sensorWiring;

    Detecting water leakage I would do exactly as you suggested: if you mean eg. to detect a leaking washing machine, it could be monitored by laying the stripped wires parallel on the bottom of a container or tray and put the machine on top of it.
    It should be easy to modify or extend the sketch to implement a binary switch to indicate leakage above a certain moisture threshold.

    Good luck. Please let us know about your progress.

  • Thanks @RobKuipers , it compiles fine now. I will work on finetuning the code, just to confirm, you attach one wire to the both D4 and A0, and second to D5 and A1 ?

    I will test with a variation of this ribbon wire https://ae01.alicdn.com/kf/HTB1admbHVXXXXcfXVXXq6xXFXXXb/NEW-font-b-laptop-b-font-Switch-touchpad-font-b-cable-b-font-1-0mm-pitch.jpg
    Just to expose the wire every few cm with a dremel/polisher, and stick the wire to the floor under the appliance somehow (double tape).

    (for start I will put it under dryer actually, because baby sometimes removes the rubber sealing and it starts leaking)

    But I am now being concerned about the corrosion, as it is very thin wire... If it doesn't work long, I will replace it with something more robust and corrosion resistant.

  • @dakipro Good to hear you have it up and running. You are correct about the connections.
    Any wire will do, they just have to be close to each other. Enough to bridge the leaking water. As soon as both wires touch the same puddle you will get readings way above zero.
    The sketch can do multiple detectors with just one Arduino; so you could could create separate alarms for both the washer and the dryer 🙂

  • Plugin Developer

    Has anyone had a look at the "Chirp" sensor? It's a great little open hardware project that can be bought on Aliexpress for $4 - $6.

    alt text

    • It monitors the waterlevel and light level.
    • When soil moisture is low, it will chirp to let you know it needs water.
    • It can be read out via i2c!

  • Mod

    @alowhum yes, the chirp sensor has been discussed a few times.

  • Here is the water leakage sensor I was mentioning few posts above, using thin ribbon cable as a sensor.
    Time will tell if it is usable at all before it corrodes completely.
    Thanks @RobKuipers for the code, works like a charm!

  • This is a really simple question but I'm new to the whole thing. How would I use the water level sensor which is shown in the shopping guide? I understand that it's analog but I'm not completely sure how I'd write the sketch. Thanks!

  • Just to summarize since the thread is becoming a bit confusing.

    The sensor shown in the example and the shopping guide is no more than a device that measures the resistance between the two pins of the fork. That is done by the boards, which includes an analog output and a digital output.

    Should you just need to know when moisture is over or below a certain degree, just connect the digital output to a digital pin in the Arduino. Then use the potentiometer in the board to decide the switching point. In a battery powered node, this could be connected to an interrupt pin so the node sleeps and is only waken up when the moisture falls under the predetermined level to send an alert to the controller. But if you want to know track how moisture evolves, you may connect the analog output of the board to an analog pin in the arduino, which will provide a numerical value. Then the sensor needs to be calibrated; there are several forms but one involves measuring the output when the fork is submerged in water (which would be 100% moisture) and then when it's in air (that would be 0%). You can then map this scale to a moisture scale, typically a cb scale.

    The negative side of using that board is that the current always flows in the same direction through the fork. The same occurs with another similar type of sensor like the sparkfun here. This will lead in some time to corrosion of the fork, even if it's one of the latest nickeled ones. Reports in the internet vary from weeks to months, but in any case the form will corrode and as a result the measurement will drift slowly.

    The alternating polarization strategy tries to overcome this problem. To do so, the board is removed and only the fork is used. Instead of connecting it to Vcc and GND, the two terminals are connected so that the fork is actually one of the resistors in a voltage divider. The other resistor is usually a 10k resistor. In this setup, one of the digital pins is connected to one leg of the resistor, the other resistor leg is connected to one side of the fork, and the other side of the fork is connected to the other digital pin on the Arduino. Another wire needs then to be connected between the connection between the resistor and the fork, to an analog pin of the Arduino, which will read a value that will be proportional to the resistance of the fork, therefore to the moisture level. Then, by switching the pins from INPUT to OUTPUT, and from HIGH to LOW, you can have the current flow in one direction or the opposite one, which significantly delays the corrosion. In my case, the forks still look like new after months of use. Corrosion speed will still obviously depend by time between readings, reading time, soil type and other factors. I've never experimented with this sensor but with a rain sensor I could see corrosion symptoms after some minutes of continuous readings. This sensor also needs to be calibrated in a similar way as the former one. This setup makes the sketch a bit more complex but there are multiple examples here and in the internet.

    There are also variations on the measurement strategy within this approach. For example, you may just take a reading in one direction, another reading in the other direction, convert them to moisture level, and average them. Other people take several readings and average them all. I realized that if the reading is repeated, the value increases with each reading until it stabilizes at a certain value, so I decided to have the sketch iterate until two consecutive readings get the same result. The measuring time also needs to be asessed; in my investigation, the shorter the time, the less battery consumption, but at some point around 5ms the readings started to be unreliable. On the other hand, the longer the measurement the more realiable, but the span of the measurements in analog pin where closer and closer which led to loss of accuracy, and of course higher battery consumption. I decided 10ms was a good balance but others' milage may vary.

    Finally, there are other completely types of moisture sensor that measure the soil dielectric constant instead of its resistance. They are said to be more reliable, and additionally they do not suffer from corrosion since they do not need to be conductive, hence they are covered by a layer of non-metal material (probably epoxy?). This makes them more durable but also more expensive. I have no experience with those.

    I hope this contributes to clarify this topic a little bit. This thread contains additional information on the same topic.

  • I guess I'm not the only one seeking for the correct diagram. It can be found here: http://vanderleevineyard.com/1/post/2012/08/-the-vinduino-project-3-make-a-low-cost-soil-moisture-sensor-reader.html
    alt text

  • Now that I managed to get my grips on Fritzing, I thought I could share a quick diagram of my own device which I tried to describe above.

    alt text

    Note that the capacitor between the middle point of the voltage divider and GND is just recommended, and its value is orientative.

    Not showing battery, radio, reset button, etc., just the soil moisture sensor part.

    I've seen other versions using transistors to switch the sensor current, and other variations; I think this is the simplest version of an alternating current sensor and it works very well.

  • @manutremo You may want to put a jumper in on the top power bus that you connect the 100nf capacitor to. It is not clear, at least to me, if that is to VCC or GND. On a true breadboard you would have to do that.

  • @dbemowsk the convention in these breadboards is that the blue rail is Gnd. You may either connect the two sides or use a Mb102 module to feed both sides at the same time. You may also choose other options.

    The capture is not showing the power feed part since it's clear enough and because what it is mainly trying to describe is the moisture measurement part which is the part seemingly causing confusion and the origin of the thread.

  • @manutremo said in 💬 Soil Moisture Sensor:

    @dbemowsk the convention in these breadboards is that the blue rail is Gnd.

    I get that, but if someone were to build that as you have diagrammed with a standard breadboard, it would not work.

    @manutremo said in 💬 Soil Moisture Sensor:

    You may either connect the two sides or use a Mb102 module to feed both sides at the same time. You may also choose other options.

    You, me and other people in here may understand that, but a newbie most likely wouldn't. When I made the comment, I was assuming that that is what you meant, but had to be sure for the newbies.

  • My posting clearly states:

    the capacitor between the middle point of the voltage divider and GND

    @dbemowsk said in 💬 Soil Moisture Sensor:
    It is not clear, at least to me, if that is to VCC or GND.

    There's only one cap in the diagram so it should be quite clear.

    if someone were to build that as you have diagrammed with a standard breadboard, it would not work.

    I tend to think it wouldn't work with the jumper either if built as diagrammed, since the power source would still be missing.

    Don't you think that jumper could possibly lead newbies to confusion into thinking that the power supply needs to be done in a certain way? Or would it be better to avoid overloading the diagram with information irrelevant to the concept being illustrated and just focus on the important part? Certainly a personal decision. I might be wrong but I chose "less is more".

    Even newbies getting into electronics understand that diagrams may not always show all the components specially when they are focused and intended to illustrate a specific part of the circuit. even newbies into electronics understand that a power source is always necessary even though it may not appear in the diagram. Almost anyone using a breadboard knows what those rails are, what do the colors mean and that the way to pòwer them is mostly irrelevant as long as they get the proper voltage and current. And for the newbies and the few that may not , the community here will be happy to clarify.

    I appreciate your contribution but still fail to see why the diagram is confusing and I still think it responds to its original purpose. Feel free to improve it at your convenience.

  • Try to never try resistive sensors. It is reaaly wrong way. I try to bult few resistive. No way.
    I try to buld some inductive. Yes, it's possible, but lot of analog parts, difficult to calibrate. No way too.
    Capacitive senors is most reliable and has a simple digital schematics.

    Good luck you on your way)

    PS: here is my own sensor http://vegimatics.com/products/current/
    want do discuss - wellcome)

  • @ul7aajr The link isn’t working for me.

  • Hero Member

    @raptorjr Worked for me.

  • @neverdie Yes. Works today. Yesterday I got a 404 error.

  • Plugin Developer

    @ul7aajr said in 💬 Soil Moisture Sensor:

    Try to never try resistive sensors. It is reaaly wrong way. I try to bult few resistive. No way.
    I try to buld some inductive. Yes, it's possible, but lot of analog parts, difficult to calibrate. No way too.
    Capacitive senors is most reliable and has a simple digital schematics.

    Good luck you on your way)

    PS: here is my own sensor http://vegimatics.com/products/current/
    want do discuss - wellcome)

    I'm currently building a sensor that uses the Chirp devices. I want to chain them together. You can get them for 4 dollars each.

  • Hero Member

    @alowhum What do you mean by "chain them together"?

  • Plugin Developer

    @neverdie They support I2C. So in theory you can connect a whole bunch to a pin. I'm trying to figure out if I can detect all of them and then automatically give each a unique ID.

  • @alowhum I amm not sure how easy it is to change the I2C address on devices like this.

  • Plugin Developer

    @dbemowsk Changing the Chirp's I2C address is very easy actually.

    #include <I2CSoilMoistureSensor.h>
    #include <Wire.h>
    I2CSoilMoistureSensor sensor(0x20);
    // connect the reset pin (5) of the Chirp to a pin on your Arduino. It will create a small reset signal. This tells the chirp it should not be a stand-alone ensor, but an I2C connected one. If it receives I1C data shortyl after a reset (few seconds), then it will understand.
    int resetPin = 4;
    void setup() {
      pinMode(resetPin, OUTPUT); 
      digitalWrite(resetPin, HIGH);       // sets the digital pin 13 on
      delay(100);                  // waits for a second
      digitalWrite(resetPin, LOW);        // sets the digital pin 13 off
      sensor.begin(); // reset sensor
      delay(1000); // give some time to boot up
      Serial.print("I2C Soil Moisture Sensor Address: ");
      Serial.print("Sensor Firmware version: ");
      Serial.print("Change address to 0x21 ...");
      if (sensor.setAddress(0x21,true)) // set Sensor Address to 0x21 and reset
        Serial.println("... DONE");
        Serial.println("... ERROR");
    /*loop scans I2C bus and displays foud addresses*/
    void loop() {
      byte error, address;
      int nDevices;
      nDevices = 0;
      for(address = 1; address < 127; address++ ) {
        // The i2c_scanner uses the return value of
        // the Write.endTransmisstion to see if
        // a device did acknowledge to the address.
        error = Wire.endTransmission();
        if (error == 0) {
          Serial.print("I2C device found at address 0x");
          if (address<16)
          Serial.println("  !");
        else if (error==4) {
          Serial.print("Unknow error at address 0x");
          if (address<16)
      if (nDevices == 0)
        Serial.println("No I2C devices found\n");
      delay(3000);           // wait 5 seconds for next scan

    The default address is 0x20. So my idea is to just keep scanning, and if I find a 0x20 Chirp, then I change its I2C address to 0x21 and higher. Repeat as necessary until all 0x20 devices are gone.

    The only thing I'm not sure about is if this is possible. If I can pick them off one by one this way.

  • @alowhum That is nice. Some I2C devices have it hard coded and do not allow this from my understanding.

  • Plugin Developer

    @dbemowsk True. But it's another reason why I think the Chirp devices are pretty great soil sensors.

  • @alowhum
    Not sure I2C is a good idea excepting case all sensors inside one room. It can be used just for testing to make it easy. As usual RS485 used to connect any sensors to nework. And there is Modbus protocol over RS485 that enable to use not only custom sensors, but kind of devices can be usefull in automatic systems. For example pump controllers, valve controllers....

    So.. no good perspecrives to go

  • Plugin Developer

    Well, the Chirp doesn't support that protocol, so..
    It does have a mini arduino inside. Perhaps you could reprogram it. Then I will happily have a look 😉


  • No reason to reprogramm. There is I2C wired outside of sensor instead of UART. And some IC necessary to drive RS485.

    Would be easy to use custom adapter over the sensor with only two IC on board, some MCU and MAX485 (or analog).

  • Plugin Developer

  • @robkuipers

    Your code will fail compiling in Arduino 1.8.5 (mysensors 2.2.0) with the following errors:

    /mnt/data/Dropbox/UTV/Arduino/SoilMoisture/SoilMoisture.ino: In function 'void before()':
    /mnt/data/Dropbox/UTV/Arduino/SoilMoisture/SoilMoisture.ino:112:114: warning: extended initializer lists only available with -std=c++11 or -std=gnu++11
    /mnt/data/Dropbox/UTV/Arduino/SoilMoisture/SoilMoisture.ino:112:14: warning: extended initializer lists only available with -std=c++11 or -std=gnu++11
    /mnt/data/Dropbox/UTV/Arduino/SoilMoisture/SoilMoisture.ino:116:114: warning: extended initializer lists only available with -std=c++11 or -std=gnu++11
    /mnt/data/Dropbox/UTV/Arduino/SoilMoisture/SoilMoisture.ino:116:14: warning: extended initializer lists only available with -std=c++11 or -std=gnu++11

    So the following code need tobe changed to something valid


    I'm not a c++ guy so I can't tell what needs to be done. Maybe you or someone else would like to help out?


    EDIT: After removing the file platform.txt for solving another problem (as suggested here) The problem above vanished. So strange. But it works now so... 😎 😎 😎

  • I've found that measuring soil moisture by the electrical resistance is not a trivial task.

    If the probe is put into compact soil containing no mold, you'll typically get a high reading even at very low moisture levels. It will most likely always stay within the span of 90-100%.

    However if the probe is put into pure mold, the readings will range between 0% to 100%.

    My conclusion is that measuring directly in the soil is very unpredictable. A better solution might be to surround the probe with some material that adapts the ambient humidity from whatever kind of soil it's put into.

  • Plugin Developer

    Perhaps the capacitive sensors are more useful.

  • Mod

    I guess it depends on the soil. Resistive measurements works well for all my plants.

  • This post is deleted!

  • @mfalkvidd It depends from mineral composition of soil. I buld capacitive sensor with additional electrodes to measure salinity of soil with resistive method (it measures the resistance of soil to alternating current). So, while value of capacitive sensor stable and let say 50%, value of resistive can be critically changed by adding few milliliters of water with fertilizer. Capacitive value will be chaged only to 60% e.g.

    It's not a good idea to use resistive sensor, especcialy measuring resistance to direct current.

  • Mod

    @ul7aajr could you expand on why is it not a good idea? I've been using my sensors for almost 3 years without noticing any problem.

  • Sure. At first, I'm very surprised that your resistive sensor in soil still not destroyed under corrosion especially when the current flows. All my experiments with such sensors have been stuck many years ago. May be a miss sometihing, just show me your sensors after three years in soil? And again, it's a basic phisical things, that the conductivity of the soil depends on the mineral composition. I have already said more than once that there is possible to get a "negative" conductivity of the soil, something like effect of the battery.

  • Hello,
    I start with mysensors and I do not know much about programming. Is there a possibility to have 7 soil moisture sensor on one or two arduino mini pro.
    Thank you

  • Plugin Developer

    My sketch handles 6. Feel free to use it. It uses analog capacitive sensors. They cost about 3 euro.

    I would recommend getting an Arduino Nano with an Expansion board. Then you don't need to solder anything.

     * 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.
     * This node can measure the moisture of 6 different plants. It uses the cheap 'capacitive analog 
     * moisture sensor' that you can get for about 3 dollars an Aliexpress or eBay. For example:
     * https://www.aliexpress.com/item/Analog-Capacitive-Soil-Moisture-Sensor-V1-2-Corrosion-Resistant-Z09-Drop-ship/32858273308.html
     * Each plant' moisture value can also be responded to individually, either by turning on an LED (wire that to the plan, and you can see which one is thirsty) or, if you want, per-plant automated irrigation by connecting a little solenoid..
     * Todo: Allow the controller to set the threshold values for each plant individually. Unfortunately, Domoticz doesn't support this yet :-(
    //#define MY_SIGNING_SIMPLE_PASSWD "changeme"
    #define MY_SPLASH_SCREEN_DISABLED                       // saves a little memory.
    //#define MY_DISABLE_RAM_ROUTING_TABLE_FEATURE          // saves a little memory.
    #define MY_NODE_ID 60                                   // Optional. Sets fixed id with controller.
    #define MY_PARENT_NODE_ID 0                             // Optional. Sets fixed id for controller.
    #define MY_PARENT_NODE_IS_STATIC                        // Optional. Sets fixed id for controller.
    #define MY_TRANSPORT_WAIT_READY_MS 5000                 // try connecting for 5 seconds. Otherwise just continue.
    // Enable debug prints to serial monitor
    //#define MY_DEBUG
    // Enable and select radio type attached
    #define MY_RADIO_NRF24
    //#define MY_RADIO_NRF5_ESB
    //#define MY_RADIO_RFM69
    //#define MY_RADIO_RFM95
    #define MY_RF24_PA_LEVEL RF24_PA_LOW                    // Low power radio setting works better with cheap Chinese radios.
    #include <MySensors.h>
    #define NUMBEROFSENSORS 6                               // How many sensors are connected?
    #define DRYNESSTHRESHOLD 45                             // minimum moisture level that is still ok. A lower value will trigger LED/irrigation.
    uint32_t SLEEPTIME = 60;                                // Sleep time between the sending of data (in SECONDS). Maximum is 254 seconds. Change "byte" to "int" further down in the code if you want more time between sending updates.
    unsigned long lastTimeChecked = 0;
    MyMessage msg(0, V_LEVEL);
    void before()
      for (byte i = 3; i < NUMBEROFSENSORS + 3; i++){             // Set the LED (or irrigation vales) to their initial position.
        pinMode(i, OUTPUT);
        digitalWrite(i, LOW);
    void presentation()
    	// Send the sketch version information to the gateway and Controller
    	sendSketchInfo(F("Plant Sensorium"), F("1.2"));
      // present the sensors
      for (byte i=0; i<NUMBEROFSENSORS ; i++) {
        present(i, S_MOISTURE, i); // the last i gives the controller a name, in this case the number of the sensor.
    void setup()
      Serial.println(F("Hello world. Warming up the sensors (15 seconds)."));
    void loop()
      static byte measurementCounter = 0;                     // Counts the measurements that are done, once per second.
      uint32_t currentMillis = millis();                      // The millisecond clock in the main loop.
      if (currentMillis - lastTimeChecked > 1000) {           // Internally, the moisture values are checked every second.
        lastTimeChecked = currentMillis;
        for (int i=0; i<NUMBEROFSENSORS; i++) {               // loop over all the sensors.
          byte shiftedDigitalPin = i + 3;
        	int16_t moistureLevel = (1023-analogRead(i))/10.23;
          Serial.print(F(" mosture level: "));
          Serial.print(F("- output pin: "));
          Serial.print(F("- irrigation/LED state is "));
          if(digitalRead(shiftedDigitalPin) == HIGH){                         // outputs the LED/irrigation status via serial. This code can be removed.
            Serial.print(F("- currently watering until "));
            Serial.println(DRYNESSTHRESHOLD + 10);
          if (moistureLevel < DRYNESSTHRESHOLD){              // if the plant doesn' have enough water, turn on the LED/water.
            Serial.print(F("- moisture level is below "));
            digitalWrite(shiftedDigitalPin, HIGH);
          }else if (moistureLevel >= DRYNESSTHRESHOLD + 10){   // turn of the water/led if the plant is wet enough.
            digitalWrite(shiftedDigitalPin, LOW);
          if(measurementCounter < NUMBEROFSENSORS){           // During the first 6 seconds the script will send updated data.
            if(measurementCounter == i){                      // it sends sensor 0 at second 0. Sensor 1 at second 1, etc. This keeps the radio happy.
              Serial.println(F("- sending data."));
          if(measurementCounter > SLEEPTIME){ // If enough time has passed, the counter is reset, and new data is sent.
            measurementCounter = 0;

  • I command and I try. Thank you very much

  • Plugin Developer

    @mathieu44444 My pleasure. Good luck.

  • @mfalkvidd , maybe you are using your resistive sensors indoors in soil consisting of 100% mold. (blomjord). I guess it works great. However I'm just curious if your sensors are also working on soil from outdoors. I guess not very well.

  • @รอเร-อ I have resistive sensors (YL-69 type) both indoors and outdoors. Both have been working correctly for months now. I'm using a direct-reverse polarization sketch to minimize corrosion and it seems to work well. What I found to be very important in outdoors sensors is the isolation of the connector between the probe and the cable; if rain water or watering stays into there, they tend to corrode and their resistance increases, therefore fooling the sensor into thinking that the soil is drier than it really is. I have a couple of capacitive sensors somewhere but haven't felt the need to try them since the resistive ones are working well.

  • @alowhum

    I've ordered 5 capacitive sensors from Aliexpress now. I need to find a way to protect them so I can bury them into the soil in the garden at different depths.

    What sketch are you using for capacitive sensors?

    EDIT: I just saw your sketch posted above. I will try it out. Thanks!

  • @manutremo


    here with my soil, it's different. Even at very little moisture it shows 100%. Maybe I have a lot of iron in the soil.

  • @alowhum

    How are your capacitive sensors wired to the board?

  • Plugin Developer

    I use the expansion board I mentioned. You can just plug the sensors directly into it, all in a row from A0 to A5.

    Then on the opposite side of the board I have LED's connected to digital pins 3 till 8, one for each plant.

    I'm working on replacing the LED's with solenoids that will automatically water the plants. The code already supports this.

  • @manutremo

    how did you wire you normal fork sensor, i get different reading when using a voltage divider if i switch the polarization.
    i used this to connect it.
    using pin digital 6 and 7 as alternating power, and pin A0 to read

    And how do other people protect there capacitive sensor electronics from water .. rain

  • How would you guys protect one of these capacitive soil moisture sensors from moisture in case the probe shall be buried 20 cm deep in the soil outdoors.

    The way they are made now, they may only be used in a indoor flower pot and even then there is a risk that the probes electronic components will be drowned in water while watering your flowers. Ideally, they should be water proof from the beginning, that's what I think.

    Anyway, now I have a few of them and I intend to do a solar powered a multi depth soil moisture sensor using capacitive soil moisture sensors at various depths.

    So, how to protect them?

    I have an idea but I'm not sure it's working: Put it partly inside a plastic tube and cover the electronics with 2 component expoxy glue. ...

    EDIT 1 : maybe silicone rubber would work...
    EDIT 2 : Adding a photo of an untested prototype. Plastic housing filled with construction silicone rubber!

    EDIT 3: Prototype sensor works great. (At least for the moment. I hope it will last several years.)

  • Grafana graph


    Edit: Updated Graphana graph with watering events marked red. Red horizontal line is the automatic watering threshold (Which has been adjusted a few thimes)

  • if you buy a capacitive sensor like this then it is extremely simple. Here are some sample sketches which work pretty good. Not sure why one should bother with corrosion and similar issues when you can buy a pretty cheap capacitive sensor. Are there any drawbacks I may have missed ? I just installed one in a pot and curious to see how it goes

    Here's the code that I use

     * 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.
     * Arduino soil moisture based on gypsum sensor/resistive sensor to avoid electric catalyse in soil
     *  Required to interface the sensor: 2 * 4.7kOhm + 2 * 1N4148
     * Gypsum sensor and calibration:
     *    DIY: See http://vanderleevineyard.com/1/category/vinduino/1.html
     *    Built: Davis / Watermark 200SS
     *        http://www.cooking-hacks.com/watermark-soil-moisture-sensor?_bksrc=item2item&_bkloc=product
     *        http://www.irrometer.com/pdf/supportmaterial/sensors/voltage-WM-chart.pdf
     *        cb (centibar) http://www.irrometer.com/basics.html
     *            0-10 Saturated Soil. Occurs for a day or two after irrigation
     *            10-20 Soil is adequately wet (except coarse sands which are drying out at this range)
     *            30-60 Usual range to irrigate or water (except heavy clay soils).
     *            60-100 Usual range to irrigate heavy clay soils
     *            100-200 Soil is becoming dangerously dry for maximum production. Proceed with caution.
     * Connection:
     * D6, D7: alternative powering to avoid sensor degradation
     * A0, A1: alternative resistance measuring
     *  Based on:
     *  "Vinduino" portable soil moisture sensor code V3.00
     *   Date December 31, 2012
     *   Reinier van der Lee and Theodore Kaskalis
     *   www.vanderleevineyard.com
     * Contributor: epierre
    // 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
    // GNU General Public License for more details.
    #define MY_NODE_ID 6
    // Enable debug prints to serial monitor
    #define MY_DEBUG
    // Enable and select radio type attached
    //#define MY_RADIO_NRF24
    //#define MY_RADIO_NRF5_ESB
    #define MY_RADIO_RFM69
    //#define MY_RADIO_RFM95
    #define MY_RFM69_NEW_DRIVER
    #include <math.h>       // Conversion equation from resistance to %
    #include <MySensors.h>
    #define CHILD_ID 0
    MyMessage msg(CHILD_ID, V_LEVEL);
    static const uint64_t UPDATE_INTERVAL = 43200000;
    void setup()
     Serial.begin(115200); // open serial port, set the baud rate as 115200 bps
    void presentation()
        sendSketchInfo("Soil Moisture Sensor", "1.0");
        present(CHILD_ID, S_MOISTURE);
    void loop()
        int moisture;
        moisture = analogRead(0);
        //Serial.println(moisture); //print the value to serial port


  • Mod

    @cgeo the reasons I'm using the resistive sensor are:

    • the cost for the resistive sensor is less than 10% of the cost of the capacitive sensor you linked
    • after 3 years of use I don't experience corrosion issues except for the part that is above the dirt, which the capacitive sensor will have problems with as well

  • Hey. usually on A0 battery. as here?

  • Mod

    @ihor could you rephrase that question? What do you mean?

  • I mean, in sketch: A0, A1: alternative resistance measuring. In MySensors usually, A0 input battery level.

  • Mod

    @ihor I see. Thanks for explaining. Easiest way is probably to use some other analog pin for the battery measurement. Any of A2 to A6 should work.

  • I understood. Thank you

  • How to use:
    Required to interface the sensor: 2 * 4.7kOhm + 2 * 1N4148 (DESCRIPTION in skech)
    And: D6, D7: alternative powering to avoid sensor degradation

    • A0, A1: alternative resistance measuring

  • Mod

    @ihor A6 and A7 can not be used for alternating power. They can do analog read only.

  • understandably. but I asked about D6 (D7). what is the sensor connection?

  • Admin

    I think they can actually.

  • Mod

  • Mod

    @ihor oh. Sorry. Yes, D6 and D7 are fine.

  • Admin

    Ok, didn't know that these two had a special thing going. Thanks.

  • I use A0, A1
    2018-08-12 01:31:11.969 [vent.ItemStateChangedEvent] - MoistHum changed from 11 to 964

    2018-08-12 01:31:42.386 [vent.ItemStateChangedEvent] - MoistHum changed from 964 to 121

    2018-08-12 01:31:42.440 [vent.ItemStateChangedEvent] - MoistBat changed from 42 to 43

    2018-08-12 01:32:13.860 [vent.ItemStateChangedEvent] - MoistHum changed from 121 to 299

    2018-08-12 01:32:45.300 [vent.ItemStateChangedEvent] - MoistHum changed from 299 to 129

    2018-08-12 01:33:16.717 [vent.ItemStateChangedEvent] - MoistHum changed from 129 to -11

    2018-08-12 01:33:48.132 [vent.ItemStateChangedEvent] - MoistHum changed from -11 to -101

    2018-08-12 01:34:19.528 [vent.ItemStateChangedEvent] - MoistHum changed from -101 to 514

    2018-08-12 01:34:50.943 [vent.ItemStateChangedEvent] - MoistHum changed from 514 to 1478

    2018-08-12 01:35:22.355 [vent.ItemStateChangedEvent] - MoistHum changed from 1478 to -265

    What do I connect wrongly? the results are not true

  • any ideas?

  • Hi, I'm trying to get my first sensor to work and I followed this guide https://www.mysensors.org/build/moisture

    I got my gateway to work and the sensor got discovered in openhab. But I think the values I'm getting are quite odd and I don't think it's working as intended for me.


    That's my setup, just like on the guide. When I put the sensor it into water, 2 LED start to light up on the small blue board.

    I decreased the SLEEP_TIME for testing purpose and here's what I'm getting:

    https://pastebin.com/e93P86aY (too many characters to post it directly here)

    while this measuring, I put it several times into a cup with water and I dried it. Should negative values even happen? I'm not sure how to work with those values.

    It feels like, it's just giving me random numbers without actually measuring something.

  • Hi @atzohy

    The info in the page is confusing. The small board between the sensor and the arduino is an on-off level switcher. It provides a digital binary singnal so can't be connected to an analog pin on the arduino.

    If you wish to measure the moisture level with an analogic scale, you need to eliminate that board and then use a voltage divider and an analog pin. The sketch will be also different. Everything in explained above in the thread.

    You may want to read the full thread and then don't hesitate to come back with your questions.

  • Hi,

    I have this message :

    16 MCO:BGN:INIT NODE,CP=RNNNA---,FQ=16,REL=255,VER=2.3.2
    26 TSM:INIT
    28 TSF:WUR:MS=0
    36 TSM:FAIL:CNT=1
    39 TSF:TDI:TSL
    10041 TSM:FAIL:RE-INIT
    10043 TSM:INIT
    10049 !TSM:INIT:TSP FAIL
    10051 TSM:FAIL:CNT=2
    10053 TSM:FAIL:DIS
    10055 TSF:TDI:TSL

    What is the problem please ?
    I'm noob.

    alt text

    Thank you

  • @Diazovitch69 You can use the log parser : https://www.mysensors.org/build/parser

    16 MCO:BGN:INIT NODE,CP=RNNNA---,FQ=16,REL=255,VER=2.3.2	Core initialization of NODE, with capabilities RNNNA---, CPU frequency 16 MHz, library version 2.3.2, release 255
    26 TSM:INIT	Transition to Init state
    28 TSF:WUR:MS=0	Wait until transport ready, timeout 0
    34 !TSM:INIT:TSP FAIL	Transport device initialization failed
    36 TSM:FAIL:CNT=1	Transition to Failure state, consecutive failure counter is 1
    37 TSM:FAIL:DIS	Disable transport
    39 TSF:TDI:TSL	Set transport to sleep
    10041 TSM:FAIL:RE-INIT	Attempt to re-initialize transport
    10043 TSM:INIT	Transition to Init state
    10049 !TSM:INIT:TSP FAIL	Transport device initialization failed
    10051 TSM:FAIL:CNT=2	Transition to Failure state, consecutive failure counter is 2
    10053 TSM:FAIL:DIS	Disable transport
    10055 TSF:TDI:TSL	Set transport to sleep

    The initialization of the transport is failing. So there is a problem between your arduino? and your radio module.
    You should check your wirings!

  • Contest Winner

    @Diazovitch69 I have a hard time zooming in the provided wiring, so I can't check it. But as evb says, it looks like the radio isn't connected right. So either it's not wired correctly or you could have a broken radio.

    The things I normally do when I encounter this, is first check and double check the wiring. I also measure the individual cables in the dupont cable. It happened to me once I had bought a broken cable. Or another problem I once had, was that the power and ground rail of the bread board weren't connected from the left to the right section. Some broad boards have them connected others don't have that so you need to connect them in the middle.

    I even got a free arduino once. Because I was convinced everything was correct so I contacted the supplier and he send me a new Arduino. I replaced it and still the same problem lol. Then I measured and found the cause.

    If you're sure the wiring is correct. I'd try out another radio. Be sure that power radio with 3.3v and not 5V.

  • Hi,

    I see in the pictures of the connection that the soil sensor is attached to 3.3V, GND and D3 but I can't see where D3 is named. How do you obtain a read from D3 if it isn't named in the code?

  • Contest Winner

    @Newzwaver d3 is called just 3 in the arduino IDE for atmel boards. Only the analog pins have an A suffix. But pin 14 is also A0.

    Not sure if it answers your question. I'm on a lunch break 🙂

  • Hi

    Thank you for your reply and I understand that, if you look at the code you will see that pin 3 isn't named/defined in the coed. Unless I am missing something


Log in to reply

Suggested Topics

  • 3
  • 110
  • 2
  • 163
  • 2
  • 347