Introduction: Automatic Gardening System With NodeMCU and Blynk, the "ArduFarmBot 2"

Picture of Automatic Gardening System With NodeMCU and Blynk, the "ArduFarmBot 2"

Some time ago, we published here a similar project: "ArduFarmBot: Controlling a Tomato Home Farm using Arduino and IoT". On this new version, the ArduFarmBot 2, the main specification of the original project will be kept. We will develop a fully automated Gardening System based on NodeMCU ESP8266 and an IoT app, the BLYNK.

Basically, information from a plantation will be captured, temperature and humidity, both of air and soil. Based on those data, the ArduFarmBot 2 will decide the right amount (and when) the plantation should receive heat and water. Also, the project should allow manual intervention of an operator in order to control a water pump and an electric lamp to generate heat for the plantation. The manual intervention must be both, local and remote via Internet.

In short, the system should receive as input:

  • Sensors:
    • Air Temperature
    • Air Relative Humidity
    • Soil Temperature
    • Soil Moisture (humidity)
  • Buttons:
    • Pump ON/OFF
    • Lamp ON/OFF

The system should provide as an output:

  • Actuators:
    • Relay for Pump control
    • Relay for Lamp control
  • Messages
    • Automatic messages must be sent on main events as:
      • Pump ON
      • Lamo On
      • System Offline
  • Data Display
    • All analog and digital data should be available for instant evaluation
  • Data Storage
    • Historic data should be storage remotely

The above block diagram shows the main components of the project.

Step 1: Bill of Material

Step 2: The NodeMCU

Picture of The NodeMCU

The NodeMCU ESP-12E is the integrated version of the popular ESP8266, a Serial to Wi-Fi System On a Chip (SoC) that appeared for the first time in 2013, been released on following year. The ESP8266 was developed by the Shangai-based company Espressif Systems, an IC manufacturer focused on the development of RF chips, particularly Wi-Fi.

There are several modules in the market that use the ESP8266 chip, they are named ESP-NN, where NN is a number 01, 02, ..... 12, sometimes followed by a letter. These modules typically carry the ESP8266 SoC, flash memory, a crystal, and in most cases, an onboard antenna. In the link you can find the full list of ESP8266 based devices found in the market: ESP8266 Module Family. The 2 more important modules are without doubt, the ESP-01 and the ESP-12E.

Here, we will use the ESP-12E Development Board (NodeMCU DevKit 1.0). This development board for the ESP8266 SoC inside the ESP-12E module is out-of-the-box ready for you to connect it to your computer, install USB drivers, and start writing programs that connect to your Wi-Fi network!

Technical Specifications

  • Support STA/AP/STA+AP 3 working modes;
  • Built-in TCP/IP protocol stack, support multiple-channel TCP Client connection (max 5);
  • 0~D8, SD1~SD3: used for GPIO, PWM (D1-D8), IIC, ect; the driven ability can be arrived at 15mA;
  • AD0: one-way 10 bits ADC;
  • Power input: 4.5V~9V(10VMAX), support USB powered and USB debug;
  • Working current: ≈70mA(200mA MAX, continue), standby<200uA;
  • Transmission data rate: 110-460800bps;
  • Support UART/GPIO data communication interface;
  • Support update firmware remotely (OTA);
  • Support Smart Link;
  • Working temperature:-40℃~+125℃;
  • Driven mode: double large-power H bridge driven
  • Weight: 7g.

Step 3: Installing the NodeMCU Board at Arduino IDE

Picture of Installing the NodeMCU Board at Arduino IDE

(If you already have the NodeMCU installed with your IDE, please skip this step)

We will program and use the NodeMCU almost as a regular Arduino, using its IDE. It is important to remember that any new "custom firmware" will replace anything previously stored in the chip's flash memory, including the original firmware loaded at factory where the AT commands were common used. Although we can use the manufacturer's SDK to develop our custom firmware, it is much easier to use the good and old Arduino IDE.

Let's start:

  1. In the Arduino IDE open the PREFERENCES window and enter the URL (marked in red in the above photo) into the Additional Boards Manager URLs field, and select OK.
  2. Select the MENU option Tools → Board → Boards Manager...and scroll down and to locate the option esp8266 by ESP8266 Community which should be the last item on the list, and click INSTALL
  3. Installing The USB Drivers: The USB to Serial UART module included on the board is the Silicon Labs' CP2012, for which we usually need to install the readily available Virtual COM Port (VCP) drivers. In the case of my MAC, the device file created to communicate with the CP2102 has the name /dev/cu.SLAB_USBtoUART. You can find the appropriate drive for your computer at following link: CP210x USB to UART Bridge VCP Drivers
  4. After restarting the Arduino IDE we can now select the board we're using from the menu option Tools → Board → NodeMCU 1.0 (ESP-12E Module). Then, we specify the correct CPU Frequency (Tools → CPU Frequency: "" → 80MHz) and Upload Speed (Tools → Upload Speed: "" → 115200). Finally, the last step is to select the correct option for the Port (Tools → Port → /dev/cu.SLAB_USBtoUART).

At this point we are ready to write our own firmware and upload it, but let's first try one of the examples File → Examples → ESP8266WiFi → WiFiScan. After uploading it, we can open the Serial Monitor window and observe the results. Note that we need to match the baud rate, so check that 115200 is selected from the drop down menu!

Step 4: Installing the OLED

Picture of Installing the OLED

In order to verify the collected data locally, a small OLED Display should be installed. The model used on ArduFarmBot 2 is the OLED 128 x 64 SSD 1306 I2C. Looking the name we know that this display has as main characteristics:

  • 128 pixels at horizontal and 64 pixels at vertical. So if you use 8x8 characters, we will get a "16X8" Display (8 lines of 16 characters each).
  • Its is a I2C display, so we will connect it to the NodeMCU I2C pins, using:
    • SCL ==> D1 (5)
    • SDA ==> D2 (4)

The SSD1306 can be powered with 5V (external) or 3.3V directly from the NodeMCU module. The first option was the chosen one (5V).

Once we have connected the display, let's download and install its library on our Arduino IDE. We will use the ACROBOT library version:

SSD1306 Arduino Library

Once you have re-started the IDE, the library should be already installed. Let's now, upload the bellow sketch to test our OLED display:

*  NodeMCU and OLED display "Hello World" test
*  MJRoBot 15march17

#include <Wire.h>
#include <ACROBOTIC_SSD1306.h>

void setup()
  oled.init();                      // Initialize SSD1306 OLED display
  oled.clearDisplay();              // Clear screen
  oled.setTextXY(0,0);              // Set cursor position, start of line 0
  oled.setTextXY(4,0);              // Set cursor position, start of line 4
  oled.putString("  HELLO, WORLD");

void loop()

Note that when you do not define a different size of text character, the default is 8X8. To define a different one, you can use: oled.setFont(font5x7);

Bellow the code for "Hello World" test:

Step 5: Capturing Air Temperature and Humidity

Picture of Capturing Air Temperature and Humidity

One of most used sensors for capturing weather data is the DHT22 (or it's brother DHT11), a digital relative humidity and temperature sensor. It uses a capacitive humidity sensor and a thermistor to measure the surrounding air, and spits out a digital signal on the data pin (no analog input pins needed).

The sensor should be powered between 3.3V and 5V and will work from -40oC to +80oC with an accuracy of +/- 0.5oC for temperature and +/-2% for relative Humidity. It is also important to have in mind that the its sensing period is in average 2seconds (minimum time between readings). The site of Adafruit provides a lot of information about both, DHT22 and its brother DHT11. For more details, please visit: DHT22/11 Tutorial page . The DHT22 has 4 pins (facing the sensor, pin 1 is the most left) :

  1. VCC (we will connect to 3.3V from NodeMCU);
  2. Data out;
  3. Not connected and
  4. Ground.

Once usually you will use the sensor on distances less than 20m, a 10K resistor should be connected between Data and VCC pins. The Output pin will be connected to NodeMCU pin D3 (see the diagram above). Once the sensor is installed at our module, download the DHT library from Adafruit github repository and install it in your Arduino's Library file. Once you reload your Arduino IDE, the "DHT sensor library" should be installed. Run the DHT Sensor code bellow to verify that everything is running OK:

Step 6: Capturing Soil Moisture Humidity

Picture of Capturing Soil Moisture Humidity

On the previous ArduFarmBot Project we explored how to work with a Soil Moisture Hygrometer to measure soil humidity. There, we have explored a DIY type of sensor, here let's use a electronic one, very common in the market: the YL-69 sensor and LM393 Comparator module soil medium Hygrometer.

The LM393 module has 2 outputs, one digital (D0) that can be set-up using the potentiometer that exist on it and an analog one (A0). This module can be sourced with 3.3V, what is very convenient when working with an NodeMCU. What we will do, is install the LM393 4 pins as bellow:

  • LM393 A0 output to A0 NodeMCU A0 input
  • LM393 VCC to NodeMCU VCC or to NodeMCU GPIO D3*
  • LM393 GND to NodeMCU GND
  • LM393 D0 open

It's important to highlight that the correct is to connect the Sensor VCC to a Digital Pin as output, so the LM393 will be powered only when we need a read. This is important no only to save power, but also to protect the probes from corrosion. With a DYI type os sensor as used on the original ArduFarmBot project, its work fine, but in the case here, the NodeMCU did not worked well the soilMoisterVcc PIN connected. Also I had eventual errors due the power consumption. So, I powered the LM393 direct to VCC (5V), the code does not need to be changed. It is worked fine.

A simple routine can be written to read the analog port:

 * Get Soil Moister Sensor data
void getSoilMoisterData(void)
  soilMoister = 0;
  digitalWrite (soilMoisterVcc, HIGH);
  delay (500);
  int N = 3;
  for(int i = 0; i < N; i++) // read sensor "N" times and get the average
    soilMoister += analogRead(soilMoisterPin);   
  digitalWrite (soilMoisterVcc, LOW);
  soilMoister = soilMoister/N; 
  soilMoister = map(soilMoister, 600, 0, 0, 100); 

Few comments about the above routine:

  • The sensor data is captured 3 times and an average is taken.
  • We use MAP to setup the range in percentage.
    • Making a "short circuit" at the sensor probes (equivalent to "100% of humidity") we got a value of around 0 at ADC output and
    • Leaving it "in the air" " the value displayed at Serial Monitor would be around 600 (5V Powered source).

Bellow a partial test code for this stage of project:

Step 7: Collecting Soil Temperature

Picture of Collecting Soil Temperature

We will use on this project, a waterproofed version of the DS18B20 sensor. It is very useful for remote temperature on wet conditions, as an humid soil. The sensor is isolated and can take measurements until 125oC (Adafrut does not recommend to use it over 100oC due its cable PVC jacket).

The DS18B20 is a digital sensor what makes it good to use even over long distances! These 1-wire digital temperature sensors are fairly precise (±0.5°C over much of the range) and can give up to 12 bits of precision from the onboard digital-to-analog converter. They work great with the NodeMCU using a single digital pin, and you can even connect multiple ones to the same pin, each one has a unique 64-bit ID burned in at the factory to differentiate them.

The sensor works from 3.0 to 5.0V.

The sensor has 3 wires:

  • Black: GND
  • Red: VCC
  • Yellow: 1-Wire Data

Here, you can find the full data: DS18B20 Datasheet

In order to use the DS18B20 properly, two libraries will be necessary:

  1. OneWire (NOTE 1)
  2. DallasTemperature

Install both libraries in your Arduino IDE Library depository.

For testing the sensor, you can use the code "Simple.ino" included on the Library Examples, as shown at the photo. Upload the code in your NodeMCU and monitor the temperature using the Serial Monitor. The above photo shows the expected result. Hold the sensor in your hand, you should see the temperature going to circa of 32/34oC.

NOTE1: The OneWire library MUST be the special one, modified to be used with ESP8266, otherwise you will get an error during compilation. You will find the last version at above link or from the bellow zip file:

Step 8: Completing the HW

Picture of Completing the HW

Following the above diagrams, complete the required system HW installing the buttons and LEDs.

Verify that all sensors (DHT22, DS18B20 and LM393/YL69) as the OLED are powered using the external 5V. The NodeMCU is used only to provide the control signals. Remember that using the NodeMCU 3.3V external pins to provide power can turn the system unstable due the current consumption.


Note that LEDs connected on NodeMCU, are for testing only. They will "simulate", the Pump (Red LED) and the Lamp (Green LED). For the final circuity the Relays will connected to those outputs as described on the next Step.


Based on the readings of sensors, an operator could be also decide manually control the Pump and/or Lamp. For that, three push-buttons will be incorporate to the project:

  • RED: Pump Manual Ctrl
  • GREEN: Lamp manual Ctrl
  • YELLOW: Sensor Read Button (To update sensors, "light on" the OLED and present data (explained at next step)

The buttons will work on a "toggle" mode: If an actuator is "ON", pressing the button will "Turn-OFF" it and vice versa. The button's logic will be "normally closed", what means that NodeMCU Input will be constantly "HIGH". Pressing the button, a "LOW" will be applied at the specific pin (please see the above block diagram).

In order to read the local command, a function readLocalCmd() should be executed. This function will read each button, updating the status of actuators variables (pumpStatus and lampStatus). Note that the function type debounce(pin) is called instead a direct digitalRead (pin). This is to prevent false readings from the pushbutton. If you want to learn more about debouncing, please see this Debouncing Tutorial.

* Read local commands (Pump and Lamp buttons are normally "HIGH"):
void readLocalCmd() 
  boolean digiValue = debounce(PUMP_ON_BUTTON);
  if (!digiValue) 
    pumpStatus = !pumpStatus;

  digiValue = debounce(LAMP_ON_BUTTON);
  if (!digiValue) 
    lampStatus = !lampStatus;

In the case where a button is pressed, another function will be called: aplyCmd(). And as the name says, will apply the correspondent command, turning the actuators ON or OFF:

* Receive Commands and act on actuators
void aplyCmd()
  if (pumpStatus == 1) 
    digitalWrite(PUMP_PIN, HIGH);
        digitalWrite(PUMP_PIN, LOW);
  if (lampStatus == 1) 
    digitalWrite(LAMP_PIN, HIGH);
        digitalWrite(LAMP_PIN, LOW);

Code considerations

When we think about the 4 big "group of tasks" so far:

  1. Read sensors
  2. Read buttons (local Command)
  3. Act on Pump/Lamp
  4. Display all Data

We will realize that the the timing when we should perform such tasks are not necessarily the same. For example, to read the Temperature and Humidity data from DHT 22, we will need to wait at least 2 seconds between mesure, but minutes are OK. For Soil Moisture sensor, as less measurements we do, better (due probe corrosion generate by electrolise) and last but not least, daylight will not vary instantly. But when we think about the actuators, as soon we press a button, we would like (and possibly need) a quick reaction.

So, we must use here a "timer" to correctly control the correct timing of those tasks. We could do this using the millis(), as we did on the original ArdFarmBot Project, but let's introduce another great tool here:

SimpleTimer.h (follow the instructions on this link to install the Library:SimpleTimer)

The library must be included on the main body of your code, following by a timer definition:

SimpleTimer timer;

Next, define the timers:

  timer.setInterval(1000L, readLocalCmd);       // Read buttons at every 1 second
  timer.setInterval(2000L, getSoilTempData);    // Read Soil Temp at every 2 seconds
  timer.setInterval(2000L, getDhtData);         // Read DHT Sensor at every 2 seconds
  timer.setInterval(10000, getSoilMoisterData); // Read Soil Humidity at every 10 seconds
  timer.setInterval(10000, displayData);        // Display Data at OLED at every 10 seconds

Step 9: The Local Control Station - Concluding the Code

Picture of The Local Control Station - Concluding the Code

Introducing the Sensor Read Button (The yellow one!)

As we could see at last step, we will need wait long cycles between Soil Moisture sensor measurements. It is Ok, for our automatic needs, but for manual operation we will not want to "wait" 10, 15 or more seconds (or even minutes in real case) for a sensor measurements. Also in real world, make no sense keep the OLED display "ON" all the time. So, the default will be "dark" or "OFF".

So, we will introduce a 3rd push button to our project that will display the actual sensor data any time that we want, independent of the the timing of the automatic readings. Also, we will use this same button to display data at OLED when the sensors are updated. Bellow the changed readLocaCmd() function:

* Read local commands (Pump, Lamp and Sensor buttons are normally "HIGH"):
void readLocalCmd() 
  boolean digiValue = debounce(PUMP_ON_BUTTON);
  if (!digiValue) 
    pumpStatus = !pumpStatus;

  digiValue = debounce(LAMP_ON_BUTTON);
  if (!digiValue) 
    lampStatus = !lampStatus;

  digiValue = debounce(SENSORS_READ_BUTTON);
  if (!digiValue) 
    turnOffOLED = !turnOffOLED;
    if (!turnOffOLED)
      oled.setTextXY(0,0); oled.putString("UPDATING SENSORS");
    }else oled.clearDisplay(); //turn off OLED

At this point, all the HW is completed (using LEDs as actuators) and we have all SW parts to be put together.

The video shows the ArduFarmBot 2, operation on a Local and Manual mode:

Bellow we can download the complete code for testing our "local Station" on its Manual mode only, or go direct to my GitHub for update versions:

Step 10: Making Our Gardening System Fully Automatic

Picture of Making Our Gardening System Fully Automatic

At this point we have all HW in place and as saw at last step, the station can be controlled by a local operator via the buttons. What is missing is the "logic" allowing our system to really perform the task of irrigating the plantation automatically! We need to include some "brain" to our ArduFarmBot project.

Let's define the initial range where the Sensors would work. Those values should be changed later using practical values to be founded on the real plantation:

Soil Moisture:

  • "WET": Over 88% (no watering at all)
  • "Target Humid": Between 66% and 88% (Where we want to work) and
  • "DRY": Bellow 66% (need turn on the pump to increase the humidity)

Air Temperature:

  • COLD: Bellow 12oC (Turn-On the Light/Heat*)
  • Optimum: between 12oC and 22oC
  • HOT: Over 22oC (Do not Turn-On the Light/Heat)

You must have in mind that each type of seeds has a optimum range of temperature where it will grow faster. For example for Tomatos the minimum time for seeds to germinate will be 6 days on temperatures between 20 and 25 oC, going up for temperatures lower or higher than that (more than 43 days for temperature less than 10oC and 9 days for temperature over 35oC

You can check more information about this relationship (Temp/Germination days) here: The effect of soil temperature on seeds germination

Having this 4 reading (Air Temperature, Air Humidity, Soil Moisture and Soil Temperature), we can built a complex matrix defining how we want that our automatic Gardening System works. On the Step 7 of ArduFarmBot - Part 2: "Remote Station" an IoT Implementation, a complex Sensor-matrix approach was developed in deep.

So, let's define the bellow parameters to be used on our code:

/* Automatic Control Parameters Definition */
#define DRY_SOIL      66
#define WET_SOIL      85
#define COLD_TEMP     12
#define HOT_TEMP      22
#define TIME_PUMP_ON  15
#define TIME_LAMP_ON  15

TIME_PUMP_ON and TIME_LAMP_ON are the time in seconds that both pump and lamp must be ON during automatic operation.

Based on the above parameters, let's think about some very simple assumptions to be implemented on the code:

  1. If it's DRY ==> PUMP = ON
  2. If it's COLD ==> LAMP = ON

In this project we will keep it simple and will not explore all possible combinations and the role of Air humidity or soil temperature on the equation.

The Code:

Let's create a new function that based on sensors reading, will deal automatically with actuators, turning on/off the Pump and Lamp: autoControlPlantation(). This function as shown bellow, will be called on every Cycle of Sensors readings:

* Automatically Control the Plantation based on sensors reading
void autoControlPlantation(void)
  if (soilMoister < DRY_SOIL) 

  if (airTemp < COLD_TEMP) 

The function will have 2 main tasks:

  • Pump Control
  • Lamp Control

Bellow, both functions:

* Turn Pump On for a certain amount of time
void turnPumpOn()
  pumpStatus = 1;
  delay (TIME_PUMP_ON*1000);
  pumpStatus = 0;

* Turn Lamp On for a certain amount of time 
void turnLampOn()
  lampStatus = 1;
  delay (TIME_LAMP_ON*1000);
  lampStatus = 0;

At last, but not least, let's use the Sensor Read button ("yellow one") to not only pause the program for a certain time during the start-up but also to display the most important initial parameters, as shown at above photo.

At this point the ArduFarmBot is fully functional in terms of HW and SW.

The video shows the ArduFarmBot 2, operation on a Local and Automatic mode:

Bellow the ArduFarmBot2 code in its version of "Local and Automatic control". You can download them here or go to my GitHub for update versions:

Step 11: Creating the BLYNK App

Picture of Creating the BLYNK App

It is really very easy to built IoT projects using BLYNK. The first you need is to have the BLINK App installed on you phone its Library on the Arduino IDE. If you do not have them yet, please follow the bellow steps:

  1. Download BLYNK app for Apple Iphone or Google Android
  2. Install BLYNK Library for Arduino. Note that you will download the zip file (There are 5 files there that you must manually install in your Arduino Library).
  3. Once the Arduino IDE is reloaded, you should be OK to start using BLINK on your IoT project.

Now, let's open our app at the SmartPhone:

  1. Open Blynk app.Tap on "Create New Project" screen
  2. Give a name for your project (For example "ArduFarmBot 2")
  3. Select the appropriated Hardware Model: "NodeMCU"
  4. Take note from Authorization Token (you can e-mail it to you to ease copy&past on your code)
  5. Press "OK". A Blank screen with dots will appear.
  6. Tap the Screen to open the "Widget Box"

OK, let's take a moment and think about our ArduFarmBot 2 Blynk App and define what will be the Widgets to be installed. Revisiting the general specification at introduction, we can summarize that our app we be needed for:

  1. Read all Sensors and verify the actuators status
  2. Take remote actions, "turning on/off" Pump and Lamp
  3. Sending messages when the System is "off-line" and/or an actuator is ON
  4. Record the general sensors data

In order to organize things, let's split the above "tasks" in 3 tabs:


"Tabs" will be the first Widget to be installed. Enter on it and define the above "Tab names"

Next, go to each Tab and install the Widgets as described bellow:

    • Gauge: "Temp Air [oC]" Blue; input: V10 0 to 50; frequency: 5 sec
    • Gauge: "Humidity Air [%]" Green; input: V11 0 to 100; frequency: 5 sec
    • Gauge: "Soil Humidity [%]" Red; input: V12 0 to 100; frequency: 5 sec
    • Gauge: "Soil Temperature[oC]" Yellow; input: V13 -10 to 50; frequency: 5 sec
    • LED: "PUMP" Red; V0
    • LED: "LAMP" Green; V1
    • Button: "PUMP" Red; output: V3 0 to 1; mode: Switch; label: on: ACT, off: OK
    • Button: "LAMP" Green; output: V4 0 to 1; mode: Switch; label: on: ACT, off: OK
    • LED: "PUMP" Red; V0
    • LED: "LAMP" Green; V6
    • Notifications: Notify When HW goes offline: ON
    • Data to Show:
      • V10 "Temp Air"
      • V11 "Humidity Air"
      • V12 "Soil Humidity "
      • V13 "Soil Temp"

Step 12: Changing Code to Introduce Blynk Funcionalities

Picture of Changing Code to Introduce Blynk Funcionalities

To run run a Blynk app together with your code, you will need:

  1. Include the BlynkSimpleEsp8266 library at beginning of your code
  2. During Setup(), initiate Blynk credentials: Blynk.begin(auth, ssid, pass);
  3. Define a timing to send local data to Blynk server: timer.setInterval(5000L, sendUptime);
  4. Call the function; at loop()
  5. Create the function sendUtime(); where you will introduce the sensor data to be sent to Blynk Server: Blynk.virtualWrite(VirtualPin, sensor data);

The code must include now the "StationCredentials.h":

char auth[] = "YOUR PROJECT TOKEN"; // Blynk project: "ArduFarmBot2"
char ssid[] = "YOUR LOCAL WIFI NAME";
char pass[] = "YOUR WIFI PASSWORD";

Other considerations:

To use the "Virtual LED" at Blynk app, you must define them at beginning of your cose as bellow:

WidgetLED PUMPs(V0);  // Echo signal to Sensors Tab at Blynk App
WidgetLED PUMPa(V5); // Echo signal to Actuators Tab at Blynk App
WidgetLED LAMPs(V1);  // Echo signal to Sensors Tab at Blynk App
WidgetLED LAMPa(V6); // Echo signal to Actuators Tab at Blynk App

To "turn on" or "turn off" the the PUMPs LED that is connected with virtual PIN V0, for example, call respectively the functions:

  • PUMPs.on() or

We will include dos commands at applyCmd() function, so the LEDs on Blynk app will mimic the real LEDs of our project. We should also include the command: Blynk.notify("Message to be sent"); on the same applyCmd() function, one for the Pump and another for the Lamp. Bellow, the new function:

* Receive Commands and act on actuators
void aplyCmd()
  if (pumpStatus == 1) 
    Blynk.notify("ArduFarmBot2: Warning ==>> Pump ON"); 
    digitalWrite(PUMP_PIN, HIGH);
    if (!turnOffOLED) displayData();
        digitalWrite(PUMP_PIN, LOW);
        if (!turnOffOLED) displayData();;;
  if (lampStatus == 1) 
    Blynk.notify("ArduFarmBot2: Warning ==>> Lamp ON");
    digitalWrite(LAMP_PIN, HIGH);
    if (!turnOffOLED) displayData();
        digitalWrite(LAMP_PIN, LOW);
        if (!turnOffOLED) displayData();;;

To receive a command from a Blynk button, a function BLYNK_WRITE() must be defined outside a function, loop() or setup(). For that, the bellow code was created, one for each Blynk Button (PUMP and LAMP):

* Read remote commands 
BLYNK_WRITE(3) // Pump remote control
  int i=param.asInt();
  if (i==1) 
    pumpStatus = !pumpStatus;

BLYNK_WRITE(4) // Lamp remote control
  int i=param.asInt();
  if (i==1) 
    lampStatus = !lampStatus;

Bellow, the video shows the automatic operation of ArduFarmBot 2, now including Blynk:

Bellow the ArduFarmBot2 code in its version of "Remote and Automatic control", using Blynk. You can download them here or go to my GitHub for update versions:

Step 13: Relays As Actuators

Picture of Relays As Actuators

As discussed at introduction, our final goal here is to take care of a plantation. With the data provide by sensors, we will know the air and soil temperature, air relative humidity and the most important how "dry" is the soil. With those data in hand, our program should calculate if would be necessary to irrigate the plantation, turning on a water pump or to turn on an electric lamp to provide the appropriate heat to the crop. For that, we will use a small dual 5V Relay Module for Pump and Lamp activation. The Relay Module diagram circuit can be seen above.

Looking at the diagram, you must connect (depending of your Relay Module, labels could be different):

  • Power Supply 5V ==> (4) "Vcc"
  • NodeMCU D6 ==> (3) "IN1" (Pump)
  • NodeMCU D7 ==> (2) "IN2" (Lamp)
  • NodeMCU GND ==> (1) "GND"

Usually you will see as output, 3 Pins for each relay: "NO" ("Normal Open"), "Ref" or "COM" ("Reference" or "Common") and "NC" ("Normal Closed"). We will use the NO and COM for each Relay. On the above example, the "COM" is the terminal to connect to external Positive Pin of the 5V Power Supply (in the case of the Pump) or the 220VAC for the Lamp. The "NO" will be connected to Pump (or Lamp).

In the case of the Relay chosen and confirming on the above diagram, normally the IN1 and IN2 must be at HIGH and its activation will happen with a LOW level (less than 2V). With a LOW level from NodeMCU, the current will flow from VCC to NodeMCU Pin D6, activating the optocoupler input. The Relay output will close and the NO will close, turning ON the Pump on the example.

Regarding the SW, we must "invert"the logic. The Output Pins D6 and D7 should be normally HIGH. So at setup(), change their initial condition:

  digitalWrite(PUMP_PIN, HIGH); // To be used with Relay module (inverted logic: normally HIGH)
  digitalWrite(LAMP_PIN, HIGH); // To be used with Relay module (inverted logic: normally HIGH)

And also invert the conditions at applyCmd() function:

* Receive Commands and act on actuators
void aplyCmd()
  if (pumpStatus == 1) 
    Blynk.notify("ArduFarmBot2: Warning ==>> Pump ON"); 
    digitalWrite(PUMP_PIN, LOW); // To be used with Relay module (inverted logic: activate with LOW)
    if (!turnOffOLED) displayData();
        digitalWrite(PUMP_PIN, HIGH); // To be used with Relay module (inverted logic: normally HIGH)
        if (!turnOffOLED) displayData();;;
  if (lampStatus == 1) 
    Blynk.notify("ArduFarmBot2: Warning ==>> Lamp ON");
    digitalWrite(LAMP_PIN, LOW); // To be used with Relay module (inverted logic: activate with LOW)
    if (!turnOffOLED) displayData();
        digitalWrite(LAMP_PIN, HIGH); // To be used with Relay module (inverted logic: normally HIGH)
        if (!turnOffOLED) displayData();;;

The ArduFarmBot2 code in its version of "Remote and Automatic control", using Blynk and real Relay (activation LOW) can be download from my Github: ArduFarmBot2_Ext_Auto_Ctrl__V4_0

Step 14: Testing With a Real Pump

Picture of Testing With a Real Pump

The Pump chosen is a Mini DC Water Pump. You can install it submerse in water or "inline". We have used the second one. Follow the photos and connect the Pump at yours tank's button. After, connect the one of the Pump's wire to Relay IN1 and the other one to the External 5V Power Supply Pin (+). Take the Power Supply Pin (-) and connect it to the Relay COM1.

The bellow movie shows a manual local and remote operation of the ArduFarmBot 2

And, finally the bellow video shows its automatic operation:

Step 15: Conclusion

Picture of Conclusion

As always, I hope this project can help others find their way in the exciting world of electronics and IoT!

For updated files, please see the ArduFarmBot2 GitHub depository

For more projects, please visit my blog:

Saludos from the south of the world!

See you at my next instructable!

Thank you


Step 16: ArduFarmBot, the Book!

Picture of ArduFarmBot, the Book!

"ArduFarmBot, the book" is also at! You can get it, by clicking the bellow banner:


The book uses the electronic controller ArduFarmBot as a basis for teaching how to work in both HW and SW, with: a) LCD and OLED type displays; b) LEDs and buttons; c) Activation of pumps and lamps via relays and d) Sensors such as: DHT22 (temperature and relative air humidity), DS18B20 (soil temperature), YL69 (soil moisture) and LDR (luminosity).

All key stages of the project are documented in detail through explanatory texts, block diagrams, high-resolution color photos, electrical diagrams using Fritzing application, complete codes stored in GitHub and YouTube videos.

Two versions of the electronic controller ArduFarmBot are developed in detail in the book. From capture of data coming from a garden, such as air and soil temperature, relative humidity, soil moisture and luminosity, the ArduFarmBot helps to control when a crop should receive heat and water. Control will happen automatically, locally and remote via internet The book is divided into 3 parts. In the first part, the Arduino Nano is the starting point for development of a local version of ArduFarmBot, that can be controlled both, manually and automatically.

In the second part, the book dives into automation design, introducing remote operation through the creation of a webpage. The ESP8266-01 is used for Wi-Fi connection, sending data to an important web service in the field of IoT, the

In the third part, a second version of ArduFarmBot is developed, introducing the NodeMCU ESP8266-12E, a powerful and versatile IoT device, which replaces both the Arduino Nano and the ESP8266-01, used in the earlier parts of the book.

In this last part of the book, a new service platform of the IoT universe, the Blynk, is also explored.


Download the book, give it a review and please use the message board here to give us any comment, suggestion or critic!

Thanks a lot

Saludos desde el sur del mundo!



ivan_lim (author)2017-09-06

Hi Mjrovai,

Thanks for sharing such a Great project! Built one but was unable to get the 393 but instead used the YL-69, i keep getting negative soil humidity and the pump keeps turning on. How can i correct this?


mjrovai (author)ivan_lim2017-09-06

The YL-69 alone can be used as a soil moisture sensor, but you must add a resistor on it, so a voltage divider will be the input of Analog Pin. You must do some tests to define the values to be entered in the Map part of your code.

20_akhiha (author)2017-09-06

i am unable to set the code correctly...can anyone help me by uplaoding the entire code at one place....

thank you in advance.

langtupt (author)2017-09-01

Dear Mjrovai,

Thank your for share but could you please help check the soil sensor the values is 40% although the soil is wet 100%

kon99 made it! (author)2017-08-05

Hello, I have a problem with the test. The value is -126.9. What is the reason? Thanks.

MukeshS56 (author)2017-06-16

Hi Mjrovai,

Thanks for such a useful and beautifully written tutorial. Its simply awesome. Starting from the design, versatility and then detailed description every aspect is amazing. Not many tutorials there with such good description and focus over minute details supported by images and diagrams.

Thanks again.

mjrovai (author)MukeshS562017-06-17

Thank you! ;-)
That's the idea! I have learning from doing it, and I usually write the tutorials in the exactelly order that I build them. My goal is to share what I learn! Your comment is a nice and important one to keep me on this track! Salut from the south of the world! ;-)

msameer39 (author)2017-06-06

Awesome as always,

Marcelo do you have any solution to get rid of blynk energy. I just uninstalled the application when they start asking for energy.

jmenzer (author)2017-05-21

Thank you for a great project. I have started to assembly the hardware, and I apologize but I am very new to Arduino. Where do I include the station defines.h file? I can't seem to compile the code "fatal error" because this library can not be found.

Sorry if this is a very basic question.

Thank you for any help

mjrovai (author)jmenzer2017-05-21

Hi, I am working with multiple files at Arduino IDE.

1. You must download all files from the folder (There are 6 flies on there):

2. Note that your folder must have the same name as the main .ino file:


3. In your computer, when you click on the above file (inside the folder with same name and including all other 5 files), the Arduino IDE will open and you will see a similar situation as the photo attached (Note that will be 6 "Tabs", one for each file). One of them is the "defines.h".

Please let me know if you got it.


jmenzer (author)mjrovai2017-05-21

Thank you so much of response.

Yes, that worked. I have so much to learn about programming Arduino, and I am really grateful that folks like you are willing to go out of your way and help. I purchased a copy of your book today as well.

mjrovai (author)jmenzer2017-05-23

I am very happy to help! ;-)

I love Arduino, NodeMCU. RPi. Those are great devices! I hope you like the book. And if you like and can give it a review at Amazon would be great!

Thanks a lot!


ErickB46 made it! (author)2017-04-16

Great project I am working in this project for the school . However i am in the step number 9 . At the fisrt sight the projects is ok however when i push the button yellow the system lunch a error and the system restarts. I look the next error:

ets Jan 8 2013,rst cause:2, boot mode:(1,6)

ets Jan 8 2013,rst cause:4, boot mode:(1,6)

wdt reset

Other thing that i can see is that i cant see the messages in the monitor , only i see stranger digits. Tanks for your help.

mjrovai (author)ErickB462017-04-17

Thanks for your words! ;-)

Seems like your NodeMCU is sourcing more current that he can get from your power supply. When it happens it resets.

Try have a 2A 5V DC power supply sourcing your circuit. Check if all connections are correct. Better all devices be sourced by external power supply.

If does not work, disconnect the devices one by one and check again.

ErickB46 (author)mjrovai2017-05-02

I check all the circuit, but i have the same result. The system resets . I dont know why, if I put the power supply . There is a form to connect the module with other configuration.

mjrovai (author)ErickB462017-05-03

is it possible for you to check it with another NodeMCU? When I bought mine, I received 3 units and one of them never worked well.

ErickB46 (author)mjrovai2017-05-03

Maybe, but how i can connect the nodemcu to the power supply. Is correct connect all the grand pins ? and the pin of 5v? . I connect all the protoboard with the 5v and 2A. I dont know if can you undestand.

mjrovai (author)ErickB462017-05-03

During development phase, you will be powering the NodeMCU thru the USB cable connected to your computer and the NodeMCU Vin pin should not be connected to breadboard power raid. The external 5V will be connected to breadboard power raid and will supply 5V to all devices, except to NodeMCU. When you will use the ArduFarmBot on field (after the Sw is loaded), the only power source will be the external 5V power supply and you should connect nodeMCU Vin to breadboard power raid as showed on electrical diagram (the red cable).

Note that the NodeMCU 5V pin should be DISCONNECTED all time. We will not use it.

mjrovai (author)mjrovai2017-05-03

sorry, the NodeMCU 3.3V pins must be all DISCONNETED

Spaceshark (author)2017-03-10

Great Instructable! I'm starting to work on one of these for a garden at my school. The school's wifi requires the ssid along with a username and password. How do I go about connecting the NodeMcu in this special case? Is there extra code I need to add in? Is this possible?

mjrovai (author)Spaceshark2017-03-11

Thanks a lot. I am happy that you liked my project.
I am not a COMM specialist, but I made a search on several forums and seems that NodeMCU ESP8266 does not support "WPA & WPA2 Enterprise" security. Maybe there are some ways to overcome it, but I really do not know. Sorry.

Techovator0819 (author)2017-02-18

Absolutely fantastic

mjrovai (author)Techovator08192017-02-23

Super! Thanks, my Friend! ;-)

MartinF108 (author)2017-02-23

The best!!!

mjrovai (author)MartinF1082017-02-23

Thanks a lot! ;-)

Techovator0819 (author)2017-02-18

absolutely fantastic

arkhipenko (author)2017-02-17

Cheers! Nicely done. Seems we share the same passion for watering plants automatically :)))

Two observations, If I may:

1. The issue with NodeMCU "not liking" when your soil probe was powered via GPIO pin is the same I hit in my project with that board. The reason is some of the pins are driving the boot process, which limits their usability. If you play with assigning different pins, you should be able to go back to your original idea, because...

2. if you keep the soil probe constantly under power, the foil will be gone in a matter of couple of weeks. It erodes quickly, that's why in my project I finally gave up and used nails...

Otherwise I am sure this was a lot of fun to work on. (Spoken from experience)

mjrovai made it! (author)arkhipenko2017-02-18

Thanks a lot! You have great projects, I love them! ;-)

And thanks for your observations. The 1. is great, I did not realized it! I will test power the probe on another pin.

I did several tests with different sensors and same as you, I prefer my homemade one! On my first project, I also tried a capacitive version of the sensor. It is more expensive, but does not have the corrosion problem.

Bellow, you can see my tomato plantation, using my DYI sensor

bohicarico (author)2017-02-16

I like your methodical approach to this project. Nice job!

mjrovai (author)bohicarico2017-02-16

Thanks a lot! ;-)

About This Instructable




Bio: Engineer, writer and forever student. Passionate to share knowledge of electronics with focus on IoT and robotics.
More by mjrovai:ESP32 and OLED Display: Internet Clock - DHT22 IOT Made Simple: Playing With the ESP32 on Arduino IDEIoT Made Simple: Monitoring Multiple Sensors
Add instructable to: