|
|
@@ -0,0 +1,259 @@
|
|
|
+// -------- LIBRARIES --------
|
|
|
+#include <Wire.h>
|
|
|
+#include <LiquidCrystal_I2C.h>
|
|
|
+#include <WiFi.h>
|
|
|
+#include <PubSubClient.h>
|
|
|
+#include <DHT.h>
|
|
|
+#include <SFE_BMP180.h>
|
|
|
+// -------- PIN DEFINITIONS --------
|
|
|
+#define DHTPIN 4
|
|
|
+#define DHTTYPE DHT11
|
|
|
+#define LDR_PIN 35 // input only pin (good choice)
|
|
|
+#define RAIN_PIN 34 // analog pin
|
|
|
+#define LED_PIN 2
|
|
|
+// -------- OBJECTS --------
|
|
|
+LiquidCrystal_I2C lcd(0x27, 16, 2);
|
|
|
+DHT dht(DHTPIN, DHTTYPE);
|
|
|
+SFE_BMP180 bmp;
|
|
|
+WiFiClient espClient;
|
|
|
+PubSubClient client(espClient);
|
|
|
+// -------- WIFI & MQTT CREDENTIALS --------
|
|
|
+const char* ssid = "YOUR_WIFI_SSID";
|
|
|
+const char* password = "YOUR_WIFI_PASSWORD";
|
|
|
+const char* mqtt_server = "YOUR_MQTT_BROKER";
|
|
|
+const int mqtt_port = 1883;
|
|
|
+const char* mqtt_topic = "weather/station";
|
|
|
+// -------- VARIABLES --------
|
|
|
+double T, P;
|
|
|
+unsigned long lastSensorRead = 0;
|
|
|
+const long sensorInterval = 2000; // Read sensors every 2 seconds
|
|
|
+unsigned long lastMQTTSend = 0;
|
|
|
+const long mqttInterval = 30000; // Send data every 30 seconds
|
|
|
+
|
|
|
+struct WeatherData {
|
|
|
+ float temperature;
|
|
|
+ float humidity;
|
|
|
+ float pressure;
|
|
|
+ int rainLevel;
|
|
|
+ bool lightDetected;
|
|
|
+ bool valid;
|
|
|
+};
|
|
|
+
|
|
|
+WeatherData currentData;
|
|
|
+// -------- FUNCTIONS --------
|
|
|
+// DHT SENSOR
|
|
|
+void readDHT() {
|
|
|
+ float h = dht.readHumidity();
|
|
|
+ float t = dht.readTemperature();
|
|
|
+ if (isnan(h) || isnan(t)) {
|
|
|
+ Serial.println("DHT Error!");
|
|
|
+ currentData.valid = false;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ currentData.temperature = t;
|
|
|
+ currentData.humidity = h;
|
|
|
+}
|
|
|
+// RAIN SENSOR
|
|
|
+void readRain() {
|
|
|
+ int value = analogRead(RAIN_PIN);
|
|
|
+ value = map(value, 0, 4095, 0, 100);
|
|
|
+ value = 100 - value;
|
|
|
+ currentData.rainLevel = value;
|
|
|
+}
|
|
|
+// PRESSURE SENSOR
|
|
|
+void readPressure() {
|
|
|
+ if (bmp.startTemperature()) {
|
|
|
+ delay(100);
|
|
|
+ if (bmp.getTemperature(T)) {
|
|
|
+ if (bmp.startPressure(3)) {
|
|
|
+ delay(100);
|
|
|
+ if (bmp.getPressure(P, T)) {
|
|
|
+ currentData.pressure = P;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ Serial.println("BMP180 Error");
|
|
|
+ currentData.valid = false;
|
|
|
+ }
|
|
|
+}
|
|
|
+// LDR SENSOR
|
|
|
+void readLDR() {
|
|
|
+ int value = digitalRead(LDR_PIN);
|
|
|
+ currentData.lightDetected = (value == HIGH);
|
|
|
+ digitalWrite(LED_PIN, currentData.lightDetected ? HIGH : LOW);
|
|
|
+}
|
|
|
+// READ ALL SENSORS
|
|
|
+void readSensors() {
|
|
|
+ currentData.valid = true;
|
|
|
+ readDHT();
|
|
|
+ readRain();
|
|
|
+ readPressure();
|
|
|
+ readLDR();
|
|
|
+
|
|
|
+ if (currentData.valid) {
|
|
|
+ Serial.print("Temp: ");
|
|
|
+ Serial.print(currentData.temperature);
|
|
|
+ Serial.print("°C, Humidity: ");
|
|
|
+ Serial.print(currentData.humidity);
|
|
|
+ Serial.print("%, Rain: ");
|
|
|
+ Serial.print(currentData.rainLevel);
|
|
|
+ Serial.print("%, Pressure: ");
|
|
|
+ Serial.print(currentData.pressure);
|
|
|
+ Serial.print(" hPa, Light: ");
|
|
|
+ Serial.println(currentData.lightDetected ? "YES" : "NO");
|
|
|
+ }
|
|
|
+}
|
|
|
+// UPDATE LCD DISPLAY
|
|
|
+void updateDisplay() {
|
|
|
+ if (!currentData.valid) {
|
|
|
+ lcd.setCursor(0, 0);
|
|
|
+ lcd.print("Sensor Error! ");
|
|
|
+ lcd.setCursor(0, 1);
|
|
|
+ lcd.print("Check wiring ");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Display temperature and humidity on first line
|
|
|
+ lcd.setCursor(0, 0);
|
|
|
+ lcd.print("T:");
|
|
|
+ lcd.print(currentData.temperature, 1);
|
|
|
+ lcd.print("C H:");
|
|
|
+ lcd.print(currentData.humidity, 0);
|
|
|
+ lcd.print("%");
|
|
|
+
|
|
|
+ // Display rain and pressure on second line
|
|
|
+ lcd.setCursor(0, 1);
|
|
|
+ lcd.print("R:");
|
|
|
+ lcd.print(currentData.rainLevel);
|
|
|
+ lcd.print("% P:");
|
|
|
+ lcd.print(currentData.pressure, 0);
|
|
|
+ lcd.print(" ");
|
|
|
+}
|
|
|
+// SETUP WIFI
|
|
|
+void setupWiFi() {
|
|
|
+ Serial.println("Connecting to WiFi...");
|
|
|
+ lcd.setCursor(0, 0);
|
|
|
+ lcd.print("WiFi connecting");
|
|
|
+
|
|
|
+ WiFi.begin(ssid, password);
|
|
|
+
|
|
|
+ int attempts = 0;
|
|
|
+ while (WiFi.status() != WL_CONNECTED && attempts < 20) {
|
|
|
+ delay(500);
|
|
|
+ Serial.print(".");
|
|
|
+ attempts++;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (WiFi.status() == WL_CONNECTED) {
|
|
|
+ Serial.println("\nWiFi connected");
|
|
|
+ Serial.println("IP address: ");
|
|
|
+ Serial.println(WiFi.localIP());
|
|
|
+ lcd.setCursor(0, 0);
|
|
|
+ lcd.print("WiFi connected ");
|
|
|
+ } else {
|
|
|
+ Serial.println("Failed to connect to WiFi");
|
|
|
+ lcd.setCursor(0, 0);
|
|
|
+ lcd.print("WiFi failed! ");
|
|
|
+ }
|
|
|
+
|
|
|
+ delay(2000);
|
|
|
+}
|
|
|
+// RECONNECT MQTT
|
|
|
+void reconnectMQTT() {
|
|
|
+ while (!client.connected()) {
|
|
|
+ Serial.print("Attempting MQTT connection...");
|
|
|
+
|
|
|
+ String clientId = "ESP32WeatherStation-";
|
|
|
+ clientId += String(random(0xffff), HEX);
|
|
|
+
|
|
|
+ if (client.connect(clientId.c_str())) {
|
|
|
+ Serial.println("connected");
|
|
|
+ } else {
|
|
|
+ Serial.print("failed, rc=");
|
|
|
+ Serial.print(client.state());
|
|
|
+ Serial.println(" try again in 5 seconds");
|
|
|
+ delay(5000);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+// SEND MQTT DATA
|
|
|
+void sendMQTTData() {
|
|
|
+ if (!currentData.valid || !client.connected()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ String payload = "{";
|
|
|
+ payload += "\"temperature\":" + String(currentData.temperature, 2) + ",";
|
|
|
+ payload += "\"humidity\":" + String(currentData.humidity, 2) + ",";
|
|
|
+ payload += "\"pressure\":" + String(currentData.pressure, 2) + ",";
|
|
|
+ payload += "\"rainLevel\":" + String(currentData.rainLevel) + ",";
|
|
|
+ payload += "\"lightDetected\":" + String(currentData.lightDetected ? "true" : "false");
|
|
|
+ payload += "}";
|
|
|
+
|
|
|
+ if (client.publish(mqtt_topic, payload.c_str())) {
|
|
|
+ Serial.println("MQTT data sent successfully");
|
|
|
+ } else {
|
|
|
+ Serial.println("Failed to send MQTT data");
|
|
|
+ }
|
|
|
+}
|
|
|
+// -------- SETUP --------
|
|
|
+void setup() {
|
|
|
+ Serial.begin(115200);
|
|
|
+
|
|
|
+ // Initialize pins
|
|
|
+ pinMode(LDR_PIN, INPUT);
|
|
|
+ pinMode(RAIN_PIN, INPUT);
|
|
|
+ pinMode(LED_PIN, OUTPUT);
|
|
|
+ digitalWrite(LED_PIN, LOW);
|
|
|
+
|
|
|
+ // Initialize I2C and sensors
|
|
|
+ Wire.begin(21, 22); // SDA, SCL
|
|
|
+ lcd.init();
|
|
|
+ lcd.backlight();
|
|
|
+ dht.begin();
|
|
|
+
|
|
|
+ if (!bmp.begin()) {
|
|
|
+ Serial.println("BMP180 not detected!");
|
|
|
+ }
|
|
|
+
|
|
|
+ // Initialize WiFi
|
|
|
+ setupWiFi();
|
|
|
+
|
|
|
+ // Initialize MQTT
|
|
|
+ client.setServer(mqtt_server, mqtt_port);
|
|
|
+
|
|
|
+ // Initial sensor reading
|
|
|
+ readSensors();
|
|
|
+ updateDisplay();
|
|
|
+
|
|
|
+ lcd.setCursor(0, 0);
|
|
|
+ lcd.print("System Ready");
|
|
|
+ delay(2000);
|
|
|
+ lcd.clear();
|
|
|
+}
|
|
|
+// -------- LOOP --------
|
|
|
+void loop() {
|
|
|
+ unsigned long currentMillis = millis();
|
|
|
+
|
|
|
+ // Reconnect MQTT if needed
|
|
|
+ if (!client.connected()) {
|
|
|
+ reconnectMQTT();
|
|
|
+ }
|
|
|
+ client.loop();
|
|
|
+
|
|
|
+ // Read sensors at regular interval
|
|
|
+ if (currentMillis - lastSensorRead >= sensorInterval) {
|
|
|
+ lastSensorRead = currentMillis;
|
|
|
+ readSensors();
|
|
|
+ updateDisplay();
|
|
|
+ }
|
|
|
+
|
|
|
+ // Send MQTT data at regular interval
|
|
|
+ if (currentMillis - lastMQTTSend >= mqttInterval) {
|
|
|
+ lastMQTTSend = currentMillis;
|
|
|
+ sendMQTTData();
|
|
|
+ }
|
|
|
+
|
|
|
+ delay(100);
|
|
|
+}
|