Overview: IoT Based Soil Nutrient Monitoring
In this project, we will learn about IoT Based Soil Nutrient Monitoring & Analysis systems using Arduino & ESP32. Soil is the base of agriculture. Soil provides nutrients that increase the growth of a crop. Some chemical and physical properties of soil, such as its moisture, temperature, soil nitrogen, phosphorous & potassium content heavily affect the yield of a crop. These properties can be sensed by the open-source hardware, and they can be used in the field.
In this project, a soil Nutrient monitoring & analysis system is proposed in which the farmer will be able to monitor soil moisture, soil temperature, and soil nutrient content like Nitrogen, Phosphorous & Potassium. The farmer can monitor all these parameters wirelessly on a mobile phone or the PC System.
To measure the Soil Moisture, we will use a Capacitive Soil Moisture Sensor. The temperature of the soil can be measured using the DS18B20 Waterproof Temperature Sensor. Similarly, in order to measure the Soil NPK Values, we will use a Soil NPK Sensor. All these sensors can be easily interfaced with Arduino.
We will use the Thingspeak Server to Monitor the data in graphical & numerical format. We need the GSM or WiFi network in the field to send the data to the server. But the agricultural field doesn’t have access to these networks. In order to solve this, we will use the NRF2401 Wireless transceiver Module to send the data from sensor Node to Gateway. The data from the transmitter can be transmitted wirelessly from a kilometer distance to the Receiver. The receiver is built using ESP32 WiFi Module, which has access to WiFi Network. Using this WiFi Network, the data can be uploaded to Thingspeak Server.
So, let’s build an IoT Based Soil Nutrient Content Analysis, Monitoring & Testing System simply using Wireless Sensors Network, Arduino & ESP32.
Bill of Materials
The Bill of Material for this great IoT Based Project is given below. All the components can be easily purchased from the Amazon.
S.N. | Components Name | Quantity | Purchase Links |
---|---|---|---|
1 | Arduino Nano Board | 1 | Amazon | AliExpress |
2 | ESP32 Board | 1 | Amazon | AliExpress |
3 | NR24L01 PA+LNA Module | 2 | Amazon | AliExpress |
4 | NPK Sensor | 1 | Amazon | AliExpress |
5 | Capacitive Soil Moisture Sensor | 1 | Amazon | AliExpress |
6 | DS18B20 Temperature Sensor | 1 | Amazon | AliExpress |
7 | MAX485 Modbus Module | 1 | Amazon | AliExpress |
8 | Resistor 4.7K | 1 | Amazon | AliExpress |
9 | 9V Power Supply | 1 | Amazon | AliExpress |
10 | Connecting Jumper Wires | 20 | Amazon | AliExpress |
11 | Breadboard | 1 | Amazon | AliExpress |
Sensors Used: Soil Moisture, Temperature & NPK
The project Iot based soil Nutrient Monitoring, Analysis & Testing requires some sensors which are explained in detail below.
Capacitive Soil Moisture Sensor
To measure the Soil Moisture Level we need a Soil Moisture Sensor. For this application, a Capacitive type of Soil Moisture Sensor is preferred. We will use an analog capacitive soil moisture sensor that measures soil moisture levels by capacitive sensing. It means the capacitance is varied on the basis of water content present in the soil. The measured capacitance is converted into voltage level basically from 1.2V to 3.0V maximum. The advantage of Capacitive Soil Moisture Sensor is that they are made of a corrosion-resistant material giving it long service life.
The Capacitive Soil Moisture Sensor v2.0 operates between 3.3V-5.5V DC voltage. The output is in Analog form up to 3V Maximum. We can convert the output voltage into the Percentage value. You can follow our previous detailed tutorial on this sensor here: Capacitive Soil Moisture Sensor Tutorial.
DS18B20 Waterproof Temperature Sensor
This is a pre-wired and waterproofed version of the DS18B20 Sensor used to measure something far away, or in wet conditions. The Sensor can measure the temperature between -55 to 125°C (-67°F to +257°F). The cable is jacketed in PVC. These 1-wire digital temperature sensors are fairly precise, i.e ±0.5°C over much of the range. They work great with any microcontroller using a single digital pin.
The sensor requires two libraries like Dallas Temperature Sensor Library & One-Wire Library. It also requires a 4.7k resistor, which is required as a pullup from the DATA to the VCC line when using the sensor. To learn more about this sensor you can go through the previous post: DS18B20 Sensor Tutorial.
NPK Sensor
The soil NPK sensor is suitable for detecting the content of nitrogen, phosphorus, and potassium in the soil. It helps in determining the fertility of the soil. The sensor can be buried in the soil for a long time.
The sensor doesn’t require any chemical reagent. The sensor has high measurement accuracy, fast response speed, and good interchangeability & can be used with any microcontroller. To read the NPK Data you need any Modbus Module like RS485/MAX485. The Modbus module is connected to Microcontroller & to Sensor.
The sensor operates on 9-24V. The accuracy of the sensor is up to within 2%. The nitrogen, phosphorous & potassium measuring resolution is up to 1mg/kg (mg/l). To learn more about this sensor & register addresing check this previous post: NPK Sensor Tutorial.
NRF24L01 Wireless Transceiver Module
The nRF24L01 is a wireless transceiver module, i.e. each module can both send & receive data. It works within the frequency of 2.4GHz. The modules when operated efficiently can cover a distance of 100 meters.
The second version of this module, i.e. nRF24L01 PA+LNA comes with an SMA connector, duck-antenna & special RFX2401C chip which integrates the PA + LNA. This range extender chip along with a duck-antenna helps the module achieve a significantly larger transmission range about 1000m.
The module operates at 3.3V but its SPI pins are 5V tolerable. The NRF24L01 module works with the help of SPI communications hence you can use NRF24L01 with any microcontroller with SPI Pins like ESP32 WiFi Module or Arduino Boards. To learn more about this NRF24L01 Module, you can check some of our previous posts here: NRF24L01 Tutorial
Circuit: IoT Based Soil Nutrient Monitoring with Arduino & ESP32
Now, let us go through our project, i.e. IoT Based Soil Nutrient Monitoring with Arduino & ESP32. We have to make a pair of circuits for that. The one circuit is called a Sensor Node that is made using the Arduino Nano Board & some sensors along with the NRF24L01 Transceiver Module.
For the gateway part, we used ESP32 WiFi Module along with the NRF24L01 Transceiver Module. The Sensor Node Sends the data to the Gateway & the Gateway uploads the data to the Thingspeak Server.
Sensor Node Circuit
The sensor Node Circuit & connection diagram is given below. The Sensor Node comprises of Arduino Nano Board, NRF24L01 Transceiver Module, Soil Moisture Sensor, DS18B20 Temperature Sensor & Soil NPK Sensor.
The connection between NRF24L01 & Arduino Nano Board is given below.
NRF24L01 CSN ………………………………………… 10 of Arduino
NRF24L01 MOSI ………………………………………… 11 of Arduino
NRF24L01 GND ………………………………………… GND of Arduino
NRF24L01 CE ………………………………………… 9 of Arduino
NRF24L01 SCK ………………………………………… 13 of Arduino
NRF24L01 MISO ………………………………………… 12 of Arduino
Apart from the NRF24L01 Arduino Connections, the Sensor are connected to analog & digital pin of Arduino. The Capacitive Soil Moisture Sensor Analog pin is connected to A0 of Arduino. Similarly, the DS18B20 sensor is connected to the D5 of Arduino. And the NPK Sensor is connected to Arduino via Modbus Pin to 2,3,7,8 Pin of Arduino. The NPK Sensor works between 9V-24V. So an extra supply is required for the circuit. The rest of all components can be powered via Arduino 5V/3.3V Pin.
Gateway Circuit
The IoT based Soil Nutrient Content Analysis & Monitoring also involves the Gateway. The Gateway is designed using ESP32 WiFi Module & NRF24L01 Wireless Transceiver Module.
The connection between ESP32 Board & NRF24L01 Wireless Transceiver Module is given below.
NRF24L01 CSN ………………………………………… D5 of ESP32
NRF24L01 MOSI ………………………………………… D23 of ESP32
NRF24L01 GND ………………………………………… GND of ESP32
NRF24L01 CE ………………………………………… D4 of ESP32
NRF24L01 SCK ………………………………………… D18 of ESP32
NRF24L01 MISO ………………………………………… D19 of ESP32
Setting Up Thingspeak Server
The Iot Based IoT Soil Nutrient Monitoring & Analysis is done on Thingspeak Server. So, we need to setup the Thingspeak Account. To set up Thingspeak follow the following Steps:
Step 1: Visit https://thingspeak.com/ and create your account by filling up the details.
Step 2: Create a New Channel by Clicking on “Channel” & fill up the following details as shown in the image below.
Step 3: Click on API Key, you will see the “Write API Key“. Copy the API Key. This is very important, it will be required in Code Part.
Step 4: You can click on the “Private View” & customize the display window as you want.
So, that’s all from the Thingspeak Setup Part. Now let us move to the programming Part.
Adding Necessary Library to Arduino IDE
1. NRF24L01 Library
This library is designed to be maximally compliant with the intended operation of the nRF24L01 2.4GHz Wireless Transceiver Module. This chip uses the SPI bus, plus two-chip control pins.
2. RH24 Library
This is the RadioHead Packet Radio library for embedded microprocessors. It provides a complete object-oriented library for sending and receiving packetized messages via a variety of common data radios and other transports on a range of embedded microprocessors.
3. One Wire Library
The OneWire library lets you access 1-wire devices made by Maxim/Dallas, such as DS18B20 Temperature sensors. OneWire requires a single 4.7K pull-up resistor, connected between the pin and your power supply.
4. Dallas Temperature Sensor Library
This is the Arduino Library for Maxim Temperature Integrated Circuits. This library supports DS18B20, DS1822, DS1820 & MAX31820. The Dallas 1-Wire protocol is somewhat complex and requires a bunch of code to parse out the communication. The Dallas Temperature Sensor Library can issue simple commands to get temperature readings from the sensor.
Source Code/Program: IoT Soil Nutrient Monitoring & Analysis
The Source Code/Program for IoT Soil Nutrient Monitoring, Analysis & Testing part has a pair a code. One is for the Transmitter/Node part where the code needs to be uploaded to the Arduino IDE. The other part is the Receiver/Gateway part where the code needs to be uploaded to the ESP32 Board.
Sensor Node/Transmitter Code
Copy the following code and upload it to the Arduino Nano Board.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
#include <SPI.h> #include <SoftwareSerial.h> #include <OneWire.h> #include <DallasTemperature.h> #include <nRF24L01.h> #include <RF24.h> RF24 radio(9, 10); // CE, CSN on Blue Pill const uint64_t address = 0xF0F0F0F0E1LL; #define ONE_WIRE_BUS 5 #define RE 8 #define DE 7 const byte code[] = {0x01, 0x03, 0x00, 0x1e, 0x00, 0x03, 0x65, 0xCD}; byte values[11]; SoftwareSerial mod(2, 3); const int AirValue = 645; //you need to replace this value with Value_1 const int WaterValue = 254; //you need to replace this value with Value_2 int soilMoistureValue = 0; int soilmoisturepercent = 0; float temperature; int nitrogen; int phosphorous; int potassium; OneWire oneWire(ONE_WIRE_BUS); DallasTemperature sensors(&oneWire); struct MyVariable { byte soilmoisturepercent; byte nitrogen; byte phosphorous; byte potassium; byte temperature; }; MyVariable variable; void setup() { Serial.begin(9600); mod.begin(9600); radio.begin(); //Starting the Wireless communication radio.openWritingPipe(address); //Setting the address where we will send the data radio.setPALevel(RF24_PA_MIN); //You can set it as minimum or maximum depending on the distance between the transmitter and receiver. radio.stopListening(); //This sets the module as transmitter sensors.begin(); pinMode(RE, OUTPUT); pinMode(DE, OUTPUT); } void loop() { byte val; digitalWrite(DE, HIGH); digitalWrite(RE, HIGH); delay(10); if (mod.write(code, sizeof(code)) == 8) { digitalWrite(DE, LOW); digitalWrite(RE, LOW); for (byte i = 0; i < 11; i++) { //Serial.print(mod.read(),HEX); values[i] = mod.read(); Serial.print(values[i], HEX); } Serial.println(); } nitrogen = values[4]; phosphorous = values[6]; potassium = values[8]; delay(1500); soilMoistureValue = analogRead(A0); //put Sensor into soil //Serial.println(soilMoistureValue); soilmoisturepercent = map(soilMoistureValue, AirValue, WaterValue, 0, 100); { if (soilmoisturepercent >= 100) { soilmoisturepercent = 100; } else if (soilmoisturepercent <= 0) { soilmoisturepercent = 0; } else if (soilmoisturepercent > 0 && soilmoisturepercent < 100) { soilmoisturepercent = soilmoisturepercent; } } delay(1500); sensors.requestTemperatures(); temperature = sensors.getTempCByIndex(0); variable.soilmoisturepercent = soilmoisturepercent; variable.nitrogen = nitrogen; variable.phosphorous = phosphorous; variable.potassium = potassium; variable.temperature = temperature; delay(1500); Serial.print("Soil Moisture: "); Serial.print(variable.soilmoisturepercent); Serial.println("%"); Serial.print("Nitrogen: "); Serial.print(variable.nitrogen); Serial.println(" mg/kg"); Serial.print("Phosphorous: "); Serial.print(variable.phosphorous); Serial.println(" mg/kg"); Serial.print("Potassium: "); Serial.print(variable.potassium); Serial.println(" mg/kg"); Serial.print("Temperature: "); Serial.print(variable.temperature); Serial.println("*C"); Serial.println(); radio.write(&variable, sizeof(MyVariable)); Serial.println("Data Packet Sent"); Serial.println(""); delay(10000); } |
Gateway/Receiver Code
The code need to be uploaded to the ESP32 Board. But before uploading the code, you need to make changes to the WiFi SSID & Password from the following line.
1 2 |
const char* ssid = "********************************"; const char* password = "********************************"; |
Also replace the Thingspeak API Key with your API Key.
1 |
String apiKey = "********************************"; |
After updating the WiFi SSID & Password, you can now finally upload the code to the ESP32 WiFi Module.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
#include <WiFi.h> #include <SPI.h> #include <nRF24L01.h> #include <RF24.h> String apiKey = "FTY1Txxxxxxx1NGU"; const char* ssid = "********************************"; const char* password = "********************************"; const char* server = "api.thingspeak.com"; RF24 radio(4, 5); const uint64_t address = 0xF0F0F0F0E1LL; struct MyVariable { byte soilmoisturepercent; byte nitrogen; byte phosphorous; byte potassium; byte temperature; }; MyVariable variable; WiFiClient client; void setup() { Serial.begin(115200); radio.begin(); //Starting the Wireless communication radio.openReadingPipe(0, address); //Setting the address at which we will receive the data radio.setPALevel(RF24_PA_MIN); //You can set this as minimum or maximum depending on the distance between the transmitter and receiver. radio.startListening(); //This sets the module as receiver Serial.println("Receiver Started...."); Serial.print("Connecting to "); Serial.println(ssid); Serial.println(); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); } int recvData() { if ( radio.available() ) { radio.read(&variable, sizeof(MyVariable)); return 1; } return 0; } void loop() { if(recvData()) { Serial.println("Data Received:"); Serial.print("Soil Moisture: "); Serial.print(variable.soilmoisturepercent); Serial.println("%"); Serial.print("Nitrogen: "); Serial.print(variable.nitrogen); Serial.println(" mg/kg"); Serial.print("Phosphorous: "); Serial.print(variable.phosphorous); Serial.println(" mg/kg"); Serial.print("Potassium: "); Serial.print(variable.potassium); Serial.println(" mg/kg"); Serial.print("Temperature: "); Serial.print(variable.temperature); Serial.println("*C"); Serial.println(); if (client.connect(server, 80)) { String postStr = apiKey; postStr += "&field1="; postStr += String(variable.soilmoisturepercent); postStr += "&field2="; postStr += String(variable.nitrogen); postStr += "&field3="; postStr += String(variable.phosphorous); postStr += "&field4="; postStr += String(variable.potassium); postStr += "&field5="; postStr += String(variable.temperature); postStr += "\r\n\r\n\r\n\r\n\r\n"; client.print("POST /update HTTP/1.1\n"); client.print("Host: api.thingspeak.com\n"); client.print("Connection: close\n"); client.print("X-THINGSPEAKAPIKEY: " + apiKey + "\n"); client.print("Content-Type: application/x-www-form-urlencoded\n"); client.print("Content-Length: "); client.print(postStr.length()); client.print("\n\n"); client.print(postStr); delay(1000); Serial.println("Data Sent to Server"); } client.stop(); } } |
IoT Based Soil Nutrient Monitoring, Testing & Results
After successfully uploading the code to the Arduino & ESP32 Board, you can start testing the device. So for that place all the sensor into the soil as shown in image below.
Now open both the Serial Monitor to check whether the data transmission is happening or not. The Serial Monitor on the sensor node shows the data read from the sensor like the value of soil moisture in percentage, the temperature in degree Celcius, the NPK Content in mg/Kg.
The data is transmitted wirelessly to the receiver/gateway section. The gateway collects the data and uploads it to the Thingspeak Server. You can just visit the private view of the Thingspeak Dashboard. You will the data being logged into the Thingspeak Server.
So, this is how you can make a simple IoT Based Soil Nutrient Monitoring & Analysis System using ESP32, Arduino & some Soil Sensors along with the NRF24L01 Wireless Transceiver Module.
Video Tutorial & Guide
For better results, you may use RS485 Soil Moisture Sensor for measuring Soil Humidity and Temperature Value. You can add few extras Sensor to the project like Soil Ph Sensor & also the Soil EC Sensor. This will make the project more interesting & give you more detail analysis.
23 Comments
What is the principle of operation of this NPK sensor? This looks like nonsense; three metal probes with no ISFET visible or sample channel. How will it distinguish between NO3-, K+, P+ ions? Is this component a fake?
Can I get this project flow diagram
This is not a fake component. It has a internal circuitry which is calibrated with a great measurement accuracy. Its an industrial sensor build only for industrial propose. They have explained all the working and principle behind the operation in their manual. But unfortunately the manual is in Chinese language.
How can do this project with only single esp32?
esp32 connect with sensors and gateway (router)
Regarding this project, since this project only monitor and analyse the nutrients. What do I have to do to make the watering and fertilization system automated according to the data?
Hi, what if i want to send sensor data from arduino UNO connect to ESP 01 then to nodered? Do u know how? because the NPK sensor already use serial port on UNO and connecting arduino to ESP01 also use serial port.
I can confirm that the above tutorial is correct but the sensor does not measure directly the NPK content of the soil. By using benchmarking solutions of 50ppm N-NO3, 7ppm N-Nh4 and a few others + 2 samples of soil whose NPK content was determined using spectrophotometry, i have determined that this sensor is nothing more than an Ec sensor. If you wish to measure such thing, you can find way cheaper solutions out there and can infer the NPK content ( just like this sensor does) of the soil.
Hello! I am using a pH and NPK Sensors, whenever I combine them into 1 arduino board the output of pH is 25.5 and N, P, and K is 255. May I know how to solve this?
When you combine the both sensor to one common modbus line, the sensor will not work bcoz of the buffer issue with software serial.
They have different/ separate RS485 modbus, Sir.
any one able to send soil npk sensor library?
I think it doesnt need library? just connect it to Rs485 and use the address provided on its manual
Good day! May I know if the nrf24l01 doesn’t required to be configured?
10q so much, would u reply the simulator software that have the sensor
can i do this project but instead of using nrf24l01, can i use Lora SX1278?
Why is my ESP32S not receiving data? Arduino Nano and the NRF24L01 work just fine and the data is send but the ESP32 side of this project does not receive the data??? Please help…
Why is my ESP32S not working? Arduino and the NRF24L01 are working just fine and sending the data but the ESP32 part of this project does not receive the data?? Please help…
please i am new in IOT and my ESP32 has 38 pins how can i modify the wiring and code
My data constant 0 value, can u help me out
I was trying to add the NRF24L01 Library, but when I tried, Arduino gave me an error message saying that the .zip file didn’t contain a library. What is the fix? Can you double check the link/file?
Add any NRF24L01 libray, look in the github or somewhere else.
And can you please add the links to the specific libraries you used for the code? It would help me figure out where my code is incorrect.
if i want to close this in box what would be the dimension of box and can please which part are neede to be outside the box