#include "WiFi.h"
#include "PubSubClient.h"
#include "DHT.h"
#include "Wire.h" // For I2C communication with BMP180
// WiFi Configuration
const char* ssid = "Wokwi-GUEST";
const char* password = "";
// MQTT Broker Configuration
const char* MQTTServer = "broker.hivemq.com";
const char* MQTT_ID = "1cd878b0-5820-4178-8f03-cb5728416b3e";
const int Port = 1883;
// MQTT Topics
const char* topic_humidity = "sensors/humidity";
const char* topic_temperature = "sensors/temperature";
const char* topic_rain = "sensors/rain";
const char* topic_flow_rate = "sensors/flow_rate";
const char* topic_water_level = "sensors/water_level";
const char* topic_ph = "sensors/ph";
const char* topic_bmp_temperature = "sensors/bmp_temperature";
const char* topic_bmp_pressure = "sensors/bmp_pressure";
const char* alert_level1 = "sensors/level1";
const char* alert_level2 = "sensors/level2";
const char* alert_level3 = "sensors/level3";
// MQTT Client
WiFiClient espClient;
PubSubClient client(espClient);
// DHT22 Configuration
#define DHTPIN 15
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
// GPIO Pins
#define RAIN_AO_PIN 34 // Analog output from rain sensor
#define RAIN_DO_PIN 35 // Digital output from rain sensor
#define FLOW_SENSOR_PIN 13 // Flow sensor digital output
#define TRIG_PIN 4 // HC-SR04 Trigger pin
#define ECHO_PIN 5 // HC-SR04 Echo pin
#define PH_SENSOR_PIN 36 // pH sensor analog output
#define BMP_SCL_PIN 22 // BMP180 SCL
#define BMP_SDA_PIN 21 // BMP180 SDA
#define LED_CONNECTED 25
#define LED_DISCONNECTED 26
unsigned long lastSensorReadTime = 0;
const unsigned long sensorInterval = 100; // 100ms interval
// --------- WiFi Connection ---------
void connectWiFi() {
pinMode(LED_CONNECTED, OUTPUT);
pinMode(LED_DISCONNECTED, OUTPUT);
digitalWrite(LED_CONNECTED, LOW);
digitalWrite(LED_DISCONNECTED, HIGH);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
digitalWrite(LED_DISCONNECTED, LOW);
digitalWrite(LED_CONNECTED, HIGH);
}
// --------- MQTT Connection ---------
void reconnectMQTT() {
while (!client.connected()) {
digitalWrite(LED_CONNECTED, LOW);
digitalWrite(LED_DISCONNECTED, HIGH);
if (client.connect(MQTT_ID)) {
digitalWrite(LED_DISCONNECTED, LOW);
digitalWrite(LED_CONNECTED, HIGH);
} else {
delay(5000);
}
}
}
// --------- Sensor Data Reading ---------
float readWaterLevel() {
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
long duration = pulseIn(ECHO_PIN, HIGH, 10000); // Timeout 10ms
if (duration == 0) return -1; // No signal
return duration * 0.034 / 2; // Convert to distance (cm)
}
float readPH() {
int analogValue = analogRead(PH_SENSOR_PIN);
return (analogValue * (14.0 / 4095.0)); // Convert analog value to pH
}
int readRainSensor() {
return analogRead(RAIN_AO_PIN); // Read rain sensor as analog value
}
int readFlowRate() {
int flowValue = pulseIn(FLOW_SENSOR_PIN, HIGH, 10000); // Timeout 10ms
return (flowValue > 0) ? flowValue : -1; // Return -1 if no signal
}
float readBMPSimTemperature() {
Wire.beginTransmission(0x77); // Address of BMP180
// Simulated I2C commands for temperature read
return 25.0; // Replace with actual read logic if necessary
}
float readBMPSimPressure() {
Wire.beginTransmission(0x77); // Address of BMP180
// Simulated I2C commands for pressure read
return 101325; // Replace with actual read logic if necessary
}
void sendSensorData() {
float humidity = dht.readHumidity();
float temperature = dht.readTemperature();
int rainAmount = readRainSensor();
int flowRate = readFlowRate();
float waterLevel = readWaterLevel();
float phValue = readPH();
float bmpTemperature = readBMPSimTemperature();
float bmpPressure = readBMPSimPressure();
// Publish data to MQTT
if (!isnan(humidity)) client.publish(topic_humidity, String(humidity).c_str());
if (!isnan(temperature)) client.publish(topic_temperature, String(temperature).c_str());
client.publish(topic_rain, String(rainAmount).c_str());
if (flowRate >= 0) client.publish(topic_flow_rate, String(flowRate).c_str());
if (waterLevel >= 0) client.publish(topic_water_level, String(waterLevel).c_str());
client.publish(topic_ph, String(phValue).c_str());
client.publish(topic_bmp_temperature, String(bmpTemperature).c_str());
client.publish(topic_bmp_pressure, String(bmpPressure).c_str());
}
void processAlerts(int rainAmount, float waterLevel, int flowRate) {
if (waterLevel < 50 && rainAmount > 500 && flowRate < 15) {
client.publish(alert_level1, "Cảnh báo nhẹ: Điều kiện ổn định nhưng cần theo dõi.");
} else if (waterLevel >= 20 && waterLevel < 50 && rainAmount > 500 && flowRate >= 15 && flowRate < 25) {
client.publish(alert_level2, "Cảnh báo trung bình: Có nguy cơ lũ.");
} else if (waterLevel < 20 && rainAmount > 500 && flowRate >= 25) {
client.publish(alert_level3, "Cảnh báo nghiêm trọng: Lũ lụt có nguy cơ xảy ra.");
}
}
// --------- Main Setup and Loop ---------
void setup() {
Serial.begin(115200);
Serial.println("Khởi động cảm biến...");
dht.begin();
Wire.begin(BMP_SDA_PIN, BMP_SCL_PIN); // Initialize I2C
pinMode(RAIN_AO_PIN, INPUT);
pinMode(RAIN_DO_PIN, INPUT);
pinMode(FLOW_SENSOR_PIN, INPUT);
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
pinMode(PH_SENSOR_PIN, INPUT);
connectWiFi();
client.setServer(MQTTServer, Port);
}
void loop() {
if (!client.connected()) {
reconnectMQTT();
}
client.loop();
unsigned long currentMillis = millis();
if (currentMillis - lastSensorReadTime >= sensorInterval) {
lastSensorReadTime = currentMillis;
// Read and send data
sendSensorData();
// Process alerts
int rainAmount = readRainSensor();
float waterLevel = readWaterLevel();
int flowRate = readFlowRate();
processAlerts(rainAmount, waterLevel, flowRate);
}
}