Om Bhatt
Published © MIT

LoRa-Based-Environmental-Monitoring-System

A low-cost ESP32 and LoRa based system for monitoring temperature, humidity, pressure, UV index and air quality in real time.

IntermediateFull instructions provided5 days69
LoRa-Based-Environmental-Monitoring-System

Things used in this project

Hardware components

Espressif ESP32 Development Board - Developer Edition
Espressif ESP32 Development Board - Developer Edition
×1
lora sx1278
×2
Fermion: Multi-function Environmental Module - CCS811+BME280 (Breakout)
DFRobot Fermion: Multi-function Environmental Module - CCS811+BME280 (Breakout)
×1
CJMCU-GUVA-S12SD uv sensor
×1
SHARP GP2Y1014AU0F
×1
1.8 inch tft display
×1
Buzzer
Buzzer
×1

Software apps and online services

Arduino IDE
Arduino IDE

Story

Read more

Custom parts and enclosures

3D box

not necessary but if u want to make

Schematics

Block diagram, Tx circuit diagram and Rx circuit diagram

If required change the pins. I am giving github link u can find Block diagram, Tx circuit diagram and Rx circuit diagram there.

Code

Tx code

Arduino
You have to upload the Tx code in Tx module & Rx one in Rx module. You can change it according to your need.
#include <SPI.h>
#include <LoRa.h>
#include <Wire.h>
#include <Adafruit_BME280.h>

#define LORA_SS   5
#define LORA_RST  14
#define LORA_DIO0 26

#define UV_PIN     34
#define DUST_LED   25
#define DUST_PIN   35

#define UV_MULTIPLIER 3.75

Adafruit_BME280 bme;

float readUV() {
  uint32_t total = 0;
  for (int i = 0; i < 30; i++) total += analogRead(UV_PIN);

  float avg = total / 30.0;
  float voltage = (avg / 4095.0) * 3.3;
  float uv = voltage * UV_MULTIPLIER;

  if (uv < 0.7) uv = 0;
  return uv;
}

float readDust() {
  float sum = 0;

  for (int i = 0; i < 5; i++) {
    digitalWrite(DUST_LED, LOW);
    delayMicroseconds(280);

    int raw = analogRead(DUST_PIN);

    delayMicroseconds(40);
    digitalWrite(DUST_LED, HIGH);
    delayMicroseconds(9680);

    float voltage = raw * (3.3 / 4095.0);
    float dust = 170 * voltage - 0.1;

    if (dust < 0) dust = 0;
    sum += dust;
  }

  return sum / 5.0;
}

String getAQILevel(float dust) {
  if (dust < 350) return "Satisfactory";
  else if (dust < 500) return "Moderate";
  else if (dust < 800) return "Poor";
  else return "Dangerous";
}

String getRain(float hum, float pres) {
  if (hum > 75 && pres < 1008) return "HIGH";
  else if (hum > 65 && pres < 1010) return "MED";
  else return "LOW";
}

void setup() {

  Serial.begin(115200);

  delay(4000);   
  Wire.begin(21,22);
  Wire.setClock(100000);


  bool status = false;

  for (int i = 0; i < 5; i++) {

    if (bme.begin(0x76)) {
      Serial.println("BME @ 0x76 OK");
      status = true;
      break;
    }

    if (bme.begin(0x77)) {
      Serial.println("BME @ 0x77 OK");
      status = true;
      break;
    }

    delay(1000);
  }

  if (!status) {
    Serial.println("BME280 ERROR ");
  }

  pinMode(DUST_LED, OUTPUT);
  digitalWrite(DUST_LED, HIGH);

  LoRa.setPins(LORA_SS, LORA_RST, LORA_DIO0);

  if (!LoRa.begin(433E6)) {
    Serial.println("LoRa FAIL");
    while (1);
  }

  LoRa.setTxPower(20);
  LoRa.setSpreadingFactor(12);
  LoRa.setSignalBandwidth(62.5E3);
  LoRa.setCodingRate4(8);
  LoRa.enableCrc();

  Serial.println("TX READY ");
}

void loop() {

  float temp = bme.readTemperature();
  float hum  = bme.readHumidity();
  float pres = bme.readPressure() / 100.0;

  float uv   = readUV();
  float dust = readDust();

  String AQI  = getAQILevel(dust);
  String RAIN = getRain(hum, pres);

  String data =
    "T:" + String(temp,1) +
    ";H:" + String(hum,1) +
    ";P:" + String(pres,1) +
    ";UV:" + String(uv,1) +
    ";AQ:" + AQI +
    ";R:" + RAIN;

  LoRa.beginPacket();
  LoRa.print(data);
  LoRa.endPacket();

  Serial.println(data);

  delay(6000);
}



//Rx code////////
#include <SPI.h>
#include <LoRa.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>

#define LORA_SS 5
#define LORA_RST 14
#define LORA_DIO0 26

#define TFT_CS 17
#define TFT_DC 2
#define TFT_RST 16

#define BUZZER 15

Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);

String getValue(String data, String key) {
  int start = data.indexOf(key + ":");
  if (start == -1) return "--";
  start += key.length() + 1;

  int end = data.indexOf(';', start);
  if (end == -1) end = data.length();

  return data.substring(start, end);
}

void setup() {

  Serial.begin(115200);

  pinMode(BUZZER, OUTPUT);
  digitalWrite(BUZZER, LOW);

  /* Startup beep */
  digitalWrite(BUZZER, HIGH); delay(500);
  digitalWrite(BUZZER, LOW); delay(500);
  digitalWrite(BUZZER, HIGH); delay(500);
  digitalWrite(BUZZER, LOW);

  tft.initR(INITR_BLACKTAB);
  tft.setRotation(1);
  tft.fillScreen(ST77XX_BLACK);

  tft.setTextColor(ST77XX_WHITE);
  tft.setTextSize(1);

  tft.setCursor(20,5);
  tft.println("LoRa RX Ready");

  LoRa.setPins(LORA_SS, LORA_RST, LORA_DIO0);

  if (!LoRa.begin(433E6)) {
    tft.println("LoRa FAIL");
    while(1);
  }

  LoRa.setSpreadingFactor(12);
  LoRa.setSignalBandwidth(62.5E3);
  LoRa.setCodingRate4(8);
  LoRa.enableCrc();

  tft.setCursor(10,20);
  tft.println("Waiting data...");
}

void loop() {

  int packetSize = LoRa.parsePacket();

  if(packetSize) {

    digitalWrite(BUZZER, HIGH);
    delay(80);
    digitalWrite(BUZZER, LOW);

    String msg = "";

    while (LoRa.available()) {
      msg += (char)LoRa.read();
    }

    int rssi = LoRa.packetRssi();

    String T = getValue(msg,"T");
    String H = getValue(msg,"H");
    String P = getValue(msg,"P");
    String UV = getValue(msg,"UV");
    String AQ = getValue(msg,"AQ");
    String Rain  = getValue(msg,"R");

    tft.fillScreen(ST77XX_BLACK);

    tft.setCursor(5,5);
    tft.println("ENV MONITOR");

    tft.setCursor(5,25);
    tft.print("Temp: "); tft.println(T);

    tft.setCursor(5,40);
    tft.print("Hum : "); tft.println(H);

    tft.setCursor(5,55);
    tft.print("Pres: "); tft.println(P);

    tft.setCursor(5,70);
    tft.print("UV  : "); tft.println(UV);

    tft.setCursor(5,85);
    tft.print("AQI : "); tft.println(AQ);

    tft.setCursor(5,100);
    tft.print("Rain: "); tft.println(R);

    tft.setCursor(5,115);
    tft.print("RSSI: "); tft.println(rssi);

    Serial.println(msg);
  }
}

Credits

Om Bhatt
1 project • 1 follower

Comments