IoT Based Soil Fertility Analyzer Using NPK Sensor

This IoT based project uses an NPK sensor to measure the soil nutrient available in the soil and then displays it in an OLED as well as sending the read soil values to Blynk IoT dashboard as shown above. The project is very important to agriculture and gardening practices.

IoT NPK Fertility Analyzer – The Components Required

The following are the materials used for this IoT NPK project tutorial.

  1. Soil NPK Sensor
  2. Arduino Nano
  3. ESP8266-01 (ESP-1)
  4. 12V Power Supply Module
  5. OLED
  6. Max485 Module
  7. Jumper Wires
  8. Button Switch
  9. DC-DC Buck converter
  10. A pushbutton
  11. Some PCB socket
  12. Male and Female Socket Wires
  13. LED (green and red LED)
IoT Based NPK Sensor Project
IoT Based NPK Sensor Project – Assembling the components

The IoT based NPK fertilizer analyzer project was first assembled using the breadboard, as shown above. The breadboarding phase allowed for the testing of of the project tutorial, giving room for error making and modification. The setting up and connection of the components on the breadboard is done following the schematic diagram shown below.

IoT Based NPK Sensor Project – Schematic Diagram

Schematic diagram of IoT Based NPK sensor Project
Schematic diagram of IoT Based NPK sensor Project

Explanation of the Schematic Diagram

The pictorial schematic diagram shown above, has exclusion of the power connection. We only focused the connection of the 5V coming out from the DC-DC buck converter. The 12V power supply is fed into the PCB socket (shown in green).

IoT NPK Project

The ESP8266-01 (ESP-01) module is connected to the Arduino Nano board using serial communication since the Blynk IoT platform to be used here doesn’t work well with the I2C communication. Hence, the OLED doesn’t work with the libraries of Blynk when using the both of them on the same Arduino board.

To solve this problem, we used the ESP-01 as a microcontroller instead of a module, then we used serial communication protocol to talk to it through the Arduino Nano. The Arduino Nano would do the job of taking the readings of the soil fertility through the NPK sensor, displaying these sensor readings on the OLED module and sending it through serial to the ESP-01, who would in turn send it to the Blynk dashboard.

The MAX485 module helps us maintain a RS485 to TTL communication between the NPK sensor and the Arduino. The MAX485 module uses the 5V logic from the Arduino to power itself and it is connected as shown below.

Powering the Circuitry

IoT NPK sensor

The system itself uses 12V DC power from a 12V adapter. The adapter is first stripped of its casing and made in such a way that it can fit into a 3×6″ box. The adapter 12V DC output is connected to the 12V input of the NPK power rails and also to the input of the DC-DC buck converter. This is bucked down to 5V for the Arduino Nano board and the MAX485 module. The AC input to the adapter is connected to the AC load point through power plug. This was made in such a way that is can be detachable.

IoT NPK sensor

Programing the IoT NPK Project Design

The programming of this project was using Arduino IDE. The source code is found in the link here. You can also copy the one in the code snippet and paste it into your Arduino IDE and run it. Since the Arduino Nano does the sensor reading and calculation and displays these readings on the OLED the same time it sends the said readings to the ESP-01 snesor who would send it to the IoT Blynk platform.

Arduino Source Code – The Transmitter Side

#include <SoftwareSerial.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET     4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
define RE 8
#define DE 7
  
//const byte code[]= {0x01, 0x03, 0x00, 0x1e, 0x00, 0x03, 0x65, 0xCD};
const byte nitro[] = {0x01,0x03, 0x00, 0x1e, 0x00, 0x01, 0xe4, 0x0c};
const byte phos[] = {0x01,0x03, 0x00, 0x1f, 0x00, 0x01, 0xb5, 0xcc};
const byte pota[] = {0x01,0x03, 0x00, 0x20, 0x00, 0x01, 0x85, 0xc0};

#define buttonPush 7
#define sensorReadPin 8
 
int readButton, readSensor;
int count = 0;
int countDown = 5; 
int a, i = 0;

int n, p, k;
String greeting = "hello";

byte values[11];
SoftwareSerial mod(2,3);
void setup() {
  Serial.begin(9600);
  mod.begin(9600);
  pinMode(RE, OUTPUT);
  pinMode(DE, OUTPUT);
   
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C); //initialize with the I2C addr 0x3C (128x64)
  delay(500);
  display.clearDisplay();
  display.setCursor(25, 15);
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.println(" WELCOME SMART");
  display.setCursor(15, 35);
  display.setTextSize(1);
  display.print("SOIL NPK DETECTION");
  display.setCursor(45, 55);
  display.setTextSize(1);
  display.print("PROJECT");
  display.display();
  delay(3000);
}
  
void loop() {
 byte val1,val2,val3;
 val1 = nitrogen();
 delay(250);
 val2 = phosphorous();
 delay(250);
 val3 = potassium();
 delay(250);
  
  
 Serial.print("Nitrogen: ");
 Serial.print(val1);
 Serial.println(" mg/kg");
 Serial.print("Phosphorous: ");
 Serial.print(val2);
 Serial.println(" mg/kg");
 Serial.print("Potassium: ");
 Serial.print(val3);
 Serial.println(" mg/kg");
 delay(2000);
 
 display.clearDisplay();
  
 
 display.setTextSize(2);
 display.setCursor(0, 5);
 display.print("N: ");
 display.print(val1);
 display.setTextSize(1);
 display.print(" mg/kg");
 
 display.setTextSize(2);
 display.setCursor(0, 25);
 display.print("P: ");
 display.print(val2);
 display.setTextSize(1);
 display.print(" mg/kg");
 
 display.setTextSize(2);
 display.setCursor(0, 45);
 display.print("K: ");
 display.print(val3);
 display.setTextSize(1);
 display.print(" mg/kg");
 
 display.display();

Explanation of Arduino Sketch

The transmitter Arduino sketch allows us to use the serial communication protocol to communicate with the MAX485 module to read the NPK sensor. This shows where the Transmitter and receiver pins of the MAX485 module is connected on the Arduino Nano board. The sketch uses 5 libraries to make the whole setup function perfectly for the Arduino Nano side.

In the setup() function, we enabled the OLED function and displayed a welcome message and after a period of 3 seconds we cleared the screen. The program then checks to see of the NPK sensor is connected. And if it was connected, it will display that it was connected hence proceed to take the sensor readings of the soil levels for Nitrogen, Phosphorus and Potassium. This is printed out on the serial monitor and also sent to the ESP-01 MCU since the Arduino Nano baords communicate to the ESP-01 via hardware serial communication and this is enabled the moment we enabled serial communication in the setup().

However, The method of sending this type of data required a special approach so that it can be parsed easily by the receiving end. We had to use special alphabets to concatenate the strings being sent to the serial buffer.

The Arduino Code – The Receiver Side (ESP-01 MCU)

#include <SoftwareSerial.h>

SoftwareSerial esp(4,5);

const byte numChars = 32;
char receivedChars[numChars];
char tempChars[numChars];        // temporary array for use when parsing
boolean newData = false;

// variables to hold the parsed data
char messageFromPC[numChars] = {0};
int n, p, k = 0;

static boolean recvInProgress = false;
static byte ndx = 0;
char startMarker = '<';
char endMarker = '>';
char rc;

void recvData(){
   
 }
 

void setup(){
  // Debug console
  Serial.begin(115200);
  esp.begin(115200);

  }

void loop(){
recvWithStartEndMarkers();
    if (newData == true) {
     strcpy(tempChars, receivedChars);
     // this temporary copy is necessary to protect the original data
      //   because strtok() used in parseData() replaces the commas with \0
     parseData();
     showParsedData();
     newData = false;
    }

}

void recvWithStartEndMarkers() {
    while (esp.available() > 0 && newData == false) {
        rc = esp.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}

//============

void parseData() {      // split the data into its parts

    char * strtokIndx; // this is used by strtok() as an index

    strtokIndx = strtok(tempChars,",");      // get the first part - the string
    strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC

    strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
    n = atoi(strtokIndx);
    
    strtokIndx = strtok(NULL, ",");
    p = atoi(strtokIndx);     // convert this part to a float

    strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
    k = atoi(strtokIndx);     // convert this part to an integer
    Serial.print(" N: ");
    Serial.print(n);
    Serial.print(" P: ");
    Serial.print(p);
    Serial.print(" K: ");
    Serial.println(k);
}

//============

void showParsedData() {
    Serial.print(" N: ");
    Serial.print(n);
    Serial.print(" P: ");
    Serial.print(p);
    Serial.print(" K: ");
    Serial.println(k);

}

Explanation of Arduino Sketch (Receiver Side)

This source code explains how we used software serial comm. to received the sent data strings from the Arduino Nano. We used the logic above to parse the data sent and then sent this data to the Blynk IoT Dashboard. This is a smart and cost effective way to solve the Blynk and OLED libraries issues. Since, the both of them can’t run together on the same ARDUINO UNO AND NANO BOARDS.

Setting up the Blynk IoT Platform

You can check out any of these previous blog links below on how to set up the Blynk dashboard. If you still can’t get it done. Kindly leave a comment below.

Testing the Design

IoT NPK sensor using Blynk and Arduino
Testing IoT NPK sensor using Blynk and Arduino

When the coupling and tidying up was completed, we used a white wrapper to cover the top enclosure making a bit flashy. The OLED screen is made to show on the top cover. There is a pushbutton on the side to reset the microcontroller to take new readings on insertion of the sensor probe into a new soil sample. And the sensor connection is made detachable to make it plug-N-play.

IoT based NPK project
IoT based NPK project

The ESP-01 MCU would take these readings to the Blynk cloud platform and display them on the dashboard as shown above. The readings will be updated the moment the sensor senses new soil parameters.

Kindly note that the NPK sensor can be quite frustrating to use. Kindly get an original copy for this project to work. IF possible, get the type that has a UART USB reader that can be first tested using a PC program before using it with the MAX485 module.

Conclusion

The project tutorial teaches how to use Soil NPK sensor to monitor the soil fertility concentrations. Soil parameters like the Nitrogen, Phosphate and Potassium concentration level can be remotely monitored on an IoT Blynk platform.

Leave a Reply

Your email address will not be published. Required fields are marked *