Monitoring of Soil Moisture using Arduino+Wifi, Adafruit IO and IFTTT

Overview

Soil moisture is the water stored in soil and is affected by different parameters. These parameters include temperature, soil characteristics, precipitation, and much more. In this project, the soil moisture of a certain plant is measured. Then, the obtained data is transmitted through a cloud service, known as the Adafruit IO. Once displayed, the IFTTT platform is used to connect different applications. In this case, an e-mail will be sent to the user once the obtained data reaches a certain threshold value.

Adafruit IO is a cloud service that is commonly used for the implementation of the Internet of Things (IoT) platform. It is an easy-to-use cloud service that utilizes MQTT to transmit and receive data. According to the founders of Adafruit IO, “MQTT, or message queue telemetry transport, is a protocol for device communication that Adafruit IO supports. Using an MQTT library or client allows you to publish and subscribe to a feed to send and receive feed data.”

IFTTT is a free web-based service to create chains of simple conditional statements, called applets. The user can connect two different applications by creating a certain condition for it to operate.

Hardware Used

  • RobotDyn Uno + Wi-Fi

  • Soil Moisture Sensor
  • 
    
  • Breadboard
  • 
    
  • Resistors: 100kΩ (1); 47kΩ (2)
  • 
    
  • Dupont Jumper Wires
  • 
    
  • Soil
  • You can buy all this Hardware at Createlabz.

    Software Used

    Libraries Used

    Application Description

    This project implements the platform of the Internet of Things (IoT). The gathered soil moisture data is sent to the Adafruit IO using the RobotDyn Uno + Wi-Fi board. The said board transmits the data using Wi-Fi. Once transmitted, an e-mail is sent to the user once the data reaches a certain threshold value. This warns the user that the soil is too dry or too moist.

    Set-Up the Hardware

    The image above illustrates the connections needed for this project. It is quite obvious that neither analog nor digital pins were used. This is because this project utilizes the ESP8266 chip off the board only. To gather the data, the analog input pin of the ESP8266 was used. Since the analog input pin of the ESP8266 covers voltages ranging from 0 to 1V and the output voltage of the soil moisture sensor is between 0 to 5V, a combination of resistor networks were used to divide the output voltage to reach the range of the ESP8266 through ratio and proportion.

    The image above shows the details of the RobotDyn board. The ESP8266 pinout is also shown in the image. The pin used for the analog input is labeled as “TOUT.”

    Also, it is of utmost importance that the RobotDyn board can cater different modes of communication. These modes include: USB to ESP8266 (upload sketch only), USB to ESP8266 (connect only), USB to ATMEGA, ATMEGA to ESP8266, and the different chips work independently. These modes can be used using the switches seen on the board. The table below shows the different switch configurations to change the modes available.

    Set-Up the Software

    Sensor Calibration

    Before setting up the code needed for this project, it is imperative that the soil moisture must be calibrated in order to give accurate results. This part of the tutorial will explain the process of calibrating the soil moisture sensor.

    int sensor_pin = A0;
    int output_value;
    int raw;
    int dryval = 400;
    int moistval = 750;
    
    void setup() {
      Serial.begin(115200);
      Serial.println("Reading From the Sensor ...");
      delay(2000);
    }
    
    void loop() {
    
      raw = analogRead(sensor_pin);
      Serial.println(raw);
      output_value = map(raw, dryval, moistval, 0, 100);
      Serial.print("Moisture : ");
      Serial.print(output_value);
      Serial.println("%");
      delay(1000);
    }

    The code shown above is used as the process of getting the soil moisture percentage. It is important to change the mode of the RobotDyn board to connect the CH340 and the ATMEGA328 chips. This allows the board to work as a regular Arduino Uno.

    To calibrate the sensor, the user should measure the raw value obtained from the sensor in the dry and wet soil, respectively. In the sample code shown above, the obtained raw value in dry soil is at 400 while 750 is acquired in the wet or moist soil.

    Once these raw values are acquired, the moisture percentage can now be calculated using the Arduino’s own map() function. This function scales a range of values to another range of values. In this project, the values from 400 to 750 is scaled down to 0 to 100. This allows the data to be labeled as a percentage ranging from 0 to 100.

    After calibrating the sensor, setting up the Arduino IDE is the next thing to do.

    Arduino IDE Setup

    Since the RobotDyn board contains the ESP8266 module, the Arduino IDE must have the right specifications for it to upload the necessary code for this project.

    To start, open the Arduino IDE and go to File and click Preferences.

    In the Preferences tab,  there is a text box which asks the URL of any additional boards. Paste this link: http://arduino.esp8266.com/stable/package_esp8266com_index.json

    Then, go to the Boards Manager of the IDE. The Boards Manager is found on the Tools tab.

    The Boards Manager displays the different boards that the Arduino IDE supports. Use the search bar to install ESP8266 board.

    After installing the ESP8266 board, use the board manager to select the Generic ESP8266 Module.

    The Arduino IDE is now ready to proceed.

    Code Breakdown

    After setting up the Arduino IDE, it is now time to utilize the code which allows the RobotDyn board to transmit the gathered data to Adafruit IO. The code is shown below.

    #include <Adafruit_MQTT.h>
    #include <Adafruit_MQTT_Client.h>
    #include <ESP8266WiFi.h>
    
    
    //WiFi network name & password
    #define ssid "wifi_ssid"
    #define password "wifi_password"
    
    //Username & AIO key
    #define AIO_SERVER          "io.adafruit.com"
    #define AIO_SERVERPORT      1883                   // use 8883 for SSL
    #define AIO_USERNAME        "adafruit_username" //paste the AIO username here
    #define AIO_KEY             "adafruit_key" //paste the AIO key here
    
    int sensor_pin = A0;
    int output_value;
    int raw;
    int dryval = 400;
    int moistval = 750;
    
    const unsigned long SECOND = 1000;
    const unsigned long HOUR = 3600 * SECOND;
    
    // Create an ESP8266 WiFiClient class to connect to the MQTT server.
    WiFiClient client;
    const char SOILMOISTURE_FEED[] PROGMEM = AIO_USERNAME "/feeds/soilmoisture";
    
    // Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
    Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);
    
    // Setup a feed called 'onoff' for subscribing to changes.
    Adafruit_MQTT_Publish soilmoisture = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/soilmoisture");
    
    void MQTT_connect();
    
    void setup() {
      Serial.begin(115200);
      delay(3000);
    
      WiFi.begin(ssid, password);             // Connect to the network
      Serial.print("Connecting to ");
      Serial.print(ssid); Serial.println(" ...");
    
      int i = 0;
      while (WiFi.status() != WL_CONNECTED) { // Wait for the Wi-Fi to connect
        delay(1000);
        Serial.print(++i); Serial.print(' ');
      }
    
      Serial.println('\n');
      Serial.println("Connection established!");
      Serial.print("IP address:\t");
      Serial.println(WiFi.localIP());         // Send the IP address of the ESP8266 to the computer
    
    }
    
    uint32_t x = 0;
    
    void loop() {
      // Ensure the connection to the MQTT server is alive (this will make the first
      // connection and automatically reconnect when disconnected).  See the MQTT_connect
      // function definition further below.
      MQTT_connect();
    
      SoilMoisture();
    
      Serial.print(F("\nSending soil moisture val "));
      Serial.print(raw);
      Serial.print("...");
      if (! soilmoisture.publish(output_value++)) {
        Serial.println(F("Failed"));
      } else {
        Serial.println(F("OK!"));
      }
    
      delay(HOUR/6);
    }
    void MQTT_connect() {
      int8_t ret;
    
      // Stop if already connected.
      if (mqtt.connected()) {
        return;
      }
    
      Serial.print("Connecting to MQTT... ");
    
      uint8_t retries = 3;
      while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
        Serial.println(mqtt.connectErrorString(ret));
        Serial.println("Retrying MQTT connection in 5 seconds...");
        mqtt.disconnect();
        delay(5000);  // wait 5 seconds
        retries--;
        if (retries == 0) {
          // basically die and wait for WDT to reset me
          while (1);
        }
      }
      Serial.println("MQTT Connected!");
    }
    
    void SoilMoisture() {
      raw = analogRead(sensor_pin);
      Serial.println(raw);
      output_value = map(raw, dryval, moistval, 0, 100);
      Serial.print("Moisture : ");
      Serial.print(output_value);
      Serial.println("%");
      delay(1000);
    
    }

    The code is divided into five major parts. These are the declaration of variables, setup, loop, MQTT_connect() function and the SoilMoisture() function. Each major part will be thoroughly explained.

    #include <Adafruit_MQTT.h>
    #include <Adafruit_MQTT_Client.h>
    #include <ESP8266WiFi.h>
    
    
    //WiFi network name & password
    #define ssid "wifi_ssid"
    #define password "wifi_password"
    
    //Username & AIO key
    #define AIO_SERVER          "io.adafruit.com"
    #define AIO_SERVERPORT      1883                   // use 8883 for SSL
    #define AIO_USERNAME        "adafruit_username"
    #define AIO_KEY             "adafruit_key"
    
    int sensor_pin = A0;
    int output_value;
    int raw;
    int dryval = 400;
    int moistval = 750;
    
    const unsigned long SECOND = 1000;
    const unsigned long HOUR = 3600 * SECOND;
    
    // Create an ESP8266 WiFiClient class to connect to the MQTT server.
    WiFiClient client;
    const char SOILMOISTURE_FEED[] PROGMEM = AIO_USERNAME "/feeds/soilmoisture";
    
    // Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
    Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);
    
    // Setup a feed called 'soilmoisture' for subscribing to changes.
    Adafruit_MQTT_Publish soilmoisture = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/soilmoisture");

    The code snippet shown above is the declaration of variables. This is where the variables are first initialized. Also, the libraries needed are also defined in this part of the code.

    It is important to encode the SSID and the password of the WLAN used. The SSID is simply the name of the network, while the password is the network password itself.

    The AIO username and AIO key are found on the Adafruit IO website. It is important that the user must sign in to Adafruit IO to get the AIO key. The method of signing up will be explained thoroughly in the latter portions of this tutorial.

    This is also where the code initializes the connections to the Adafruit IO. The connection to the feed, which displays the real-time data, is first introduced.

    void setup() {
      Serial.begin(115200);
      delay(3000);
    
      WiFi.begin(ssid, password);             // Connect to the network
      Serial.print("Connecting to ");
      Serial.print(ssid); Serial.println(" ...");
    
      int i = 0;
      while (WiFi.status() != WL_CONNECTED) { // Wait for the Wi-Fi to connect
        delay(1000);
        Serial.print(++i); Serial.print(' ');
      }
    
      Serial.println('\n');
      Serial.println("Connection established!");
      Serial.print("IP address:\t");
      Serial.println(WiFi.localIP());         // Send the IP address of the ESP8266 to the computer
    
    }

    The second major part of the code is the setup function. This is where the baud rate is initialized. Baud rate is defined as the rate of transfer of information in a communication channel. In this project, a baud rate of 115200 is used. This means that the serial port is capable of sending and receiving a maximum of 115200 bits per second.

    Also, this is where the RobotDyn board connects to the WLAN network. The IP address is also printed on the serial monitor to ensure the user that the connection to the WLAN network is established.

    void loop() {
      // Ensure the connection to the MQTT server is alive (this will make the first
      // connection and automatically reconnect when disconnected).  See the MQTT_connect
      // function definition further below.
      MQTT_connect();
    
      SoilMoisture();
    
      Serial.print(F("\nSending soil moisture val "));
      Serial.print(raw);
      Serial.print("...");
      if (! soilmoisture.publish(output_value++)) {
        Serial.println(F("Failed"));
      } else {
        Serial.println(F("OK!"));
      }
    
      delay(HOUR/6);
    }

    The third major part of the code is the loop function. The processes inside this function are done repeatedly by the RobotDyn board. The processes inside this loop are the connections to the MQTT server, the data acquisition from the soil moisture sensor, and the data transmission to the Adafruit IO server. MQTT, or Message Queuing Telemetry Transport, is a type of messaging protocol which uses the publish-subscribe method to transmit and receive data. This messaging protocol is bandwidth-efficient and uses less battery power since the devices are connected via a satellite link.

    Also, the loop function holds the delay of transmitting the gathered data to the server. In this project, the soil moisture percentage is sent every 10 minutes. The time interval can be changed by giving a certain value to the delay() function.

    void MQTT_connect() {
      int8_t ret;
    
      // Stop if already connected.
      if (mqtt.connected()) {
        return;
      }
    
      Serial.print("Connecting to MQTT... ");
    
      uint8_t retries = 3;
      while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
        Serial.println(mqtt.connectErrorString(ret));
        Serial.println("Retrying MQTT connection in 5 seconds...");
        mqtt.disconnect();
        delay(5000);  // wait 5 seconds
        retries--;
        if (retries == 0) {
          // basically die and wait for WDT to reset me
          while (1);
        }
      }
      Serial.println("MQTT Connected!");
    }

    The fourth major part of the code is the MQTT_connect() function. This is where the connections to the MQTT server is programmed. This method handles the event when the MQTT and the RobotDyn board are disconnected. Once disconnected, the code will try to reconnect again to the server. This is the main reason why this function is inside the loop.

    void SoilMoisture() {
      raw = analogRead(sensor_pin);
      Serial.println(raw);
      output_value = map(raw, dryval, moistval, 0, 100);
      Serial.print("Moisture : ");
      Serial.print(output_value);
      Serial.println("%");
      delay(1000);
    }

    The fifth and final major part of the code is the SoilMoisture() function. This has been explained in the earlier parts of the tutorial. This is where the raw analog value is obtained from the soil moisture sensor and calibrated to acquire accurate results.

    Adafruit IO and IFTTT

    This part of the tutorial will thoroughly explain the step-by-step process of using the Adafruit IO to save data and the IFTTT to connect two different applications.

    Before using the Adafruit IO, the user must sign in. The sign-in process is similar to other websites and can be found by clicking this link.

    After creating the Adafruit IO account, it is now time to create a feed. This is where the data are pushed into the AIO.

    Creating a Feed

    Click on the Feeds tab located on the left side of the web page.

    Once the page appears, click on Actions to create a new feed.

    Click “Create a New Feed” and a pop-up will appear. Fill out the necessary information. Note that the feed name must be similar with the feed name found on the Arduino code.

    Click “Create” to create the feed.

    After creating the feed, it is now time to display the gathered data in an orderly fashion. To do this, a dashboard is used.

    Creating a Dashboard

    Click “Dashboards” to display the web page. The button is located on the left side and is below the Feeds button.

    Click the Actions button to display the different options. Click on Create a new dashboard.

    After clicking the button, a pop-up will appear. Fill out the necessary information.

    Once the Create button is clicked, the dashboard will show its empty template. The next thing to do is to create a block. The button is found on the top-right side of the page. Click the blue button.

    Once clicked, a pop-up will appear which displays the available blocks. These blocks show the gathered data in a simple manner, rather than just pure numbers. In this project, a line graph is utilized to visualize the obtained data.

    After choosing the line graph as a way of displaying the obtained data, another pop-up will appear. The pop-up will allow the user to choose the feed used for display.

    After picking the desired feed, click Next step to edit the different parameters of the line graph. Fill out the necessary information.

    Click “Create block” to create the block.

    Adafruit IO Key

    To connect the Arduino code and the Adafruit IO, a key is used. This is generated by Adafruit itself and must be kept safe to avoid intruders from seeing the obtained data.

    In the Dashboard page, click the yellow button.

    When clicked, a pop-up will appear. This will show the AIO key.

    Copy the active key and paste it into the Arduino code which initializes the AIO key.

    IFTTT

    IFTTT is a web-based service which allows its users to connect two different applications. In this project, IFTTT will connect the Adafruit IO to the user’s e-mail account. Once the gathered data reaches a certain threshold value, it will send an e-mail to the user. The e-mail will then warn the user if the soil is either too dry or too moist.

    To use IFTTT, one must first create an account. The steps on creating an account are quite similar to any other websites.

    IFTTT uses applets to connect different applications. In this project, the user must create his/her own applet. This part of the tutorial will explain the process of creating an applet and connecting the Adafruit IO and GMail.

    To create an applet, click the drop-down button located on the top-right side of the web page. Then, click New Applet.

    Once clicked, a new web page will appear. Click the blue portion of the web page to start creating the applet.

    Once clicked, the different applications are shown. Use the search bar to find Adafruit IO.

    Click the Adafruit button and two choices will appear. Click the first option since the e-mail only occurs when a threshold value is reached.

    The next step is to fill out the necessary information. In this project, the threshold value is at 25%.

    After creating the trigger, the next step is to connect it to the next application. Click the blue portion to start.

    When clicked, a new web page will appear which displays the applications. Use the search bar to find the e-mail. Connect Gmail to IFTTT.

     

    After connecting Gmail, a web page shows three options. The second option is used since the user will only receive the e-mail.

    When picked, a pop-up asks the necessary information. Fill up the blank parts. Click “Create Action” to create the applet.

    Once clicked, IFTTT allows the user to review the finished applet.

    The applet is now complete and ready to use.

    Important Notes

    • The code for this project is uploaded to the Generic ESP8266 module, not the Arduino Uno board.
    • When uploading the code, the board switches 5, 6, and 7 must be switched on.
    • After uploading, switches 1 and 2 must be switched on and the other switches must be turned off.
    • The user may use switches 3 and 4 to use the RobotDyn board as a regular Arduino Uno.

    References

     

    The post Monitoring of Soil Moisture using Arduino+Wifi, Adafruit IO and IFTTT appeared first on CreateLabz.

    AdafruitAdafruit ioAppletArduino unoDryEsp8266IftttKnowledgebaseMqttPlantSoilSoil moistureWaterWetWifi

    Leave a comment

    All comments are moderated before being published