Internet of Things - Moisture Sensor with ESP8266


#1

In this little project we will use a cheap soil moisture sensor to monitor when a plant requires more water. This sensor will be connected to an ESP8266 that will check the humidity periodically to alert us via email and blinking a led alarm. The sketch will have some configurable parameters over the Internet, like setting led alarm state (enable/disable, frequency), changing the hysteresis period, or checking the water state.

Required components

  • ESP8266. In this project it is used a NodeMCU, but any other network enabled device can be used by adapting the code a little.
  • Soil Moisture sensor. It is used a cheap one from AliExpress
  • One led for blinking when there is no water.
  • Arduino IDE with thinger.io library installed and support for the ESP8266 board.

This is the moisture sensor used in the project. Is a cheap one from AliExpress.

Wiring

The wiring for this project is so easy. The moisture sensor output (digital) is connected to D1 of the Node MCU board, while the alarm led is connected to D2.

Source Code

#include <SPI.h>
#include <ESP8266WiFi.h>
#include <ThingerWifi.h>

// thinger.io config
#define USER_ID "your_user_id"
#define DEVICE_ID "your_device_id"
#define DEVICE_CREDENTIAL "your_device_credential"
#define ALARM_ENDPOINT "your_alarm_endpoint"

// wifi config
#define WIFI_SSID "your_wifi_ssid"
#define WIFI_WPA2_PASSWORD "your_wifi_password"

// sensor/led pins
#define SENSOR_PIN D1
#define LED_PIN D2

ThingerWifi thing(USER_ID, DEVICE_ID, DEVICE_CREDENTIAL);

typedef enum WaterState{
  WATER,
  START_DETECTING_NO_WATER,
  NO_WATER
};

WaterState waterState = WATER;          // current water state
bool showLedAlarm = true;               // control led alarm on/off
unsigned long ledAlarmInterval = 500;   // led alam blink frequency
unsigned long previousMillis = 0;       // util for hysteresis and blink
unsigned long timeWithoutWater = 0;     // for hysteresis time
unsigned long hysteresisTime = 60000;   // one minute
int ledState = LOW;                     // current led alarm state

void setup() {
  // set pinmode for led alarm and humidity reader
  pinMode(SENSOR_PIN, INPUT);
  pinMode(LED_PIN, OUTPUT);

  // add wifi connection
  thing.add_wifi(WIFI_SSID, WIFI_WPA2_PASSWORD);

  // allow reading plant water/humidity
  thing["water"] >> [](pson& out){ out = !digitalRead(SENSOR_PIN); };

  // allow activating and deactivating led alarm remotelly
  thing["led_alarm"]["show"] << [](pson& in){ 
    if(in.is_empty()) in = showLedAlarm;
    else showLedAlarm = in;
  };

  // allow changing led alarm frequency
  thing["led_alarm"]["freq"] << [](pson& in){ 
    if(in.is_empty()) in = ledAlarmInterval;
    else ledAlarmInterval = in;
  }; 

  // allow changing hysteresisTime remotelly
  thing["hysteresis"] << [](pson& in){ 
    if(in.is_empty()) in = hysteresisTime;
    else hysteresisTime = in;
  };
}

void loop() {
  thing.handle();

  // read water value
  bool water = !digitalRead(SENSOR_PIN);
  
  if(water){
    if(waterState!=WATER){
      digitalWrite(LED_PIN, LOW); // turn off led alarm
      waterState = WATER; // reset water state
    }
  }else{
     unsigned long currentMillis = millis();
     switch(waterState){
        case WATER:
            timeWithoutWater = 0;
            previousMillis = currentMillis;
            waterState = START_DETECTING_NO_WATER;
          break;
        case START_DETECTING_NO_WATER:
          timeWithoutWater += (currentMillis - previousMillis);
          previousMillis = currentMillis;
          // only notify after a hysteresis time to prevent drifts in sensor reading
          if(timeWithoutWater>=hysteresisTime){
            waterState = NO_WATER;
            thing.call_endpoint(ALARM_ENDPOINT);
          }
          break;
        case NO_WATER:
          if(currentMillis - previousMillis > ledAlarmInterval) {
            previousMillis = currentMillis;   
            ledState = ledState == LOW ? HIGH & showLedAlarm : LOW;
            digitalWrite(LED_PIN, ledState);
          }
          break;
     }
  }
}

Some Details

To be continued…


#2

Can you explain EndPoints???
Thanks you very much!!


#3

Yes! I am working on some documentation!! Hope to release it in a few days!


#4

More than a very hot welcome, needed info !!! :smile:

And Thank you for the hard work


#5

Thanks! I will publish some documentation tomorrow for the Arduino client library, which is the way the people is using thinger (it includes some information about how to call endpoints). The next one will be documentation for Linux Clients, server API, console, etc.


#6

thank you very much!
I use Arduino


#7

Here is some starting documentation! At this moment still needs to be completed, but the Arduino section is almost complete. Just require some examples. Let me know what do you think about the docs!

http://docs.thinger.io/arduino/


#8

kindly update your page


#9

What page? Thanks…


#10

actually my device is not able to connect to your platform…is there any step that is missing ?


#11

As soon as I remove al the code exept the thing.handle() from loop(); I am able to receive the resources. As soon I have any snipet inside with other code. It’ stops transmitting the resources.
Any idea?
Kind regards
Jonas


#12

Hello @alvarolb,
This is Devaraj From India, i need to discuss some topics about Thinger.io. Can to please help me to interact with you when you getting Free for your daily routines.

Thank you sir,
With Regards
Devaraj
R&D Engineer
FutureFarms


#13

Greate idea, we are engaged with the building and decoration products and intend to make them more smarter