Close Menu
  • Articles
    • Learn Electronics
    • Product Review
    • Tech Articles
  • Electronics Circuits
    • 555 Timer Projects
    • Op-Amp Circuits
    • Power Electronics
  • Microcontrollers
    • Arduino Projects
    • STM32 Projects
    • AMB82-Mini IoT AI Camera
    • BLE Projects
  • IoT Projects
    • ESP8266 Projects
    • ESP32 Projects
    • ESP32 MicroPython
    • ESP32-CAM Projects
    • LoRa/LoRaWAN Projects
  • Raspberry Pi
    • Raspberry Pi Projects
    • Raspberry Pi Pico Projects
    • Raspberry Pi Pico W Projects
  • Electronics Calculator
Facebook X (Twitter) Instagram
  • About Us
  • Disclaimer
  • Privacy Policy
  • Contact Us
  • Advertise With Us
Facebook X (Twitter) Instagram Pinterest YouTube LinkedIn
How To Electronics
  • Articles
    • Learn Electronics
    • Product Review
    • Tech Articles
  • Electronics Circuits
    • 555 Timer Projects
    • Op-Amp Circuits
    • Power Electronics
  • Microcontrollers
    • Arduino Projects
    • STM32 Projects
    • AMB82-Mini IoT AI Camera
    • BLE Projects
  • IoT Projects
    • ESP8266 Projects
    • ESP32 Projects
    • ESP32 MicroPython
    • ESP32-CAM Projects
    • LoRa/LoRaWAN Projects
  • Raspberry Pi
    • Raspberry Pi Projects
    • Raspberry Pi Pico Projects
    • Raspberry Pi Pico W Projects
  • Electronics Calculator
How To Electronics
Home » IoT LoRa Based Smart Agriculture & Remote Monitoring System
Arduino Projects IoT Projects LoRa/LoRaWAN Projects

IoT LoRa Based Smart Agriculture & Remote Monitoring System

Mamtaz AlamBy Mamtaz AlamUpdated:March 8, 202317 Comments7 Mins Read
Share Facebook Twitter LinkedIn Telegram Reddit WhatsApp
IoT LoRa Based Smart Agriculture
Share
Facebook Twitter LinkedIn Pinterest Email Reddit Telegram WhatsApp

Overview: IoT LoRa Based Smart Agriculture

In this project, we are going to learn about IoT LoRa Based Smart Agriculture & Remote Monitoring System. Smart Agriculture means monitoring environmental conditions that influence crop production & track livestock health indicators. LoRa based Internet of Things (IoT) technology for agriculture enables efficiencies that reduce environmental impact, maximize yield, and minimize expenses. Smart agriculture use cases based on LoRa devices and the LoRaWAN protocol have demonstrated significant improvements, such as a 50% water reduction for commercial farms.

In this project we will use the LoRa soil moisture sensor based on the Atmega328P microcontroller, LoRa Module RFM95 & AHT10 Humidity/Temperature Sensor. The AHT10 Digital Humidity & Temperature Sensor measures the local air temperature & humidity. The Capacitive Soil Moisture Sensor will measure the Soil Humidity/Moisture. Hence all the measured data can be sent wirelessly up to 15km distance and can be read by the receiver. Both the transmitter and receiver is designed using the LoRa Module.

IoT LoRa Based Smart Agriculture & Remote Monitoring System

The transmitter operates on low power mode. Using a AAA Battery the device can be operated over a year. The device power can be controlled and data sending intervals can be increased as per requirement. Thus the advantage of this Technology includes long-range, low-power wireless qualities that enable the use of low-cost sensors to send data from the farm to the Cloud where it can be analyzed to improve operations.


Bill of Materials

Following are the components required for making this IoT LoRa Network Based Smart Agriculture Project. We need a few LoRa Agriculture sensors like the Soil Moisture sensor to measure Soil Moisture. We can measure the environmental parameter like surrounding humidity & temperature. For this AHT10 is the best suitable Sensor.

Instead of buying separate sensors and assembling on a board is a tough and time-consuming task. So I purchased a combined sensor board assembled on a PCB. Both the transmitter & receiver part PCB Board with component assembled on it can be purchased from the below link.

S.N.Components NameQuantityPurchase Link
1LoRa AHT10 Soil Moisture Sensor1Makerfabs
2LoRa Receiver1Makerfabs
3FTDI USB-to-UART Converter1Amazon | AliExpress
4AAA Battery2-
5Micro-USB Cable1Amazon | AliExpress




LoRa Transmitter: Soil Moisture Sensor + AHT10 Humidity/Temperature Sensor

The Transmitter part consists of Lora soil moisture sensor and AHT10 Humidity/Temperature Sensor. The microcontroller used in this board is Atmel’s Atmega328P which supports Arduino Programming. The AHT10 Sensor collects local air temperature & humidity. The Capacitive Soil Moisture Sensor detects the soil humidity. The Sensor is based on 555-Timer IC. The Lora Radio and the Soil Moisture Sensor must have the same work frequency. Otherwise, it receive nothing from another. The transmitter transmits the local environment data to the gateway using LoRa Module RFM95.

LoRa Soil Moisture Sensor

The Lora Transmitter is powered by a pair of AAA Battery. The device transmits the data regularly after the interval of a few minutes and then goes to sleep mode for saving the Battery Power. The sensor function could be shut down or they can be only powered ON for a short time based on code and hardware setup. Thus because of sleep mode and low power consumption mode, the battery life can be extended up to several months. The capacitive soil Moisture sensor is coated with waterproof paint, so it doesn’t have any corrosion effect even the sensor is dipped in the soil for a long time. The module suits for applications for smart-farm, irrigation, agriculture, etc.

The ATmega328 chip has default Arduino bootloader and thus can be easily programmed using Arduino IDE. We just need a USB-to-TTL Converter Module.

Power Consumption & Sleep Mode

MCU Power Consumption at 1MHz, 1.8V, 25°C
– Active Mode: 0.2mA
– Power-down Mode: 0.1µA
– Power-save Mode: 0.75µA (Including 32kHz RTC)


LoRa Receiver: Lora Radio (433M/868M/915M)

The Lora Radio Receiver is a mainboard based on the ATmega328 and 433MHZ/868MHz/915MHz RFM95 LoRa module. The LoRa Radio allows the user to send data and reach extremely long ranges at low data-rates. It provides ultra-long range spread spectrum communication and high interference immunity whilst minimizing current consumption. It has Arduino pro mini 3.3V 8MHz bootloader on this board and uses the CP2104 as USB to serial to upload the code using Arduino IDE. In this LoRa Smart Agriculture project, we will use it as a Receiver Gateway.

lora agriculture sensor

Features

  • BAT Input Voltage: 3.4-4.2V
  • Integrated Power Control System
  • 127 dB Dynamic Range RSSI
  • Uses the License-free ISM band: “European ISM” @ 433MHz/868MHz/915MHz
  • +5 to +20 dBm up to 100 mW Power Output Capability (power output selectable in software)
  • ~100mA Peak during +20dBm transmit, ~30mA during active radio listening
  • Range of approx. 2Km, depending on obstructions, frequency, antenna, and power output



Setting up Loara Soil Moisture Transmitter Part

In order to upload the Code to the Transmitter Part you need to solder a 5 Pin Male Header pin. So first Solder the Male header pin here.

Now you need to connect USB-to-UART Module to upload the Code the Atmega328 Chip using Arduino IDE. Make a connection between the USB-to-UART Module as follow.

Note that the DTR in the USB-to-UART converter is needed to connect to the “Reset” pin for Arduino sketch uploading. If there is no DTR, you may need to press the “reset” button manually for uploading the code.

Install AAA Battery on the backside of the Module.

Now in order to program the Board using Arduino IDE for Lora agriculture sensor Board, there is already a default package board installed on Arduino IDE.

From the top Arduino IDE menu, select Tools-> Board-> Arduino Pro or Pro Mini. Also select Tools-> Processor->Atmega328P(3.3V,8Mhz).


Setting up Loara Receiver Part

The Lora Receiver doesn’t need any USB-to-UART Module as it can be directly programmed using Micro-USB Data Cable.

The board uses the same package for programming. So Select the Arduino Pro or Pro mini & ATmega328P (3.3V,8Mhz) Board.


Transmitter Code

The Transmitter Code is divided into 3 files:
1. Main.ino File
2. I2C_AHT10.cpp File
3. I2C_AHT10.h File

But before that, you need to add RFM95 Library to the Arduino IDE. So download the RFM95 Library from the link below and add it to the Library Folder.

Download LoRa RFM95 Library

Modify the frequency macro according to your board is 433Mhz or 868Mhz or 915Mhz.
If your Lora board is 433MHz:

C++
1
#define RF95_FREQ 433.0

If your Lora board is 868MHz:

C++
1
#define RF95_FREQ 868.0

If your Lora board is 915MHz:

C++
1
#define RF95_FREQ 915.0


1. Main.ino File

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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
#include <SPI.h>
#include "RH_RF95.h"
 
#include "I2C_AHT10.h"
#include <Wire.h>
AHT10 humiditySensor;
 
int sensorPin = A2;    // select the input pin for the potentiometer
int sensorValue = 0;  // variable to store the value coming from the sensor
int sensorPowerCtrlPin = 5;
 
void sensorPowerOn(void)
{
  digitalWrite(sensorPowerCtrlPin, HIGH);//Sensor power on
}
void sensorPowerOff(void)
{
  digitalWrite(sensorPowerCtrlPin, LOW);//Sensor power on
}
 
#define RFM95_CS 10
#define RFM95_RST 4
#define RFM95_INT 2
 
// Change to 434.0 or other frequency, must match RX's freq!
#define RF95_FREQ 433.0
 
// Singleton instance of the radio driver
RH_RF95 rf95(RFM95_CS, RFM95_INT);
 
void setup()
{
 
  pinMode(RFM95_RST, OUTPUT);
  digitalWrite(RFM95_RST, LOW);
  delay(100);
  digitalWrite(RFM95_RST, HIGH);
 
  pinMode(sensorPowerCtrlPin, OUTPUT);
  //digitalWrite(sensorPowerCtrlPin, LOW);//Sensor power on
  sensorPowerOn();
  //pinMode(sensorPin, INPUT);
  
  //while (!Serial);
  Serial.begin(115200);
  delay(100);
 
  Wire.begin(); //Join I2C bus
  //Check if the AHT10 will acknowledge
  if (humiditySensor.begin() == false)
  {
    Serial.println("AHT10 not detected. Please check wiring. Freezing.");
    //while (1);
  }
  else
    Serial.println("AHT10 acknowledged.");
    
  Serial.println("Marduino LoRa TX Test!");
 
  // manual reset
  digitalWrite(RFM95_RST, LOW);
  delay(10);
  digitalWrite(RFM95_RST, HIGH);
  delay(10);
 
  while(!rf95.init()) {
    Serial.println("LoRa radio init failed");
    while (1);
  }
  Serial.println("LoRa radio init OK!");
 
  //rf95.setModemConfig(Bw125Cr48Sf4096);
 
  //Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM
  if (!rf95.setFrequency(RF95_FREQ)) {
    Serial.println("setFrequency failed");
    while (1);
  }
  Serial.print("Set Freq to: ");
  Serial.println(RF95_FREQ);
  
  // Defaults after init are 434.0MHz, 13dBm, Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on
 
  // The default transmitter power is 13dBm, using PA_BOOST.
  // If you are using RFM95/96/97/98 modules which uses the PA_BOOST transmitter pin, then
  // you can set transmitter powers from 5 to 23 dBm:
  rf95.setTxPower(23, false);
 
  //dht.begin();
}
 
int16_t packetnum = 0;  // packet counter, we increment per xmission
float temperature=0.0;//
float humidity=0.0;
 
void loop()
{
 
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  //float humidity = 6.18;//dht.readHumidity();
  // Read temperature as Celsius (the default)
 
  sensorPowerOn();//
  delay(100);
  sensorValue = analogRead(sensorPin);
  delay(200);
 
  if (humiditySensor.available() == true)
  {
    //Get the new temperature and humidity value
    temperature = humiditySensor.getTemperature();
    humidity = humiditySensor.getHumidity();
 
    //Print the results
    Serial.print("Temperature: ");
    Serial.print(temperature, 2);
    Serial.print(" C\t");
    Serial.print("Humidity: ");
    Serial.print(humidity, 2);
    Serial.println("% RH");
 
  }
    // Check if any reads failed and exit early (to try again).
  if (isnan(humidity) || isnan(temperature)) {
    Serial.println(F("Failed to read from AHT sensor!"));
    //return;
  }
  
  delay(100);
  //sensorPowerOff();
 
  Serial.print(F("Moisture ADC : "));
  Serial.println(sensorValue);
 
  
  //Serial.print(F("Humidity: "));
  //Serial.print(humidity);
  //Serial.print(F("%  Temperature: "));
  //Serial.print(temperature);
  //Serial.println("Humidity is " + (String)humidity);
  //Serial.println("Temperature is " + (String)temperature);
 
  String message = "#"+(String)packetnum+" Humidity:"+(String)humidity+"% Temperature:"+(String)temperature+"C"+" ADC:"+(String)sensorValue;
  Serial.println(message);
  packetnum++;
  Serial.println("Transmit: Sending to rf95_server");
  
  // Send a message to rf95_server
 
  uint8_t radioPacket[message.length()+1];
  message.toCharArray(radioPacket, message.length()+1);
  
  radioPacket[message.length()+1]= '\0';
 
  Serial.println("Sending..."); delay(10);
  rf95.send((uint8_t *)radioPacket, message.length()+1);
  Serial.println("Waiting for packet to complete..."); delay(10);
  rf95.waitPacketSent();
  // Now wait for a reply
  uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];
  uint8_t len = sizeof(buf);
 
  Serial.println("Waiting for reply..."); delay(10);
  if(rf95.waitAvailableTimeout(8000))
  {
    // Should be a reply message for us now  
    if (rf95.recv(buf, &len))
   {
      Serial.print("Got reply: ");
      Serial.println((char*)buf);
      Serial.print("RSSI: ");
      Serial.println(rf95.lastRssi(), DEC);    
    }
    else
    {
      Serial.println("Receive failed");
    }
  }
  else
  {
    Serial.println("No reply, is there a listener around?");
  }
  delay(1000);
}

2. I2C_AHT10.cpp File

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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
#include "I2C_AHT10.h"
 
/*--------------------------- Device Status ------------------------------*/
bool AHT10::begin(TwoWire &wirePort)
{
    _i2cPort = &wirePort; //Grab the port the user wants to communicate on
 
    _deviceAddress = AHT10_DEFAULT_ADDRESS; //We had hoped the AHT10 would support two addresses but it doesn't seem to
 
    if (isConnected() == false)
        return false;
 
    //Wait 40 ms after power-on before reading temp or humidity. Datasheet pg 8
    delay(40);
 
    //Check if the calibrated bit is set. If not, init the sensor.
    if (isCalibrated() == false)
    {
        //Send 0xBE0800
        initialize();
 
        //Immediately trigger a measurement. Send 0xAC3300
        triggerMeasurement();
 
        delay(75); //Wait for measurement to complete
 
        uint8_t counter = 0;
        while (isBusy())
        {
            delay(1);
            if (counter++ > 100)
                return (false); //Give up after 100ms
        }
 
        //This calibration sequence is not completely proven. It's not clear how and when the cal bit clears
        //This seems to work but it's not easily testable
        if (isCalibrated() == false)
        {
            return (false);
        }
    }
 
    //Check that the cal bit has been set
    if (isCalibrated() == false)
        return false;
 
    //Mark all datums as fresh (not read before)
    sensorQueried.temperature = true;
    sensorQueried.humidity = true;
 
    return true;
}
 
//Ping the AHT10's I2C address
//If we get a response, we are correctly communicating with the AHT10
bool AHT10::isConnected()
{
    _i2cPort->beginTransmission(_deviceAddress);
    if (_i2cPort->endTransmission() == 0)
        return true;
 
    //If IC failed to respond, give it 20ms more for Power On Startup
    //Datasheet pg 7
    delay(20);
 
    _i2cPort->beginTransmission(_deviceAddress);
    if (_i2cPort->endTransmission() == 0)
        return true;
 
    return false;
}
 
/*------------------------ Measurement Helpers ---------------------------*/
 
uint8_t AHT10::getStatus()
{
    _i2cPort->requestFrom(_deviceAddress, (uint8_t)1);
    if (_i2cPort->available())
        return (_i2cPort->read());
    return (0);
}
 
//Returns the state of the cal bit in the status byte
bool AHT10::isCalibrated()
{
    return (getStatus() & (1 << 3));
}
 
//Returns the state of the busy bit in the status byte
bool AHT10::isBusy()
{
    return (getStatus() & (1 << 7));
}
 
bool AHT10::initialize()
{
    _i2cPort->beginTransmission(_deviceAddress);
    _i2cPort->write(sfe_aht10_reg_initialize);
    _i2cPort->write(0x80);
    _i2cPort->write(0x00);
    if (_i2cPort->endTransmission() == 0)
        return true;
    return false;
}
 
bool AHT10::triggerMeasurement()
{
    _i2cPort->beginTransmission(_deviceAddress);
    _i2cPort->write(sfe_aht10_reg_measure);
    _i2cPort->write(0x33);
    _i2cPort->write(0x00);
    if (_i2cPort->endTransmission() == 0)
        return true;
    return false;
}
 
//Loads the
void AHT10::readData()
{
    //Clear previous data
    sensorData.temperature = 0;
    sensorData.humidity = 0;
 
    if (_i2cPort->requestFrom(_deviceAddress, (uint8_t)6) > 0)
    {
        uint8_t state = _i2cPort->read();
 
        uint32_t incoming = 0;
        incoming |= (uint32_t)_i2cPort->read() << (8 * 2);
        incoming |= (uint32_t)_i2cPort->read() << (8 * 1);
        uint8_t midByte = _i2cPort->read();
 
        incoming |= midByte;
        sensorData.humidity = incoming >> 4;
 
        sensorData.temperature = (uint32_t)midByte << (8 * 2);
        sensorData.temperature |= (uint32_t)_i2cPort->read() << (8 * 1);
        sensorData.temperature |= (uint32_t)_i2cPort->read() << (8 * 0);
 
        //Need to get rid of data in bits > 20
        sensorData.temperature = sensorData.temperature & ~(0xFFF00000);
 
        //Mark data as fresh
        sensorQueried.temperature = false;
        sensorQueried.humidity = false;
    }
}
 
//Triggers a measurement if one has not been previously started, then returns false
//If measurement has been started, checks to see if complete.
//If not complete, returns false
//If complete, readData(), mark measurement as not started, return true
bool AHT10::available()
{
    if (measurementStarted == false)
    {
        triggerMeasurement();
        measurementStarted = true;
        return (false);
    }
 
    if (isBusy() == true)
    {
        return (false);
    }
 
    readData();
    measurementStarted = false;
    return (true);
}
 
bool AHT10::softReset()
{
    _i2cPort->beginTransmission(_deviceAddress);
    _i2cPort->write(sfe_aht10_reg_reset);
    if (_i2cPort->endTransmission() == 0)
        return true;
    return false;
}
 
/*------------------------- Make Measurements ----------------------------*/
 
float AHT10::getTemperature()
{
    if (sensorQueried.temperature == true)
    {
        //We've got old data so trigger new measurement
        triggerMeasurement();
 
        delay(75); //Wait for measurement to complete
 
        uint8_t counter = 0;
        while (isBusy())
        {
            delay(1);
            if (counter++ > 100)
                return (false); //Give up after 100ms
        }
 
        readData();
    }
 
    //From datasheet pg 8
    float tempCelsius = ((float)sensorData.temperature / 1048576) * 200 - 50;
 
    //Mark data as old
    sensorQueried.temperature = true;
 
    return tempCelsius;
}
 
float AHT10::getHumidity()
{
    if (sensorQueried.humidity == true)
    {
        //We've got old data so trigger new measurement
        triggerMeasurement();
 
        delay(75); //Wait for measurement to complete
 
        uint8_t counter = 0;
        while (isBusy())
        {
            delay(1);
            if (counter++ > 100)
                return (false); //Give up after 100ms
        }
 
        readData();
    }
 
    //From datasheet pg 8
    float relHumidity = ((float)sensorData.humidity / 1048576) * 100;
 
    //Mark data as old
    sensorQueried.humidity = true;
 
    return relHumidity;
}

3. I2C_AHT10.h File

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
#ifndef __I2C_AHT10_H__
#define __I2C_AHT10_H__
 
#include <Arduino.h>
#include <Wire.h>
 
#define AHT10_DEFAULT_ADDRESS 0x38
 
enum registers
{
    sfe_aht10_reg_reset = 0xBA,
    sfe_aht10_reg_initialize = 0xBE,
    sfe_aht10_reg_measure = 0xAC,
};
 
class AHT10
{
private:
    TwoWire *_i2cPort; //The generic connection to user's chosen I2C hardware
    uint8_t _deviceAddress;
    bool measurementStarted = false;
 
    struct
    {
        uint32_t humidity;
        uint32_t temperature;
    } sensorData;
 
    struct
    {
        uint8_t temperature : 1;
        uint8_t humidity : 1;
    } sensorQueried;
 
public:
    //Device status
    bool begin(TwoWire &wirePort = Wire); //Sets the address of the device and opens the I2C bus
    bool isConnected();                   //Checks if the AHT10 is connected to the I2C bus
    bool available();                     //Returns true if new data is available
 
    //Measurement helper functions
    uint8_t getStatus();       //Returns the status byte
    bool isCalibrated();       //Returns true if the cal bit is set, false otherwise
    bool isBusy();             //Returns true if the busy bit is set, false otherwise
    bool initialize();         //Initialize for taking measurement
    bool triggerMeasurement(); //Trigger the AHT10 to take a measurement
    void readData();           //Read and parse the 6 bytes of data into raw humidity and temp
    bool softReset();          //Restart the sensor system without turning power off and on
 
    //Make measurements
    float getTemperature(); //Goes through the measurement sequence and returns temperature in degrees celcius
    float getHumidity();    //Goes through the measurement sequence and returns humidity in % RH
};
#endif



Receiver Code

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
#include <SPI.h>
#include <RH_RF95.h>
#define RFM95_CS 10
#define RFM95_RST 9
#define RFM95_INT 2
// Change to 434.0 or other frequency, must match RX's freq!
#define RF95_FREQ 433.0
// Singleton instance of the radio driver
RH_RF95 rf95(RFM95_CS, RFM95_INT);
 
int count=0;
 
void setup()
{  
  pinMode(RFM95_RST, OUTPUT);
  digitalWrite(RFM95_RST, HIGH);
  //while (!Serial);
  Serial.begin(115200);
  delay(100);
  Serial.println("Arduino LoRa RX Test!");
  
  // manual reset
  digitalWrite(RFM95_RST, LOW);
  delay(10);
  digitalWrite(RFM95_RST, HIGH);
  delay(10);
  while (!rf95.init()) {
    Serial.println("LoRa radio init failed");
    while (1);
  }
  Serial.println("LoRa radio init OK!");
  // Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM
  if (!rf95.setFrequency(RF95_FREQ)) {
    Serial.println("setFrequency failed");
    while (1);
  }
  Serial.print("Set Freq to: "); Serial.println(RF95_FREQ);
  // Defaults after init are 434.0MHz, 13dBm, Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on
  // The default transmitter power is 13dBm, using PA_BOOST.
  // If you are using RFM95/96/97/98 modules which uses the PA_BOOST transmitter pin, then
  // you can set transmitter powers from 5 to 23 dBm:
  rf95.setTxPower(23, false);
}
void loop()
{
  if (rf95.available())
  {
    // Should be a message for us now  
    uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];
    uint8_t len = sizeof(buf);
    
    if (rf95.recv(buf, &len))
    {
      count++;      
      RH_RF95::printBuffer("Received: ", buf, len);
      Serial.print("Got: ");
      Serial.println((char*)buf);
      Serial.print("RSSI: ");
      Serial.println(rf95.lastRssi(), DEC);
      
      // Send a reply
      uint8_t data[] = "And hello back to you";
      rf95.send(data, sizeof(data));
      rf95.waitPacketSent();
      Serial.println("Sent a reply");
    }
    else
    {
      Serial.println("Receive failed");
    }
  }
}


IoT LoRa Based Smart Agriculture & Remote Monitoring System

Let us check now a simple demonstration of LoRa Based Smart Agriculture. Now you can open the Serial Monitor for both the Transmitter and Receiver. The Lora Transmitter and Receiver will get started and communicate with each other.

The transmitter end will read the Soil Moisture Data in ADC which can be converted to a Percentage value (Refer this Article..). Similarly, the AHT10 will collect Air Humidity and Temperature Data. The data is transmitted to the gateway.

Lora Soil Moisture Sensor Data



The gateway data can be observed in Serial Monitor.

The transmitter will send the data and then goes to Deep Sleep Mode or Power Saving Mode. During the data transmission mode, it consumes around 0.2mA of Power. While in the Power-save Mode the current get reduced to 0.75µA. The Battery life can be increased to several months by increasing the interval of data transmission.

lora agriculture sensor data

Well that’s all from IoT Lora Based Agriculture Network. You can extend this project by adding the ESP32 WiFi Gateway Based on LoRa. You can check this post: ESP32 LoRa Soil Moisture Monitoring Project on WebServer.


Video Tutorial & Demonstration

IoT LoRa Based Smart Agriculture with Remote Monitoring System | RFM95 +Arduino+Soil Moisture Sensor
Watch this video on YouTube.

The data can also be visualized on The Things Network Server using the LoRaWAN Gateway. You may refer to one of the best product LoRaWAN Temperature/ Humidity/ Soil Moisture Sensor for more information.

Share. Facebook Twitter Pinterest LinkedIn Tumblr Email Reddit Telegram WhatsApp
Previous ArticlePower Supply for NodeMCU with Battery Charger & Boost Converter
Next Article IoT Home Automation using Blynk & NodeMCU ESP8266

Related Posts

ESP32 Fingerprint Attendance System with Live Web Dashboard

ESP32 Fingerprint Attendance System with Live Web Dashboard

Updated:June 21, 2026
IoT Based PM & Air Quality Monitoring System using ESP32

IoT Based PM & Air Quality Monitoring System using ESP32

Updated:June 14, 2026
DIY ESP32 MLX90640 IR Thermal Camera with Live Web Display

DIY ESP32 MLX90640 IR Thermal Camera with Live Web Display

Updated:May 10, 20262K
IoT Activity Tracker with ESP32 & Accelerometer Gyroscope

IoT Activity Tracker with ESP32 & Accelerometer/Gyroscope

Updated:May 2, 2026

ESP32 IoT Vehicle Motion Analyzer with MPU6050 & LIS3MDL

Updated:April 27, 20261K
High-Accuracy Pitch, Roll, Yaw with ESP32 & BNO08x IMU

High-Accuracy Pitch, Roll, Yaw with ESP32 & BNO08x IMU

Updated:April 27, 20262K
View 17 Comments

17 Comments

  1. Hamza on December 14, 2020 5:36 PM

    How can we receive data from “LoRa Receiver’ in PC or Mobile phone or any Database for further processing?????

    Reply
    • Mr. Alam on December 14, 2020 5:36 PM

      I am making another version of the product next week, where you can display that on web server.

      Reply
  2. Hamza on December 15, 2020 6:07 PM

    ok plz make it fast….,
    in this product where you are displaying data?
    means at which device?

    Reply
    • Mr. Alam on December 15, 2020 6:11 PM

      On mobile phone webpage or on blynk application

      Reply
  3. Max on January 5, 2021 3:55 PM

    Hello, amazing work. Is it possible to connect multiple transmitters to 1 receiver ?
    Thank you in advance !!

    Reply
    • Mr. Alam on January 5, 2021 7:22 PM

      Yes you can connect. But assign each of the sensor the device id so that they can be identified.

      Reply
  4. Max on January 5, 2021 7:13 PM

    Hello, I have tried everything to make the transmitter go to sleep to save battery but what happens then is that all the measurements after it awakens are equal to 0. I really don’t understand my error. Could you explain how to make the transmitter go to sleep please (fast answer very appreciated)

    Reply
  5. Niels on January 6, 2021 5:21 PM

    Where can I find it ?

    Reply
  6. Hussnain Ali on March 19, 2021 11:36 PM

    lora sensor send data to receiver the rang 2 km any solution for that?

    Reply
    • Mr. Alam on March 20, 2021 10:28 AM
      1. Use 5db Antenna
      2. Keep the receiver at maximum height
      3. Maximize the transmitter power in code(default set to 14, set it at 20)
      Reply
  7. chatura on April 5, 2021 1:17 PM

    How to increase the time interval of collecting data to minimize power consumption.

    Reply
    • Alex Newton on April 5, 2021 1:17 PM

      Add delays and send the delay to sleep mode for more longer period of time

      Reply
  8. chatura on April 5, 2021 1:58 PM

    Could you specify the exact place for it. That will be very helpful.

    Reply
  9. RadioLinux on April 9, 2021 2:40 AM

    Is it possible to develop the LoRaWAN OTA IoT sketch to program directly for the Moinsture Sensor? Thanks

    Reply
  10. Roger Burris on April 9, 2021 9:05 PM

    WHERE DO i FIND “I2C_AHT10.h” ?
    PLEASE

    Roger Burris

    Reply
  11. Mamadou Faye on July 7, 2021 2:26 AM

    Hi Sir,
    Can you use multiple wireless sensors sending data to a single Arduino?

    Thanks

    Reply
  12. mitch albert on August 18, 2022 3:39 PM

    great
    do you build 5-15 temperature sensors in close proximity networks to gateway via radio to line of sight receiver for clients as a contractor/consultant? I”m in Denver CO.

    Reply

CommentsCancel reply

Latest Posts
ESP32 Fingerprint Attendance System with Live Web Dashboard

ESP32 Fingerprint Attendance System with Live Web Dashboard

June 21, 2026
IoT Based PM & Air Quality Monitoring System using ESP32

IoT Based PM & Air Quality Monitoring System using ESP32

June 14, 2026
DIY ESP32 MLX90640 IR Thermal Camera with Live Web Display

DIY ESP32 MLX90640 IR Thermal Camera with Live Web Display

May 10, 2026
IoT Activity Tracker with ESP32 & Accelerometer Gyroscope

IoT Activity Tracker with ESP32 & Accelerometer/Gyroscope

May 2, 2026
A Guide to Sourcing Obsolete ICs for Vintage Projects

Beyond AliExpress: A Guide to Sourcing Obsolete ICs for Vintage Projects

April 21, 2026

ESP32 IoT Vehicle Motion Analyzer with MPU6050 & LIS3MDL

April 27, 2026
Building a Smart Sensor Node with a BLE Microcontroller

Building a Smart Sensor Node with a BLE Microcontroller

February 26, 2026
High-Accuracy Pitch, Roll, Yaw with ESP32 & BNO08x IMU

High-Accuracy Pitch, Roll, Yaw with ESP32 & BNO08x IMU

April 27, 2026
Top Posts & Pages
  • ESP32 Fingerprint Attendance System with Live Web Dashboard
    ESP32 Fingerprint Attendance System with Live Web Dashboard
  • IoT AC Energy Meter with PZEM-004T & ESP32 WebServer
    IoT AC Energy Meter with PZEM-004T & ESP32 WebServer
  • 12V DC to 220V AC Inverter Circuit & PCB
    12V DC to 220V AC Inverter Circuit & PCB
  • ESP32 CAN Bus Tutorial | Interfacing MCP2515 CAN Module with ESP32
    ESP32 CAN Bus Tutorial | Interfacing MCP2515 CAN Module with ESP32
  • How to use Modbus RTU with ESP32 to read Sensor Data
    How to use Modbus RTU with ESP32 to read Sensor Data
  • IoT Based ECG Monitoring with AD8232 ECG Sensor & ESP32
    IoT Based ECG Monitoring with AD8232 ECG Sensor & ESP32
  • Buck Converter: Basics, Working, Design & Application
    Buck Converter: Basics, Working, Design & Application
  • MAX30102 & Arduino: Heart Rate + Blood Oxygen Monitoring
    MAX30102 & Arduino: Heart Rate + Blood Oxygen Monitoring
Categories
  • Arduino Projects (197)
  • Articles (60)
    • Learn Electronics (19)
    • Product Review (15)
    • Tech Articles (28)
  • Electronics Circuits (46)
    • 555 Timer Projects (21)
    • Op-Amp Circuits (7)
    • Power Electronics (13)
  • IoT Projects (205)
    • ESP32 MicroPython (7)
    • ESP32 Projects (82)
    • ESP32-CAM Projects (15)
    • ESP8266 Projects (76)
    • LoRa/LoRaWAN Projects (22)
  • Microcontrollers (38)
    • AMB82-Mini IoT AI Camera (4)
    • BLE Projects (18)
    • STM32 Projects (19)
  • Raspberry Pi (93)
    • Raspberry Pi Pico Projects (57)
    • Raspberry Pi Pico W Projects (12)
    • Raspberry Pi Projects (24)
Follow Us
  • Facebook
  • Twitter
  • Pinterest
  • Instagram
  • YouTube
About Us

“‘How to Electronics’ is a vibrant community for electronics enthusiasts and professionals. We deliver latest insights in areas such as Embedded Systems, Power Electronics, AI, IoT, and Robotics. Our goal is to stimulate innovation and provide practical solutions for students, organizations, and industries. Join us to transform learning into a joyful journey of discovery and innovation.

Copyright © How To Electronics. All rights reserved.
  • About Us
  • Disclaimer
  • Privacy Policy
  • Contact Us
  • Advertise With Us

Type above and press Enter to search. Press Esc to cancel.

Ad Blocker Enabled!
Ad Blocker Enabled!
Looks like you're using an ad blocker. Please allow ads on our site. We rely on advertising to help fund our site.