Harun YenisanMehmet Emin Uğur
Published © MIT

Smart Pond/Aquaculture Water Level & Temperature Monitoring

Smart Pond/Aquaculture Water Level & Temperature Monitoring

IntermediateWork in progress24 hours95
Smart Pond/Aquaculture Water Level & Temperature Monitoring

Things used in this project

Hardware components

RAKwireless RAK4631
×1
RAKwireless RAK19003
×1
RAKwireless RAK12005
×1
RAKwireless RAK1906
×1
RAKwireless Solar Panel
×1
RAKwireless RAK7268V2
×1

Software apps and online services

Arduino IDE
Arduino IDE
The Things Industries TheThingsNetwork

Hand tools and fabrication machines

Multitool, Screwdriver
Multitool, Screwdriver

Story

Read more

Code

Smart Pond/Aquaculture Water Level & Temperature Monitoring

Arduino
Smart Pond/Aquaculture Water Level & Temperature Monitoring
#include <LoRaWan-RAK4631.h> // LoRaWAN library for RAK4631
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME680.h> // For RAK1906 (uses BME680 sensor)

// For RAK12005 Water Level Sensor
// RAK12005 is typically assumed to have an analog output.
// This part should be adjusted according to the specific features of the sensor.
#define WATER_LEVEL_SENSOR_PIN WB_A0 // Example analog pin connected to water level sensor

// LoRaWAN Join Settings
// You must obtain these values from your TheThingsNetwork (TTN) console.
String node_device_eui = "AC1F09FFFE0xxxx"; // <<< CHANGE THIS
String node_app_eui = "70B3D57ED000xxxx";   // <<< CHANGE THIS
String node_app_key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; // <<< CHANGE THIS

// LoRaWAN Application Port
#define LORAWAN_APP_PORT 1

// Data Transmission Interval (in seconds)
#define SEND_INTERVAL_SEC 300 // Interval for sending sensor data (5 minutes)

// Sensor Object
Adafruit_BME680 bme; // RAK1906 (BME680) environmental sensor object

// Timer Variable
time_t lastSendTime = 0; // Last sensor data transmission time (millis())

void setup() {
  // Set internal LED as OUTPUT and turn it off initially
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW); 
  
  // Start serial communication (for debug messages)
  Serial.begin(115200);
  while (!Serial); // Wait for serial port to be ready
  Serial.println("Pond/Aquaculture Monitoring Starting...");

  // Set water level sensor pin as input
  pinMode(WATER_LEVEL_SENSOR_PIN, INPUT);

  // Start I2C communication (for BME680)
  Wire.begin();

  // Initialize RAK1906 (BME680) sensor
  // I2C address is typically 0x76 or 0x77.
  if (!bme.begin(0x76)) { 
    Serial.println("RAK1906 BME680 not found, check connection!");
    while (1); 
  }
  // Temperature oversampling setting for BME680 (only temperature is critical in this project)
  bme.setTemperatureOversampling(BME680_OS_8X);
  // Other BME680 settings (humidity, pressure, gas) are not configured as they are not used in this project.
  Serial.println("RAK1906 BME680 successfully initialized.");

  // Initialize and configure LoRaWAN module
  api.lorawan.setMcuStatus(true);         // Set MCU status
  api.lorawan.setDeviceClass(CLASS_A);    // Set device class
  api.lorawan.setRegion(EU868);           // Set LoRaWAN region
  api.lorawan.setDevEui(node_device_eui); // Set Device EUI
  api.lorawan.setAppEui(node_app_eui);   // Set Application EUI
  api.lorawan.setAppKey(node_app_key);   // Set Application Key
  api.lorawan.setConfirm(true);          // Use confirmed messages?
  api.lorawan.setAdaptiveDr(true);       // Use Adaptive Data Rate (ADR)?
  
  Serial.println("Attempting to join LoRaWAN network...");
  api.lorawan.join(); // Start LoRaWAN network join process

  // Initialize timer
  lastSendTime = millis();
}

void loop() {
  // Check LoRaWAN network connection status
  if (api.lorawan.queryNetworkStatus() == LORAWAN_JOINED) {
    // Check if it's time to send data
    if (millis() - lastSendTime > (SEND_INTERVAL_SEC * 1000)) {
      sendSensorData();       // Send sensor data
      lastSendTime = millis(); // Reset timer
    }
  } else {
    // If not connected to LoRaWAN network, try to join again...
    Serial.println("Not connected to LoRaWAN network, trying to join again...");
    api.lorawan.join(); 
    delay(10000); // Wait 10 seconds before retrying
  }
}

// Function to read water level and temperature data and send it via LoRaWAN
void sendSensorData() {
  Serial.println("Reading sensor data...");
  
  // Read raw analog value from water level sensor (example analog reading)
  int rawWaterLevel = analogRead(WATER_LEVEL_SENSOR_PIN);
  // Convert raw value to water level in centimeters
  // This conversion should be adjusted based on your sensor's calibration and setup.
  // For example, 0-4095 (12-bit ADC) -> 0-100 cm
  float waterLevelCm = map(rawWaterLevel, 0, 4095, 0, 100); 

  // Get temperature reading from RAK1906
  bme.performReading();
  float temperature = bme.temperature; // Temperature value

  // Print read data to Serial Monitor
  Serial.printf("Water Level: %.2f cm, Temperature: %.2f C\n", waterLevelCm, temperature);

  // Package data into LoRaWAN payload
  // Payload structure: | Water Level (float) | Temperature (float) |
  uint8_t payload[8]; // 2 floats * 4 bytes = 8 bytes
  memcpy(&payload[0], &waterLevelCm, sizeof(float)); // Water Level
  memcpy(&payload[4], &temperature, sizeof(float));    // Temperature

  Serial.println("Sending LoRaWAN data...");
  // Send payload to LoRaWAN network. Use LORAWAN_APP_PORT and send as confirmed message (true).
  api.lorawan.send(sizeof(payload), payload, LORAWAN_APP_PORT, true); 
}

// LoRaWAN callback functions
// Downlink messages are not processed in this project, but empty functions are defined for library requirements.
void lorawan_rx_handler(lorawan_AppData_t* appData) {
  Serial.printf("Downlink received (not expected in this project): Port %d, Length %d\n", appData->Port, appData->BuffSize);
}

void lorawan_has_joined_handler(void) {
  Serial.println("Successfully joined LoRaWAN network!");
  digitalWrite(LED_BUILTIN, HIGH); // Turn on internal LED after joining network
}

void lorawan_join_failed_handler(void) {
  Serial.println("LoRaWAN network join failed. Retrying...");
  digitalWrite(LED_BUILTIN, LOW); // Turn off internal LED if join fails
}

void lorawan_tx_handler(void) {
  Serial.println("LoRaWAN Tx Done!"); // Inform when data transmission is complete
}

Credits

Harun Yenisan
8 projects • 7 followers
Electronic engineer, working as an IT teacher at the Ministry of National Education.
Mehmet Emin Uğur
9 projects • 9 followers
Computer engineer, working as an IT teacher at the Ministry of National Education.

Comments