Soil Moisture Sensor Interfacing with ESP32

Overview of Soil Moisture

 

Soil Moisture Sensor
Soil Moisture Sensor

 

Soil moisture is basically the content of water present in the soil. This can be measured using a soil moisture sensor which consists of two conducting probes that act as a probe. It can measure the moisture content in the soil based on the change in resistance between the two conducting plates.

The resistance between the two conducting plates varies in an inverse manner with the amount of moisture present in the soil.

For more information about soil moisture sensor and how to use it, refer the topic Soil Moisture Sensor in the sensors and modules section.

 

Soil Moisture Hardware Connection with ESP32

ESP32 interfacing with Soil Moisture

 

 

Read Soil Moisture using ESP32 and Arduino IDE

Measuring soil moisture in terms of percentage.

Here, the analog output of the soil moisture sensor is processed using ADC. The moisture content in terms of percentage is displayed on the serial monitor.

The output of the soil moisture sensor changes in the range of ADC value from 0 to 4095.

This can be represented as moisture value in terms of percentage using formula given below.

                                                   Moisture in percentage = 100 – (Analog output * 100)

For zero moisture, we get a maximum value of 12-bit ADC, i.e. 4096. This, in turn, gives 0% moisture.

 

Code for Soil Moisture using ESP32 and Arduino IDE

/*
  ESP32 Soil Moisture Sensor
  http:://www.electronicwings.com
*/

int _moisture,sensor_analog;
const int sensor_pin = A0;  /* Soil moisture sensor O/P pin */

void setup(void){
  Serial.begin(115200);     /* Set the baudrate to 115200*/
}

void loop(void){
  sensor_analog = analogRead(sensor_pin);
  _moisture = ( 100 - ( (sensor_analog/4095.00) * 100 ) );
  Serial.print("Moisture = ");
  Serial.print(_moisture);  /* Print Temperature on the serial window */
  Serial.println("%");
  delay(1000);              /* Wait for 1000mS */
}

 

  • Now upload the code. (While uploading the code make sure your ESP32 board is in the boot mode.)
  • After uploading the code open the serial monitor and set the baud rate to 115200 to see the output.

 

Soil Moisture Output on the Serial Window

 

Let’s understand the code

Set the ADC pin number for the soil moisture sensor

int _moisture,sensor_analog;
const int sensor_pin = A0;  /* Soil moisture sensor O/P pin */

 

In setup function

We have initiated the serial communication with a 9600 Baud rate.

Serial.begin(9600);

 

In loop function

In the loop function, we will read the ADC value then convert it into percentages and display them on the serial monitor.

sensor_analog = analogRead(sensor_pin);
_moisture = ( 100 - ( (sensor_analog/4095.00) * 100 ) );
Serial.print("Moisture = ");
Serial.print(_moisture);  /* Print Temperature on the serial window */
Serial.println("%");
delay(1000);              /* Wait for 1000mS */

 

Reading Soil Moisture over ESP32 WebServer

ESP32 has oh-chip Wi-Fi, we can utilize it and monitor the readings over our smartphone, Laptop, or even smart TV. This can offer much more flexibility and real world applications.

We can use the ESP32 web server to monitor the moisture.

Let’s take another example to display the same readings on the web server using the ESP32 and Arduino IDE.

Before uploading the code make sure you have added your SSID, and Password as follows.

const char* ssid = "*Your SSID*";         /*Enter Your SSID*/
const char* password = "*Your Password*"; /*Enter Your Password*/

Code for Soil Moisture using ESP32 and Arduino IDE

/*
  ESP32 Soil Moisture Sensor
  http:://www.electronicwings.com
*/

#include <WiFi.h>
#include <WebServer.h>
#include "html.h"

WebServer server(80);

int _moisture,sensor_analog;
const int sensor_pin = A0;  /* Soil moisture sensor O/P pin */

const char* ssid = "*Your SSID*";         /*Enter Your SSID*/
const char* password = "*Your Password*"; /*Enter Your Password*/
 
void MainPage() {
  String _html_page = html_page;              /*Read The HTML Page*/
  server.send(200, "text/html", _html_page);  /*Send the code to the web server*/
}

void SoilMoisture() {
  String MoistuValue = String(_moisture);    //Convert it into string
  server.send(200, "text/plane", MoistuValue);  //Send updated temperature value to the web server
}

void setup(void){
  Serial.begin(115200);               /*Set the baudrate to 115200*/
  WiFi.mode(WIFI_STA);                /*Set the WiFi in STA Mode*/
  WiFi.begin(ssid, password);
  Serial.print("Connecting to ");
  Serial.println(ssid);
                          /*Wait for 1000mS*/
  while(WiFi.waitForConnectResult() != WL_CONNECTED){
    Serial.print(".");
    delay(100);
  }
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("Your Local IP address is: ");
  Serial.println(WiFi.localIP());     /*Print the Local IP*/

  server.on("/", MainPage);           /*Display the Web/HTML Page*/
  server.on("/readMoisture", SoilMoisture);       /*Display the updated Temperature and Humidity value*/
  server.begin();                    /*Start Server*/
  delay(1000);                       /*Wait for 1000mS*/
}

void loop(void){
  sensor_analog = analogRead(sensor_pin);
  _moisture = ( 100 - ( (sensor_analog/4095.00) * 100 ) );
  server.handleClient(); 
  Serial.print("Moisture = ");
  Serial.print(_moisture);           /* Print Temperature on the serial window */
  Serial.println("%");
  delay(1000);                          /* Wait for 1000mS */
}

 

  • Now upload the code. (While uploading the code make sure your ESP32 board is in the boot mode.)
  • After uploading the code open the serial monitor and set the baud rate to 115200 then reset the ESP32 board and check the IP address as shown in the below image

 

 

Output on the webserver

  • Now open any mobile browser and type the IP address which is shown in the serial monitor and hit the enter button. 
  • If all are ok, then the web page will start the showing current moisture level on the web server like in the below image.

Note: make sure your ESP32 and mobile are connected to the same router/server, if they are connected to the same router or server then only you will be able to visible the web page.

 

 

Let’s Understand the code

To understand this code, please refer to the basics guide of “How to create the ESP32 Server”.

Once you get the basics of ESP32 server creation, it will be very simple to understand the code.

This code starts with important header files and libraries, In WiFi.h file contains all ESP32 WiFi related definitions, here we have used them for network connection purposes. 

The WebServer.h file supports handling the HTTP GET and POST requests as well as setting up a server. In the html.h file contains all the web page code.

#include <WiFi.h>
#include <WebServer.h>
#include "html.h"

Let’s define HTTP port i.e., Port 80 as follows

WebServer server(80);

Define the variables for three axis

int _moisture,sensor_analog;

Set the ADC Input pin of ESP32 for the soil moisture sensor

const int sensor_pin = A0;  /* Soil moisture sensor O/P pin */

 

Setup Function

In the setup function, first we set the WiFi as an STA mode and connect to the given SSID and password

WiFi.mode(WIFI_STA);          /*Set the WiFi in STA Mode*/
WiFi.begin(ssid, password);
Serial.print("Connecting to ");
Serial.println(ssid);
delay(1000);                  /*Wait for 1000mS*/
while(WiFi.waitForConnectResult() != WL_CONNECTED){Serial.print(".");}

After successfully connecting to the server print the local IP address on the serial window.

Serial.print("Your Local IP address is: ");
Serial.println(WiFi.localIP());     /*Print the Local IP*/

 

Handling Client Requests and Serving the Page:

To handle the client request, we use server.on() function.

It takes two parameters, The first is the requested URL path, and the second is the function name, which we want to execute.

As per the below code, when a client requests the root (/) path, the “MainPage()” function executes. 

Also, when a client requests the “/readMoisture” path, The SoilMoisture() function will be called.

server.on("/", MainPage);           /*Client request handling: calls the function to serve HTML page */
server.on("/readMoisture", SoilMoisture);       /*Display the updated Temperature and Humidity value*/

Now start the server using server.begin() function.

server.begin();                     /*Start Server*/

 

Functions for Serving HTML

We have defined the complete HTML page in a file named “html.h” and added it to the header file. With the following function, we are sending the complete page to the client via server.send() function.

While sending, we are passing the first parameter “200” which is the status response code as OK (Standard response for successful HTTP requests). 

Second parameter is the content type as “text/html“, and the third parameter is html page code.

void MainPage() {
  String _html_page = html_page;              /*Read The HTML Page*/
  server.send(200, "text/html", _html_page);  /*Send HTM page to Client*/
}

Now in the below function only we are sending the updated moisture values to the web page.

void SoilMoisture() {
  String MoistuValue = String(_moisture);    //Convert it into string
  server.send(200, "text/plane", MoistuValue);  //Send updated temperature value to the web server
}

 

Loop Function

Now to handle the incoming client requests and serve the relevant HTML page, we can use handleClient() function. It executing relevant server.on() as a callback function although it is defined in void setup()

So, it continuously serves the client requests.

server.handleClient();

 

HTML Page Code

/*
  ESP32 HTML WebServer Page Code
  http:://www.electronicwings.com
*/

const char html_page[] PROGMEM = R"rawSrting(
<!DOCTYPE html>
<html>
  <style>
    body {font-family: sans-serif;}
    h1 {text-align: center; font-size: 30px;}
    p {text-align: center; color: #4CAF50; font-size: 40px;}
  </style>
 
<body>
  <h1>Soil Moisture With ESP32</h1><br>
  <p>Moisture Level :<span id="MoistureVal">0</span>%</p><br>

  <script>
    setInterval(function() {
      var xhttp = new XMLHttpRequest();
      xhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
         document.getElementById("MoistureVal").innerHTML = this.responseText;
        }
      };
      xhttp.open("GET", "readMoisture", true);
      xhttp.send();
    },50);
  </script>
</body>
</html>
)rawSrting";

 

Let’s understand the code step by step

All html pages start with the <!DOCTYPE html> declaration, it is just information to the browser about what type of document is expected.

<!DOCTYPE html>

The html tag is the container of the complete html page which represents on the top of the html code.

<html>

Now here we are defining the style information for a web page using the <style> tag. Inside the style tag we have defined the font name, size, color, and test alignment. 

  <style>
    body {font-family: sans-serif;}
    h1 {text-align: center; font-size: 30px;}
    p {text-align: center; color: #4CAF50; font-size: 40px;}
  </style>

 

Inside the body, we are defining the document body, in below we have used headings, and paragraphs if you want you can add images, hyperlinks, tables, lists, etc. also.

On the web page, we are displaying the heading of the page, and inside a paragraph moisture readings. 

Now moisture value updates under the span id which is manipulated with JavaScript using the id attribute.

<body>
  <h1>Soil Moisture With ESP32</h1><br>
  <p>Moisture Level :<span id="MoistureVal">0</span>%</p><br> 

Now, this is the javascript that comes under the <script> tag, this is also called a client-side script.

<script>

In setInterval() method we are calling the function at every 50mS intervals.

setInterval(function() {},50);

here we are creating the html XMLHttpRequest object

var xhttp = new XMLHttpRequest();

 

The xhttp.onreadystatechange event is triggered every time the readyState changes and the readyState holds the status of the XMLHttpRequest.

Now in the below code, the ready state is 4 means the request finished and response is ready and the status is 200 which means OK.

xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
const myArr = JSON.parse(this.responseText);

Now here is the main thing, we are updating the moisture values in html page using MoistureVal id.

document.getElementById("MoistureVal").innerHTML = this.responseText;

 

Here we used the AJAX method to send the updated values to the server without refreshing the page.

In the below function we have used the GET method and sent the readADXL345 function which we defined in the main code asynchronously. 

xhttp.open("GET", "readMoisture", true); 

Send the request to the server using xhttp.send(); function.

xhttp.send();

 

Close the script

</script>

Close the body

</body>

Close the html.

</html>

Components Used

Soil Moisture Sensor
Soil moisture sensor is used to measure the water content (moisture) in soil. It is used in agriculture applications, irrigation and gardening systems, etc.
1
ESP32 WROOM
WiFi Development Tools - 802.11 ESP32 General Development Kit, embeds ESP32-WROOM-32E, 4MB flash.
1

Downloads

ESP32_Soil_Moisture Download
ESP32_Soil_Moisture_WebServer Download
Ad