#include <Wire.h>
#include <Adafruit_INA219.h>
#include "HX710B.h"
#include <DHT.h>
#include <avr/sleep.h>
#include <avr/wdt.h>
#include <TinyGPS++.h>
#include <SoftwareSerial.h>
// Set the sender's unique address here: change to 100 or 150 for each sender
#define MY_ADDRESS 100
// Sensor Pins
#define SENSOR_LED_PIN 8
#define LDR_SENSOR_PIN 7 // Digital read for LDR
#define DHT_SENSOR_PIN 5 // Digital pin for DHT sensor (temperature & humidity)
#define MHSENSOR_PIN A0 // Moisture sensor (analog)
#define MQ135_SENSOR_PIN A3 // Gas sensor (analog)
#define RAIN_DROP_ANALOG_PIN A1
#define DHT_TYPE DHT11 // Change to DHT22 if needed
const int PRESSURE_DOUT_PIN = 2;
const int PRESSURE_SCLK_PIN = 3;
Adafruit_INA219 ina219;
HX710B pressure_sensor;
DHT dht(DHT_SENSOR_PIN, DHT_TYPE);
const float MAX_BATTERY_VOLTAGE = 8.4;
const float MIN_BATTERY_VOLTAGE = 6.0;
// -------------------------
// GPS related declarations
// -------------------------
SoftwareSerial gpsSerial(4, 6); // (RX, TX) using pins 4 and 6
TinyGPSPlus gps;
// -------------------------
// Function prototypes
void sendSensorPayload();
void sendGPSPayload();
void turnOffSensors();
void goToSleep();
void wakeUpSensors();
bool isFirstTransmission = true;
// Global variables to store last known location
float lastLat = 0.0;
float lastLng = 0.0;
bool hasLastLocation = false; // Flag to check if the last location is set
void setup() {
Serial.begin(115200);
gpsSerial.begin(9600);
Wire.begin();
if (!ina219.begin()) {
Serial.println("Failed to find INA219 chip");
while (1);
}
pressure_sensor.begin(PRESSURE_DOUT_PIN, PRESSURE_SCLK_PIN, 128);
dht.begin();
pinMode(LED_BUILTIN, OUTPUT);
pinMode(SENSOR_LED_PIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH);
digitalWrite(SENSOR_LED_PIN, HIGH);
// Initialize LoRa module with AT commands
Serial.print("AT\r\n");
delay(100);
Serial.print("AT+ADDRESS=");
Serial.print(MY_ADDRESS);
Serial.print("\r\n");
delay(100);
Serial.print("AT+PARAMETER=10,7,1,7\r\n");
delay(100);
Serial.print("AT+BAND=868500000\r\n");
delay(100);
Serial.print("AT+NETWORKID=6\r\n");
delay(100);
Serial.print("AT+CRFOP=15\r\n");
delay(100);
}
void loop() {
// If this sender's address is 150, wait an offset time (e.g., 5 seconds)
// so that the sender with address 100 sends first.
if (MY_ADDRESS == 150) {
delay(4500);
}
digitalWrite(LED_BUILTIN, HIGH);
digitalWrite(SENSOR_LED_PIN, HIGH);
// Read sensors
float moisturePercent = (analogRead(MHSENSOR_PIN) / 1023.0) * 100.0;
float gasPercent = (analogRead(MQ135_SENSOR_PIN) / 1023.0) * 100.0;
int ldrDigital = digitalRead(LDR_SENSOR_PIN);
String lightState = (ldrDigital == HIGH) ? "Nt" : "dt";
float rainPercent = (analogRead(RAIN_DROP_ANALOG_PIN) / 1023.0) * 100.0;
float temperature = dht.readTemperature();
float humidityDHT = dht.readHumidity();
// Pressure sensor measurement
// Assume raw pressure is in hPa, convert to atm (1 atm = 1013.25 hPa)
float rawPressure = pressure_sensor.read();
float pressure_atm = rawPressure / 1013.25;
// Battery calculation
float busVoltage = ina219.getBusVoltage_V();
float battery_percentage = ((busVoltage - MIN_BATTERY_VOLTAGE) / (MAX_BATTERY_VOLTAGE - MIN_BATTERY_VOLTAGE)) * 100.0;
String battery_flag = (battery_percentage <= 25.0) ? "00" :
(battery_percentage <= 50.0) ? "01" :
(battery_percentage <= 75.0) ? "10" : "11";
// Wake up LoRa module before measurement
Serial.print("AT+MODE=0\r\n");
delay(100);
// Measure current right before sending data
float current_mA = ina219.getCurrent_mA();
// Attempt to get a GPS fix for up to 5 seconds
unsigned long gpsStartTime = millis();
while (millis() - gpsStartTime < 5000) {
while (gpsSerial.available()) {
char c = gpsSerial.read();
gps.encode(c);
}
if (gps.location.isValid()) {
lastLat = gps.location.lat(); // Update last known location
lastLng = gps.location.lng(); // Update last known location
hasLastLocation = true; // Set the flag indicating we have a last known location
break; // Exit loop if we have a valid fix
}
}
// Build JSON message with units and include the sender address
// Build JSON payload for GPS data
String gpsJson = "{";
gpsJson += "\"addr\":\"" + String(MY_ADDRESS) + "\",";
if (gps.location.isValid()) {
gpsJson += "\"lt\":\"" + String(gps.location.lat(), 5) + "\",";
gpsJson += "\"lg\":\"" + String(gps.location.lng(), 5) + "\",";
} else if (hasLastLocation) {
// Use last known location if no current fix
gpsJson += "\"lt\":\"" + String(lastLat, 5) + "\",";
gpsJson += "\"lg\":\"" + String(lastLng, 5) + "\",";
} else {
gpsJson += "\"lt\":\"N/A\",";
gpsJson += "\"lg\":\"N/A\",";
}
gpsJson += "\"M\":\"" + String(moisturePercent, 1) + "%\",";
gpsJson += "\"G\":\"" + String(gasPercent, 1) + "%\",";
gpsJson += "\"L\":\"" + lightState + "\",";
gpsJson += "\"R\":\"" + String(rainPercent, 1) + "%\",";
gpsJson += "\"T\":\"" + String(temperature, 1) + " °C\",";
gpsJson += "\"H\":\"" + String(humidityDHT, 1) + "%\",";
gpsJson += "\"P\":\"" + String(pressure_atm, 3) + " atm\",";
gpsJson += "\"B\":\"" + battery_flag + "\",";
gpsJson += "\"C\":\"" + String(current_mA, 2) + "mA\"";
gpsJson += "}";
int gpsPayloadLength = gpsJson.length();
String gpsCommand = "AT+SEND=117," + String(gpsPayloadLength) + "," + MY_ADDRESS + gpsJson;
Serial.print(gpsCommand + "\r\n");
// Wait for LoRa module to confirm sending (max 2 seconds)
unsigned long startTime = millis();
while (millis() - startTime < 2000) {
if (Serial.available()) {
String response = Serial.readString();
if (response.indexOf("OK") != -1) {
break;
}
}
}
// Put LoRa module to sleep
Serial.print("AT+MODE=1\r\n");
delay(500);
// Turn off sensors
turnOffSensors();
// Enter deep sleep for 10 seconds
goToSleep();
delay(8000);
}
void turnOffSensors() {
digitalWrite(LED_BUILTIN, LOW);
digitalWrite(SENSOR_LED_PIN, LOW);
digitalWrite(MHSENSOR_PIN, LOW);
digitalWrite(MQ135_SENSOR_PIN, LOW);
digitalWrite(RAIN_DROP_ANALOG_PIN, LOW);
pinMode(LDR_SENSOR_PIN, INPUT);
pinMode(DHT_SENSOR_PIN, INPUT);
}
void goToSleep() {
Serial.println("Sleep...");
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
cli();
sleep_enable();
// Sleep for 10 seconds total using watchdog timer and delay
wdt_enable(WDTO_8S);
sei();
sleep_cpu();
sleep_disable();
wdt_disable();
delay(10000); // Additional 2 seconds delay to complete 10 seconds
Serial.println("Awake...");
wakeUpSensors();
}
void wakeUpSensors() {
pinMode(LDR_SENSOR_PIN, OUTPUT);
pinMode(DHT_SENSOR_PIN, OUTPUT);
pinMode(MHSENSOR_PIN, OUTPUT);
pinMode(MQ135_SENSOR_PIN, OUTPUT);
pinMode(RAIN_DROP_ANALOG_PIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH);
digitalWrite(SENSOR_LED_PIN, HIGH);
dht.begin();
pressure_sensor.begin(PRESSURE_DOUT_PIN, PRESSURE_SCLK_PIN, 128);
delay(100);
}
ISSUE IS WHEN EVER I SEND THIS PAYLOAD I AM UNABLE TO SEND IT BUT WHEN I COMMENT OUT ONE OR TWO JASON DATA LINE (BASICCALY A SNESOR DATA) IT WORKS.Any one knows the issue although the lora payload size if 240bytes+ so character length is not an issue