Introduction: ESP8266 Smart Plant

In this tutorial we wil guide you how to make a smart plant with an ESP8266. The tutorial includes hardware requirements, software requirements, a guide to make the ESP8266 work, a tutorial to setup Adafruit IO and a little troubleshooting guide.

Step 1: Hardware Requirements

Step 2: Software Requirements

Extra options

  • IFTTT account (This can be used to ad external services like Google Assistant...)

Step 3: Wiring Diagram

The wiring diagram is shown above. Want to know how I made the system? There is an video below that shows the project itself.

Step 4: Setup the Board in Arduino

To get the board working in the Arduino software, you need to follow a few steps:

  • Download and install the Arduino software
  • Download and install the ESP8266 driver
  • Start the Arduino program and go to Sketch > Include library > Manage libraries..
  • Search for esp8266 and then install the library
  • Then go to Tools > Board
  • Then select NODEMCU 1.0
  • Set the upload speed to 9600, under > Tools > Upload speed
  • To check if the code works, go to File > Examples > ESP8266 > Blink
  • Upload this code to the board.
  • If everything works, the code wil upload and a small led on the board wil blink.

Note: If it doesn't work, try the troubleshooting!

Step 5: Adafruit Setup

  • Create an account at io.adafruit.com
  • Go to Feeds and click on 'Actions' to create a new feed.
  • Make the following feed with the following values:
    • Make a meter feed called 'moisture' with an max of 100
    • Make a meter feed called 'temperature' with an max of (Max. temperature in your environment.)
    • Make a meter feed called 'humidity' with an max of 100.
    • Make a switch feed called 'waterswitch' with the values 'Auto' and 'Off'
    • Make a table feed called 'levels' and include the values of moisture, temperature and humidity.
    • Make a text feed called 'messages'
  • Now you can make a dashboard and add all the feeds in a desired direction.

    Step 6: The Example Code

    Note: Make sure you fill in the right Wifi and Adafruit credentials to get the code working. The adafruit credentials can be found in your Adafruit OI account in your dashboard. There is a small key icon.

    /***************************************************<br>  Adafruit MQTT Library ESP8266 Smart Plant System
      Written by Tony DiCola for Adafruit Industries.
      MIT license, all text above must be included in any redistribution
     *
    ************************* INCLUDES *********************************/
    #include 
    #include "Adafruit_MQTT.h"
    #include "Adafruit_MQTT_Client.h"
    #include
    dht DHT;
    /************************* VARIABLE DEFINITIONS *********************************/
    #define FLOAT D6
    #define GREENLED D10
    #define REDLED D1
    #define PUMP D5
    #define TEMP D7
    /************************* WIFI SSID & PASS *********************************/
    #define WLAN_SSID       "wifi_name_here"
    #define WLAN_PASS       "wifi_pass_here"
    /************************* ADAFRUIT AUTHORISATION *********************************/
    #define AIO_SERVER      "io.adafruit.com"
    #define AIO_SERVERPORT  1883 // use 8883 for SSL
    #define AIO_USERNAME    "your_username_here"
    #define AIO_KEY         "your_AIO_key_here"
    WiFiClient client;
    Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);
    /****************************** ADAFRUIT FEEDS ***************************************/
    Adafruit_MQTT_Publish moisture = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/moisture");
    Adafruit_MQTT_Publish temperture = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/temperture");
    Adafruit_MQTT_Publish humidity = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/humidity");
    Adafruit_MQTT_Publish messages = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/messages");
    Adafruit_MQTT_Subscribe waterswitch = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/waterswitch");
    Adafruit_MQTT_Subscribe level = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/level");
    void MQTT_connect();
    /*************************** SETUP ************************************/
    Adafruit_MQTT_Subscribe *subscription;
    bool waterEmpty;
    bool waterSwitchAuto;
    bool waterSwitchEnabled;
    int moistureLevel;
    int moistureLevelTarget;
    double sensorTemperature;
    double sensorHumidity;
    void setup() {
      //  Define inputs & outputs
      Serial.begin(115200);
      Serial.print("Executing code...");
      pinMode(PUMP, OUTPUT);
      pinMode(FLOAT, INPUT_PULLUP);
      pinMode(GREENLED, OUTPUT);
      pinMode(REDLED, OUTPUT);
      // Connect to WiFi access point.
      Serial.println(); Serial.println();
      Serial.print("Connecting to ");
      Serial.println(WLAN_SSID);
      WiFi.begin(WLAN_SSID, WLAN_PASS);
      while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
      }
      Serial.println();
      Serial.println("WiFi connected");
      Serial.println("IP address: "); Serial.println(WiFi.localIP());
      mqtt.subscribe(&waterswitch);
      mqtt.subscribe(&level);
          digitalWrite(PUMP, LOW);
      waterEmpty = true;
      waterSwitchAuto = false;
      waterSwitchEnabled = true;
      moistureLevel = 100;
      moistureLevelTarget = 0;
      sensorHumidity = 0.0;
      sensorTemperature = 0.0;
    }
    void loop() {
      // connect
      MQTT_connect();
      
      // read
      readMoistureLevel();
      readTemperatureHumidity();
      readWaterLevel();
      readAdafruitSubscriptions();
      // write
      publishStatusAdafruit();
      updateLEDs();
      controlPump();
    }
    // Function to connect and reconnect as necessary to the MQTT server.
    // Should be called in the loop function and it will take care if connecting.
    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 readMoistureLevel()
    {
        // read moisture sensor
      int sensorValue = analogRead(A0);
      int percents = sensorValue / 10.24;
      moistureLevel = 100 - percents;
    }
    void readTemperatureHumidity()
    {
      // read temperature and humidity sensor
      int chk = DHT.read11(TEMP);
      if (chk == DHTLIB_OK)
      {
        sensorTemperature = DHT.temperature;
        sensorHumidity = DHT.humidity;
      }
    }
    void readWaterLevel()
    {
      //  read water level sensor
      if (digitalRead(FLOAT) == HIGH) {
        waterEmpty = true;
      } else {
        waterEmpty = false;
      }
    }
    void readAdafruitSubscriptions() 
    {
        // Read Adafruit subscriptions and update internal variables
      subscription = mqtt.readSubscription(5000);
      if (subscription == &waterswitch) {
        if (strcmp((char *)waterswitch.lastread, "Auto") == 0) {
          waterSwitchAuto = true;
        } else {
          waterSwitchAuto = false;
        }
      }
      else if (subscription == &level) {
        uint16_t levelval = atoi((char *)level.lastread);  // convert to a number
        moistureLevelTarget = levelval;
      }
    }
    void publishStatusAdafruit() {
      // Publish sensor values to Adafruit
      if (!waterEmpty && waterSwitchAuto)
      {
        messages.publish("Water level ok");
      }
      else
      {
        messages.publish("Refil water please!");
      }
      moisture.publish(moistureLevel);
      temperture.publish(sensorTemperature, 1);
      humidity.publish(sensorHumidity, 1);
    }
    void updateLEDs() {
      // Control green led
      if (waterSwitchAuto)
      {
        digitalWrite(GREENLED, HIGH);
      }
      else
      {
        digitalWrite(GREENLED, LOW);
      }
      // Control red led
      if (waterEmpty)
      {
        digitalWrite(REDLED, HIGH);
      }
      else
      {
        digitalWrite(REDLED, LOW);
      }  
    }
    void controlPump() {
        // Control pump
      if (waterSwitchEnabled && waterSwitchAuto && !waterEmpty && moistureLevel < moistureLevelTarget) {
        digitalWrite(PUMP, HIGH);
        delay(2000);
        digitalWrite(PUMP, LOW);
      }
      else {
        digitalWrite(PUMP, LOW);
      }
    }
    
    
    

    Step 7: Test the Prototype

    Now it is time to upload the code and test if the project itself works! In the attached video you can see my version of the project running.

    Step 8: Extra: IFTTT

    I you want to do more with the project, you can add IFTTT (If this then that). Here you can add additional services to you smart plant. There is also an app! For example: If you say "Auto water plant" in Google Assistant, then toggle the 'Auto water' switch in adafruit.

    Note: Name the correct values to make it work properly. Good luck!

    Step 9: Troubleshooting

    I got an error while uploading.

    • Is the ESP8266 connected to the computer?
    • Is the correct port selected in the Arduino IDE?
    • Sometimes the ESP8266 does not work properly and the memory failed. Try to reconnect the ESP with the computer.
    • Try to restart the Arduino IDE or the computer. Sometimes the driver is not recognised.

    The code is uploaded properly, but nothing happens.

    • Are the Adafruit username and api key correct?
    • Are the Wifi credentials correct?
    • Are the names of the feeds the same as in the code?
    • Check Adafruit. Does the feeds send or receive data?
    • Check the wiring diagram to see if the wires are connected correctly?