Miguel Montiel Vega
Published

Smart Crop Monitoring and Irrigation System with LoRaWAN

We’ve built a smart crop monitoring and irrigation system using LoRaWAN for long-range, low-power communication. It collects real-time data

IntermediateWork in progress8 hours112
Smart Crop Monitoring and Irrigation System with LoRaWAN

Things used in this project

Hardware components

SKU: 920430
×1
RAK1907
×1
RAK3172
×1
RAK12035
×1
RAK12003
×1
o RAK1906
×1
RAK1921
×1
o WisGate Edge Lite 2
×1
o Solar Panel
×1

Software apps and online services

Arduino IDE
Arduino IDE
The Things Stack
The Things Industries The Things Stack

Hand tools and fabrication machines

o Screwdriver

Story

Read more

Code

Smart Crop Monitoring and Irrigation System

C/C++
C++
// Project  Smart Crop Monitoring and Irrigation System
// Board: RAK3372 (STM32WL5)
// Base: RAK1907
// Sensors: RAK12027 Soil Moisture Sensor, RAK12032 DS18B20 Temperature Sensor, RAK12030 BME680
// Display: RAK1821 OLED (Optional)
// LoRaWAN Platform: The Things Stack
 
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME680.h> // For BME680
#include <OneWire.h>         // For DS18B20
#include <DallasTemperature.h> // For DS18B20
#include <LoRaWan-RAK3372.h> // LoRaWAN library for RAK3372
#include <SPI.h>
 
// LoRaWAN Configuration (OTAA) - REPLACE WITH YOUR THE THINGS STACK CREDENTIALS!
uint8_t nodeDeviceEUI[8] = {0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX};
uint8_t nodeAppEUI[8] = {0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX};
uint8_t nodeAppKey[16] = {0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX};
 
// LoRaWAN Region Configuration
LoRaMacRegion_t loraWanRegion = LORAMAC_REGION_EU868;
 
// Sensor Pins
#define SOIL_MOISTURE_PIN WB_A0 // Analog pin for soil moisture sensor
#define ONE_WIRE_BUS WB_IO2 // Pin for DS18B20 sensor
 
// Sensor Instances
Adafruit_BME680 bme; // I2C
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
 
// Variables to store sensor readings
float soil_moisture_percent;
float air_temperature, air_humidity, air_pressure;
float soil_temperature;
 
void setup() {
  Serial.begin(115200);
  delay(100);
  Serial.println("Starting IoT Crop Monitoring...");
 
  Wire.begin();
 
  // Initialize BME680
  if (!bme.begin()) {
    Serial.println("Could not find a valid BME680 sensor, check wiring!");
    while (1);
  }
  bme.setTemperatureOversampling(BME680_OVERSAMPLING_8X);
  bme.setHumidityOversampling(BME680_OVERSAMPLING_4X);
  bme.setPressureOversampling(BME680_OVERSAMPLING_4X);
  bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
  bme.setGasHeater(320, 150); // 320 C for 150 ms
 
  // Initialize DS18B20
  sensors.begin();
 
  // Initialize LoRaWAN
  if (api.lorawan.setRegion(loraWanRegion)) {
    Serial.printf("LoRaWAN region set to %d\n", loraWanRegion);
  } else {
    Serial.println("Failed to set LoRaWAN region.");
    while (1);
  }
 
  if (api.lorawan.setAppKey(nodeAppKey) &&
     api.lorawan.setAppEUI(nodeAppEUI) &&
     api.lorawan.setDevEUI(nodeDeviceEUI)) {
    Serial.println("LoRaWAN credentials configured.");
  } else {
    Serial.println("Failed to configure LoRaWAN credentials.");
    while (1);
  }
 
  Serial.println("Attempting to join LoRaWAN network (OTAA)...");
  if (api.lorawan.join()) {
    Serial.println("Joined LoRaWAN network!");
  } else {
    Serial.println("Failed to join LoRaWAN network. Retrying...");
    while(1);
  }
  delay(2000);
}
 
void loop() {
  readSensors();
  sendLoRaWANData();
 
  Serial.println("Entering low power mode...");
  api.system.sleep.all(300000); // Sleep for 5 minutes (300000 ms)
}
 
void readSensors() {
  // Read soil moisture (example of mapping analog value to percentage)
  int soil_analog_val = analogRead(SOIL_MOISTURE_PIN);
  // Assuming 0 is dry and 4095 (for 12-bit ADC) is wet
  soil_moisture_percent = map(soil_analog_val, 0, 4095, 0, 100);
  soil_moisture_percent = constrain(soil_moisture_percent, 0, 100); // Ensure it's between 0 and 100
  Serial.printf("Soil Moisture: %.1f %%\n", soil_moisture_percent);
 
  // Read BME680 (air temperature, humidity, pressure)
  if (!bme.performReading()) {
    Serial.println("Failed to read BME680.");
  } else {
    air_temperature = bme.temperature;
    air_humidity = bme.humidity;
    air_pressure = bme.pressure / 100.0; // hPa
    Serial.printf("Air Temp: %.2f C, Air Hum: %.2f %%, Air Pres: %.2f hPa\n", air_temperature, air_humidity, air_pressure);
  }
 
  // Read DS18B20 (soil temperature)
  sensors.requestTemperatures();
  soil_temperature = sensors.getTempCByIndex(0); // Assuming a single sensor
  if (soil_temperature == DEVICE_DISCONNECTED_C) {
    Serial.println("Failed to read DS18B20.");
  } else {
    Serial.printf("Soil Temp: %.2f C\n", soil_temperature);
  }
}
 
void sendLoRaWANData() {
  // Create a buffer for the LoRaWAN payload
  // Format:
  // Byte 0-1: Soil moisture (x100)
  // Byte 2-3: Air temperature (x100)
  // Byte 4-5: Air humidity (x100)
  // Byte 6-7: Air pressure (x10)
  // Byte 8-9: Soil temperature (x100)
 
  uint8_t payload[10]; // Changed from 3 to 10 based on description
  uint16_t soil_moisture_int = (uint16_t)(soil_moisture_percent * 100);
  int16_t air_temp_int = (int16_t)(air_temperature * 100);
  uint16_t air_hum_int = (uint16_t)(air_humidity * 100);
  uint16_t air_pres_int = (uint16_t)(air_pressure * 10);
  int16_t soil_temp_int = (int16_t)(soil_temperature * 100);
 
  payload[0] = (soil_moisture_int >> 8) & 0xFF;
  payload[1] = soil_moisture_int & 0xFF;
  payload[2] = (air_temp_int >> 8) & 0xFF;
  payload[3] = air_temp_int & 0xFF;
  payload[4] = (air_hum_int >> 8) & 0xFF;
  payload[5] = air_hum_int & 0xFF;
  payload[6] = (air_pres_int >> 8) & 0xFF;
  payload[7] = air_pres_int & 0xFF;
  payload[8] = (soil_temp_int >> 8) & 0xFF;
  payload[9] = soil_temp_int & 0xFF;
 
  Serial.print("Sending LoRaWAN packet: ");
  for (int i = 0; i < sizeof(payload); i++) {
    Serial.printf("%02X ", payload[i]);
  }
  Serial.println();
 
  if (api.lorawan.send(sizeof(payload), payload, 1, true)) {
    Serial.println("LoRaWAN packet sent successfully.");
  } else {
    Serial.println("Failed to send LoRaWAN packet.");
  }
}
 
// Example Payload Formatter (Decoder) for The Things Stack (Custom Javascript)
/*
function decodeUplink(input) {
  var data = {};
  var bytes = input.bytes;
 
  // Decode soil moisture (2 bytes, uint16, x100)
  data.soil_moisture_percent = ((bytes[0] << 8 | bytes[1]) / 100.0);
 
  // Decode air temperature (2 bytes, int16, x100)
  data.air_temperature = ((bytes[2] << 8 | bytes[3]) / 100.0);
 
  // Decode air humidity (2 bytes, uint16, x100)
  data.air_humidity = ((bytes[4] << 8 | bytes[5]) / 100.0);
 
  // Decode air pressure (2 bytes, uint16, x10)
  data.air_pressure = ((bytes[6] << 8 | bytes[7]) / 10.0);
 
  // Decode soil temperature (2 bytes, int16, x100)
  data.soil_temperature = ((bytes[8] << 8 | bytes[9]) / 100.0);
 
  return {
    data: data,
    warnings: [],
    errors: []
  };
}
*/

Credits

Miguel Montiel Vega
11 projects • 9 followers
Teacher at Maude Studio & Erasmus+ project member: "Developing Solutions to Sustainability Using IoT" (2022-1-PT01-KA220-VET-000090202)
Thanks to Jose Miguel fuentes.

Comments