Skip to content
uPython based plant irrigation system running on an esp8266
Python Makefile
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.

uPython based Plant Irrigation System

Code style: black GitHub Codacy Badge Python saythanks Donate

uPython based plant irrigation system running on an ESP8266


Indoor plants can give fresh life to the room, boost oxygen in an area that can boost productivity and inspire everyone. However, due to the job often needed, they are not only substituted by artificial, counterfeit crops which are tossed into sites sometime in their lives. They do not give as much benefit as true crops. The younger generation is often seen as having a pet because of the responsibilities, and although the plants can make the most of the rooms, they're often forgotten.

Whether it is too hot, cold, dry or humid, it is very essential to regulate water levels reached by the crops. Watering crops constitute the most significant cultural practice and can be the most labor intensive or tedious job.

So, an idea of automagic plant watering system will be effective to only water plants when they need it, this reduces the amount of time required to babysit the plant.

The method employed to monitor the soil moisture level continuously and to decide whether watering is needed or not, and how much water is needed in plant’s soil.

Essentially, the system is designed and programmed to monitor humidity in the soil at specific times. Where the moisture level exceeds the set threshold value, a water pump is triggered and the required quantity of water will be provided until the threshold value is predetermined.

The automagic plant watering system runs on a Wemos D1 esp8266 running Arduino uPython, a capacitive soil moisture sensor reads the moisture content in the soil and uploads the data to ubidots which is a data collection, analysis, and visualization tool. A Slack message is sent to a specific channel when soil moisture reaches a threshold and a water pump notification is sent.

In essence this saves my plant(s) and enables me to concentrate on other boring stuffs.

Circuit Diagram


Parts Checklist


Calibrating the Soil Moisture Sensor

Calibrating the sensor has two parts, the goal is to make sure sensor functions properly:

  • Connect up the soil moisture sensor and dip it in a bowl of water and take the reading.
  • Wipe the sensor, and place it on dry surface and take the reading

These readings should be entered in config.json file.

Setup NodeMCU & Tools

Read the docs


  • Clone the repo and,
  • Plug in the device to your computer

NOTE: The installation assumes that the port name of device is /dev/ttyUSB0 else, modify Makefile with port name [Hint:$ ls /dev/tty*].

  • Run make all : Bootstrap i.e erase, flash, and upload scripts

NOTE: This will install esptool and mpfshell for communicating with ESP chips and for serial connection with MicroPython boards, Erase and flash the chip with firmware esp8266-20190125-v1.10.bin as well as upload the required files to the ESP.

Click here to get the latest uPython firmware.

Setup config

The config file is self-explanatory, fill in the missing parts.

The config goes here.

        "ADC_Pin": 0,
        "Water_Pump_Pin": 12
    "wifi_config": {
        "ssid": "",
        "password": ""
    "MQTT_config": {
        "Host": null,
    "moisture_sensor_cal": {
        "dry": 841,
        "wet": 470,
        "Threshold": 80,
    "water_pump_time": {
        "delay_pump_on": 3
    "slack_auth": {
        "app_id": "",
        "secret_id": "",
        "token": ""
        "token": "",
        "device": ""

Setup Slack

See post on how to send Slack messages using Python.



class Slack:
    def __init__(self, app_id, secret_id, token):
        Get an "incoming-webhook" URL from your slack account.
        self._url = "" % (

    def slack_it(self, msg):
        """ Send a message to a predefined slack channel."""
        headers = {"content-type": "application/json"}
        data = '{"text":"%s"}' % msg
        resp =, data=data, headers=headers)
        return "Message Sent" if resp.status_code == 200 else "Failed to sent message"

Setup Ubidots Data Viz

Who doesn't love viz data, added Ubidots support for Viz



class Ubidots:
    def __init__(self, TOKEN, device_label):
        self.url = "{}?token={}".format(
            device_label, TOKEN

    def post_request(self, payload):
        """Creates the headers for the HTTP requests and Makes the HTTP requests"""
        print("[DEBUG] Uploading Payload: %s" % payload)
        assert isinstance(payload, dict)

        status = 400
        attempts = 0
        while status >= 400 and attempts <= 5:
            req =, json=payload)
            status = req.status_code
            attempts += 1
            print("[DEBUG] Sending data to Ubidots...")

        # Processes results
        if status == 200:
            print("[INFO] Request made properly, Updated Ubidots with %s." % payload)
            return True
                "[ERROR] Could not send data after 5 attempts, please check "
                "your token credentials and internet connection."
            return False


If you like this and want to buy me a cup of coffee, please click the donation button above or click this link

Also you can click if you'd like to saythanks... :) else Star it.



Feel free to fork it or send me PR to improve it.

You can’t perform that action at this time.