#define BLYNK_TEMPLATE_ID "TMPL6V2iqc0Zy"
#define BLYNK_TEMPLATE_NAME "Water Quality Monitoring and Alert System"
#define BLYNK_AUTH_TOKEN "bceVvoNOHFvwpQEtskMXKn6jFRxkJ8oW"
#include <WiFi.h>
#include <PubSubClient.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <BlynkSimpleEsp32.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include <Fonts/FreeSans12pt7b.h>
#include <Fonts/FreeSansBold18pt7b.h>
#include <SPI.h>
#include "time.h"
// WiFi & MQTT Settings (Fixed for Wokwi)
const char* ssid = "Wokwi-GUEST";
const char* password = "";
// WiFi & MQTT Client
WiFiClient espClient;
PubSubClient client(espClient);
// Blynk Authentication
BlynkTimer timer;
// 🏷️ Sensor Pins
#define TURBIDITY_PIN 39  // VP (GPIO39)
#define TDS_PIN 36        // VN (GPIO36)
#define DO_PIN 34         // GPIO34
#define ONE_WIRE_BUS 4    // DS18B20 Temperature Sensor (GPIO4)
// DS18B20 Temperature Sensor Setup
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
// Display setup
#define TFT_CS   5
#define TFT_DC   17
#define TFT_RST  4
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
// WiFi & MQTT Setup
void setup() {
    Serial.begin(115200);
    
    // Connect to WiFi (Fixed for Wokwi)
    WiFi.begin(ssid, password);
    unsigned long startAttemptTime = millis();
    const unsigned long wifiTimeout = 10000; // 10 seconds
    while (WiFi.status() != WL_CONNECTED && millis() - startAttemptTime < wifiTimeout) {
      delay(500);
      Serial.print(".");
    }
    if (WiFi.status() == WL_CONNECTED) {
      Serial.println("\WiFi Connected!");
    } else {
      Serial.println("\WiFi Connection Failed. Will retry in loop...");
    }
    // Set NTP server
    configTime(0, 0, "pool.ntp.org");
    while (!time(nullptr)) {
      delay(1000);
      Serial.println("Waiting for time...");
    }
    Serial.println("Time synchronized");
    // Initialize DS18B20 Sensor
    sensors.begin();
    // Initialize Display
    tft.begin();
    tft.setRotation(0); // Portraite
    tft.fillScreen(ILI9341_BLACK);
    tft.setTextSize(1);
    tft.setFont(&FreeSans12pt7b);
    // Connect to Blynk
    Blynk.config(BLYNK_AUTH_TOKEN);
    Blynk.connect();  // will not hang if Blynk server is offline
    // Run sensor data every 5 seconds
    timer.setInterval(5000L, sendSensorData);
}
// Read Sensors & Update Dashboard
void sendSensorData() {
    sensors.requestTemperatures();
    float temperature = sensors.getTempCByIndex(0);
    float turbidity = analogRead(TURBIDITY_PIN) * (5.0 / 4095.0);
    float tds = analogRead(TDS_PIN) * (5.0 / 4095.0);
    float dissolved_oxygen = analogRead(DO_PIN) * (5.0 / 4095.0);
    // Display Data on Serial Monitor
    Serial.print("Temperature: "); Serial.print(temperature); Serial.println(" °C");
    Serial.print("Turbidity: "); Serial.print(turbidity); Serial.println(" V");
    Serial.print("TDS: "); Serial.print(tds); Serial.println(" V");
    Serial.print("Dissolved O₂: "); Serial.print(dissolved_oxygen); Serial.println(" V");
    // Update TFT Display
    tft.fillScreen(ILI9341_BLACK);
    // Show status message (big font)
    tft.setFont(&FreeSansBold18pt7b);
    tft.setTextColor(ILI9341_RED); // Default to red (unsafe)
    tft.setCursor(10, 50);
    bool isSafe = (turbidity <= 3.5 && dissolved_oxygen >= 2.0 && tds <= 2.0 && temperature >= 15 && temperature <= 35);
    if (isSafe) {
      tft.setTextColor(ILI9341_GREEN);
      tft.println("Safe to Swim");
    } else {
      tft.setTextColor(ILI9341_RED);
      tft.println("Water is NOT SAFE");
    }
    // Show sensor readings (small font)
    tft.setFont(&FreeSans12pt7b);
    tft.setTextColor(ILI9341_WHITE);
    tft.setCursor(10, 130);
    tft.print("Turbidity: "); tft.print(turbidity, 2); tft.println(" V");
    tft.setCursor(10, 160);
    tft.print("TDS: "); tft.print(tds, 2); tft.println(" V");
    tft.setCursor(10, 190);
    tft.print("DO: "); tft.print(dissolved_oxygen, 2); tft.println(" V");
    tft.setCursor(10, 220);
    tft.print("Temp: "); tft.print(temperature, 2); tft.println(" °C");
    // Get current time
    time_t now = time(nullptr);
    struct tm* timeinfo = localtime(&now);
    if (timeinfo == nullptr) return; // Skip display update if time is not available yet
    // Format time
    char timeStr[20];
    strftime(timeStr, sizeof(timeStr), "%d/%m %H:%M", timeinfo);
    // Set small font and print in bottom right corner
    tft.setFont(); // Default font
    tft.setTextSize(1);
    int16_t x1, y1;
    uint16_t w, h;
    tft.getTextBounds(timeStr, 0, 0, &x1, &y1, &w, &h);
    tft.setCursor(tft.width() - w - 10, tft.height() - 10);
    tft.setTextColor(ILI9341_YELLOW);
    tft.print(timeStr);
    // Send Data to Blynk Mobile App
    Blynk.virtualWrite(V1, turbidity);
    Blynk.virtualWrite(V2, tds);
    Blynk.virtualWrite(V3, dissolved_oxygen);
    Blynk.virtualWrite(V4, temperature);
    // Send Alert if Water Quality is Unsafe
    String alertMsg = "";
    bool alert = false;
    if (turbidity > 3.5) {
      alertMsg += "Water too cloudy (" + String(turbidity, 2) + " V)\n"; // Triggers alert when values is above 3.5
      alert = true;
    }
    if (dissolved_oxygen < 2.0) {
      alertMsg += "Water oxygen level low (" + String(dissolved_oxygen, 2) + " V)\n"; // Triggers alert when values is below 2.0
      alert = true;
    }
    if (tds > 2.0) {
      alertMsg += "High dissolved solids (" + String(tds, 2) + " V)\n"; // Triggers alert when values is above 2.0
      alert = true;
    }
    if (temperature > 35.0 || temperature < 15.0) {
      alertMsg += "Abnormal Temp (" + String(temperature, 2) + " °C)\n";  // Triggers alert when values is below 15.0 and above 35.0
      alert = true;
    }
    if (alert) {
      Blynk.logEvent("water_quality_alert", alertMsg);
    }
}
void loop() {
  // Reconnect WiFi if disconnected
  if (WiFi.status() != WL_CONNECTED) {
    Serial.println("🔄 Reconnecting WiFi...");
    WiFi.begin(ssid, password);
    delay(500);
  }
  // Keep running Blynk and scheduled tasks
  Blynk.run();
  timer.run();
  if (!Blynk.connected()) {
    Serial.println("⚠️ Blynk not connected.");
  }
}Loading
ds18b20
ds18b20
TDS sensor
DO sensor
Turbidity sensor
Temp sensor
Water Quality Monitering and Alert System