Introduction: Solar Soil Moisture Meter With ESP8266

About: Making and sharing are my two biggest passions! In total I've published hundreds of tutorials about everything from microcontrollers to knitting. I'm a New York City motorcyclist and unrepentant dog mom. My wo…

In this Instructable, we're making a solar powered soil moisture monitor. It uses an ESP8266 wifi microcontroller running low power code, and everything’s waterproof so it can be left outside. You can follow this recipe exactly, or take from it the useful techniques for your own projects.

If you're new to microcontroller programming, please check out my Arduino Class and Internet of Things Class to get caught up on the basics of wiring, coding, and connecting to the internet.

This project is part of my free Solar Class, where you can learn more ways to harness the sun's energy through engraving and solar panels.

To keep up with what I'm working on, follow me on YouTube, Instagram, Twitter, Pinterest, and subscribe to my newsletter.

Step 1: What You'll Need

You’ll need a solar battery charging board and ESP8266 breakout such as the NodeMCU ESP8266 or Huzzah, as well as a soil sensor, battery, power switch, some wire, and an enclosure to put your circuit inside.

Here are the components and materials used for the soil moisture monitor:

Here are the tools you'll need:

You'll need free accounts on cloud data sites io.adafruit.com and IFTTT.

As an Amazon Associate I earn from qualifying purchases you make using my affiliate links.

Step 2: Breadboard Prototype

It’s important to create a solderless breadboard prototype for projects like this, so you can make sure your sensor and code are working before making any permanent connections.

In this case, the soil sensor has stranded wires to it was necessary to temporarily attach solid headers to the ends of the sensor wires using solder, helping hands, and some heat shrink tubing.

Follow the circuit diagram to wire up the sensor's power, ground, clock, and data pins (data also gets a 10K pull-up resistor that comes with the soil sensor).

  • Sensor green wire to GND
  • Sensor red wire to 3.3V
  • Sensor yellow wire to NodeMCU pin D5 (GPIO 14)
  • Sensor blue wire to NodeMCU pin D6 (GPIO 12)
  • 10K pull-up resistor between blue data pin and 3.3V

You can translate this to your preferred microcontroller. If you're using an Arduino Uno or similar, your board is already supported by the Arduino software. If you're using the ESP8266, please check out my Internet of Things Class for step-by-step help getting set up with ESP8266 in Arduino (by adding supplemental URLs to the Additional Boards Manager URLs field in Arduino's preferences, then searching for and selecting new boards from the boards manager). I tend to use the Adafruit ESP8266 Huzzah board type to program the NodeMCU ESP8266 board, but you can also install and use the Generic ESP8266 board support. You'll also need the SiLabs USB communications chip driver (available for Mac/Windows/Linux).

To get the sensor up and running with my Arduino-compatible board, I downloaded the SHT1x Arduino Library from Practical Arduino's github page, then unzipped the file and moved the library folder to my Arduino/libraries folder, then renamed it SHT1x. Open up the example sketch ReadSHT1xValues and change the pin numbers to 12 (dataPin) and 14 (clockPin), or copy the modified sketch here:

#include <SHT1x.h>
#define dataPin  12  // NodeMCU pin D6
#define clockPin 14  // NodeMCU pin D5
SHT1x sht1x(dataPin, clockPin); // instantiate SHT1x object

void setup()
{
   Serial.begin(38400); // Open serial connection to report values to host
   Serial.println("Starting up");
}
void loop()
{
  float temp_c;
  float temp_f;
  float humidity;

  temp_c = sht1x.readTemperatureC(); // Read values from the sensor
  temp_f = sht1x.readTemperatureF();
  humidity = sht1x.readHumidity();

  Serial.print("Temperature: "); // Print the values to the serial port
  Serial.print(temp_c, DEC);
  Serial.print("C / ");
  Serial.print(temp_f, DEC);
  Serial.print("F. Humidity: ");
  Serial.print(humidity);
  Serial.println("%");

  delay(2000);
}

Upload this code to your board and open up the serial monitor to see the sensor data stream in.

If your code won't compile and complains about SHT1x.h not being found, you haven't got the required sensor library installed properly. Check your Arduino/libraries folder for one called SHT1x, and if it's somewhere else, like your downloads folder, move it to your Arduino libraries folder, and rename if it necessary.

If your code compiles but won't upload to your board, double check your board settings, be sure your board is plugged in, and select the correct port from the Tools menu.

If your code uploads but your serial monitor input is unrecognizable, double check your baud rate matches that specified in your sketch (38400 in this case).

If your serial monitor input doesn't seem correct, double check your wiring against the circuit diagram. Is your 10K pull-up resistor in place between the data pin and 3.3V? Are data and clock connected to the correct pins? Are power and ground connected as they should be throughout the circuit? Do not proceed until this simple sketch is working!

The next step is specific to the ESP8266 and configures the optional wireless sensor reporting portion of the sample project. If you're using a standard (non-wireless) Arduino-compatible microcontroller, continue to develop your final Arduino sketch and skip to Prepare Solar Charging Board.

Step 3: Software Setup

To compile the code for this project with the ESP8266, you'll need to install a few more Arduino libraries (available through the library manager):

Download the code attached to this step, then unzip the file and open up Solar_Powered_Soil_Moisture_Monitor_Tutorial in your Arduino software.

#include <SHT1x.h>
#include <ESP8266WiFi.h>
#include <AdafruitIO.h>
#include <Adafruit_MQTT.h>
#include <ArduinoHttpClient.h>

// Specify data and clock connections and instantiate SHT1x object
#define dataPin  12 // NodeMCU pin D6
#define clockPin 14 // NodeMCU pin D5
SHT1x sht1x(dataPin, clockPin);

// set up the feed
AdafruitIO_Feed *humidity = io.feed("humidity");
AdafruitIO_Feed *temperature = io.feed("temperature");

const int sleepTime = 15; // 15 minutes
void setup()
{
   Serial.begin(115200); // Open serial connection to report values to host
   Serial.println("Starting up");
   // connect to io.adafruit.com
  Serial.print("Connecting to Adafruit IO");
  io.connect();
  
  // wait for a connection
  while(io.status() < AIO_CONNECTED) {
    Serial.print(".");
    delay(500);
  }

  // we are connected
  Serial.println();
  Serial.println(io.statusText());
}
void loop()
{
  io.run(); // io.run(); keeps the client connected and is required for all sketches.
  
  float temp_c;
  float temp_f;
  float moisture;

  temp_c = sht1x.readTemperatureC(); // Read values from the sensor
  temp_f = sht1x.readTemperatureF();
  moisture = sht1x.readHumidity();

  Serial.print("Temperature: "); // Print the values to the serial port
  Serial.print(temp_c, DEC);
  Serial.print("C / ");
  Serial.print(temp_f, DEC);
  Serial.print("F. Humidity: ");
  Serial.print(moisture);
  Serial.println("%");
  
  humidity->save(moisture);
  temperature->save(temp_f);

  Serial.println("ESP8266 is sleeping...");
  ESP.deepSleep(sleepTime * 1000000 * 60);   // Sleep
}

This code is a mashup of the sensor code from earlier in this tutorial and a basic example from the cloud data service Adafruit IO. The program enters low power mode and sleeps most of the time, but wakes up every 15 minutes to read the temperature and humidity of the soil, and reports its data to Adafruit IO. Navigate to the config.h tab and fill in your Adafruit IO username and key, as well as your local wifi network name and password, then upload the code to your ESP8266 microcontroller.

You'll have to do a bit of prep on io.adafruit.com. After creating feeds for temperature and humidity, you can create a dashboard for your monitor featuring a graph of the sensor values and both incoming feeds' data. If you need a refresher on getting started with Adafruit IO, check out this lesson in my Internet of Things Class.

Step 4: ​Prepare Solar Charging Board

Prepare the solar charging board by soldering on its capacitor and some wires to the load output pads. I’m customizing mine to charge at a faster rate with an optional add-on resistor (2.2K soldered across PROG) and making it safer to leave unattended by replacing the surface mount resistor with a 10K thermistor attached to the battery itself. This will limit charging to safe a temperature range. I covered these modifications in more detail in my Solar USB Charger project.

Step 5: Build Microcontroller Circuit

Solder up the microcontroller board and power switch to a perma-proto board.

Connect the solar charger power output to the input of your switch, which should be rated for at least 1 amp.

Create and solder the breadboard wire connections described in the circuit diagram above (or to your personal version's specifications), including the 10K pull-up resistor on the sensor's data line.

The solar charger's Load pins will provide 3.7V battery power when no solar power exists, but will be powered directly from the solar panel if it's plugged in and sunny. Therefore the microcontroller must be able to tolerate a variety of voltages, as low as 3.7V and up to 6V DC. For those requiring 5V, a PowerBoost (500 or 1000, depending on the current required) can be used to modulate the Load voltage to 5V (as shown in the Solar USB Charger project). Here are some common boards and their input voltage ranges:

  • NodeMCU ESP8266 (used here): 5V USB or 3.7V-10V Vin
  • Arduino Uno: 5V USB or 7-12V Vin
  • Adafruit Huzzah ESP8266 Breakout: 5V USB or 3.4-6V VBat

In order to achieve the longest possible battery life, you should take some time to consider and optimize the total current your current draws. The ESP8266 has a deep sleep feature which we used in the Arduino sketch to reduce its power consumption dramatically. It wakes up to read the sensor and draws more current while it connects to the network to report the sensor's value, then goes back to sleep for a specified amount of time. If your microcontroller draws a lot of power and can't easily be made to sleep, consider porting your project to a compatible board that draws less power. Drop a question in the comments below if you need help identifying which board could be right for your project.

Step 6: Install Cable Glands

To make weatherproof entry points for the solar panel cable and sensor cable, we'll install two cable glands into the side of the weatherproof enclosure.

Test fit your components to identify the ideal placement, then mark and drill holes in a waterproof enclosure using a step drill. Install the two cable glands.

Step 7: Complete Circuit Assembly

Insert the port side of a waterproof power cable into one and solder it to the solar charger’s DC input (red to + and black to -).

Insert the soil sensor through the other gland, and connect it up to the perma-proto as per the circuit diagram.

Tape the thermistor probe to the battery. This will limit charging to a safe temperature range while the project is left unattended outside.

Charging while too hot or too cold could damage the battery or start a fire. Exposure to extreme temperatures can cause damage and shorten the battery's life, so bring it inside if it's below freezing or above 45℃/113F.

Tighten the cable glands to make a weatherproof seal around their respective cables.

Step 8: Prepare Solar Panel

Follow my Instructable to splice the cable for your solar panel with the plug side of the waterproof DC power cable set.

Step 9: Test It

Plug in your battery and turn on the circuit by pressing the power switch.

Test it out and be sure it's reporting to the internet before closing up the enclosure and installing the sensor in your herb garden, precious potted plant, or other soil within signal range of your wifi network.

Once the data from the sensor is being logged online, it’s easy to set up a recipe for email or text alerts on the API gateway site If This Then That. I configured mine to email me if the soil moisture level drops below 50.

To test it without waiting for my plant to dry out, I manually entered a data point to my humidity feed on Adafruit IO that fell below the threshold. A few moments later, the email arrives! If the soil's levels fall below my specified level, I'll get an email every time the feed is updated until I water the soil. For my sanity, I updated my code to sample the soil much less often than every 15 minutes.

Step 10: Use It Outside!

This is a fun project to customize based on your plant’s hydration needs, and it’s easy to swap out or add sensors or integrate the solar power features into your other Arduino projects.

Thanks for following along! I'd love to hear what you think; please post up in the comments. This project is part of my free Solar Class, where you can find easy backyard projects and more lessons on working with solar panels. Check it out and enroll!

If you like this project, you may be interested in some of my others:

To keep up with what I'm working on, follow me on YouTube, Instagram, Twitter, Pinterest, and Snapchat.

Wireless Contest

Participated in the
Wireless Contest