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

About: Engineer, writer and forever student. Passionate to share knowledge of electronics with focus on IoT and robotics.

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

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

(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

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()
{
  Wire.begin();  
  oled.init();                      // Initialize SSD1306 OLED display
  oled.clearDisplay();              // Clear screen
  oled.setTextXY(0,0);              // Set cursor position, start of line 0
  oled.putString("  MJRoBot.org");
  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

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

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);   
    delay(150);
  }
  digitalWrite (soilMoisterVcc, LOW);
  soilMoister = soilMoister/N; 
  Serial.println(soilMoister);
  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

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

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.

LEDs

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.

Buttons

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;
    aplyCmd();
  }

  digiValue = debounce(LAMP_ON_BUTTON);
  if (!digiValue) 
  {
    lampStatus = !lampStatus;
    aplyCmd();
  }
}

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);
    displayData();
  }
  else
      {
        digitalWrite(PUMP_PIN, LOW);
        displayData();
      }
  
  if (lampStatus == 1) 
  {
    digitalWrite(LAMP_PIN, HIGH);
    displayData();
  }
  else
      {
        digitalWrite(LAMP_PIN, LOW);
        displayData();
      }
}

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

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;
    aplyCmd();
  }

  digiValue = debounce(LAMP_ON_BUTTON);
  if (!digiValue) 
  {
    lampStatus = !lampStatus;
    aplyCmd();
  }

  digiValue = debounce(SENSORS_READ_BUTTON);
  if (!digiValue) 
  {
    turnOffOLED = !turnOffOLED;
    if (!turnOffOLED)
    {
      oled.setTextXY(0,0); oled.putString("UPDATING SENSORS");
      getDhtData();
      getSoilMoisterData();
      getSoilTempData();
      oledStart();
      displayData();
    }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

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) 
  {
    turnPumpOn();
  }

  if (airTemp < COLD_TEMP) 
  {
    turnLampOn();
  }
}

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;
  aplyCmd();
  delay (TIME_PUMP_ON*1000);
  pumpStatus = 0;
  aplyCmd();
}

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

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

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:

  1. SENSORS
  2. ACTUATORS / CONTROL
  3. GRAPHICS

"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:

  • SENSORS
    • 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
  • ACTUATORS / CONTROL
    • 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
  • GRAPHICS
    • Data to Show:
      • V10 "Temp Air"
      • V11 "Humidity Air"
      • V12 "Soil Humidity "
      • V13 "Soil Temp"

Step 12: 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 Blynk.run(); 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
  • PUMPs.off()

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();
    PUMPs.on();
    PUMPa.on();
  }
  else
      {
        digitalWrite(PUMP_PIN, LOW);
        if (!turnOffOLED) displayData();
        PUMPs.off();
        PUMPa.off();
      }
  
  if (lampStatus == 1) 
  {
    Blynk.notify("ArduFarmBot2: Warning ==>> Lamp ON");
    digitalWrite(LAMP_PIN, HIGH);
    if (!turnOffOLED) displayData();
    LAMPs.on();
    LAMPa.on();
  }
  else
      {
        digitalWrite(LAMP_PIN, LOW);
        if (!turnOffOLED) displayData();
        LAMPs.off();
        LAMPa.off();
      }
}

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;
    aplyCmd();
  }
}

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

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

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" (*)
(*) You can leave this pin disconnected if you power your module with an external 5V DC Power supply, diferent form the NodeMCU power supply (preferible). To do this, you must take the the jumper out of the 3 pins board and connect VCC to 5V external Power supply and GND to GND external Power suply.

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();
    PUMPs.on();
    PUMPa.on();
  }
  else
      {
        digitalWrite(PUMP_PIN, HIGH); // To be used with Relay module (inverted logic: normally HIGH)
        if (!turnOffOLED) displayData();
        PUMPs.off();
        PUMPa.off();
      }
  
  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();
    LAMPs.on();
    LAMPa.on();
  }
  else
      {
        digitalWrite(LAMP_PIN, HIGH); // To be used with Relay module (inverted logic: normally HIGH)
        if (!turnOffOLED) displayData();
        LAMPs.off();
        LAMPa.off();
      }
}

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

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

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: MJRoBot.org

Saludos from the south of the world!

See you at my next instructable!

Thank you

Marcelo

Step 16: ArduFarmBot, the Book!

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

Amazon_book


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).
book_pages_2.png


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.
book_pages_3


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.
book_pages_4


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 ThingSpeak.com.
book_pages_5


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.
book_pages_6


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


book_pages_7

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!

Marcelo

Microcontroller Contest 2017

Participated in the
Microcontroller Contest 2017

Sensors Contest 2017

Participated in the
Sensors Contest 2017