#include <PubSubClient.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>
#include <WiFi.h>
#include "ThingSpeak.h"
#include <HTTPClient.h>
#include <ArduinoJson.h>
#define THING_SPEAK_ADDRESS "api.thingspeak.com"
const char* ssid = "Wokwi-GUEST";
const char* password = "";
//***Set server***
const char* mqttServer = "broker.hivemq.com";
int port = 1883;
WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);
// Định nghĩa chân kết nối
const int LCD_SDA_PIN = 19;
const int LCD_SCL_PIN = 18;
LiquidCrystal_I2C lcd(0x27, 20, 4);
const int soilMoisturePin = 32;
const int MOISTURE_THRESHOLD_LOW = 30; // % activate
const int MOISTURE_THRESHOLD_HIGH = 60; // % deactivate
bool warningForSoilMoisture = false;
const int rainDropAnalog = 34;
const int rainDropDigital = 16;
const int HEAVY_RAIN = 300; // heavy rain
const int MODERATE_RAIN = 500; // moderate rain
const float accelerationThreshold = 1.5; // Adjust as needed
const float inclinationThreshold = 30.0; // In degrees
const int LED_RED = 17;
const int LED_YEL = 16;
const int LED_GRE = 4;
const int BUZZ = 14;
Adafruit_MPU6050 mpu;
char *WIFI_NAME = "Wokwi-GUEST";
char *WIFI_PASSWORD = "";
int channelNumber = 2648890; // ThingSpeak channel ID
char *writeApiKey = "1DE6CE4B6PMG6AVI"; // ThingSpeak write API
char *readApiKey = "4FNHDUPQK2ZFIJIB"; // ThingSpeak read API
WiFiClient client;
void mqttConnect() {
while(!mqttClient.connected()) {
Serial.println("Attemping MQTT connection...");
String clientId = "ESP32Client-";
clientId += String(random(0xffff), HEX);
if(mqttClient.connect(clientId.c_str())) {
Serial.println("connected");
//***Subscribe all topic you need***
mqttClient.subscribe("/12345/led");
}
else {
Serial.println("try again in 5 seconds");
delay(5000);
}
}
}
//MQTT Receiver
void callback(char* topic, byte* message, unsigned int length) {
Serial.println(topic);
String strMsg;
for(int i=0; i<length; i++) {
strMsg += (char)message[i];
}
Serial.println(strMsg);
//***Code here to process the received package***
}
void wifiConnect()
{
WiFi.begin(WIFI_NAME, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println(" Connected!");
}
void initSoilMoistureSensor()
{
pinMode(soilMoisturePin, INPUT);
pinMode(LED_RED, OUTPUT);
pinMode(LED_YEL, OUTPUT);
pinMode(LED_GRE, OUTPUT);
pinMode(BUZZ, OUTPUT);
}
void initMPU6050()
{
Serial.println("Initializing MPU6050...");
if (!mpu.begin())
{
Serial.println("Failed to find MPU6050 chip");
while (true)
{
delay(100);
}
}
Serial.println("MPU6050 Found!");
// Các thiết lập MPU6050
mpu.setAccelerometerRange(MPU6050_RANGE_8_G);
mpu.setGyroRange(MPU6050_RANGE_500_DEG);
mpu.setFilterBandwidth(MPU6050_BAND_5_HZ);
Serial.println("MPU6050 initialization complete.");
}
void printMPU6050Settings()
{
Serial.print("Accelerometer range set to: ");
switch (mpu.getAccelerometerRange())
{
case MPU6050_RANGE_2_G:
Serial.println("+-2G");
break;
case MPU6050_RANGE_4_G:
Serial.println("+-4G");
break;
case MPU6050_RANGE_8_G:
Serial.println("+-8G");
break;
case MPU6050_RANGE_16_G:
Serial.println("+-16G");
break;
}
Serial.print("Gyro range set to: ");
switch (mpu.getGyroRange())
{
case MPU6050_RANGE_250_DEG:
Serial.println("+- 250 deg/s");
break;
case MPU6050_RANGE_500_DEG:
Serial.println("+- 500 deg/s");
break;
case MPU6050_RANGE_1000_DEG:
Serial.println("+- 1000 deg/s");
break;
case MPU6050_RANGE_2000_DEG:
Serial.println("+- 2000 deg/s");
break;
}
Serial.print("Filter bandwidth set to: ");
switch (mpu.getFilterBandwidth())
{
case MPU6050_BAND_260_HZ:
Serial.println("260 Hz");
break;
case MPU6050_BAND_184_HZ:
Serial.println("184 Hz");
break;
case MPU6050_BAND_94_HZ:
Serial.println("94 Hz");
break;
case MPU6050_BAND_44_HZ:
Serial.println("44 Hz");
break;
case MPU6050_BAND_21_HZ:
Serial.println("21 Hz");
break;
case MPU6050_BAND_10_HZ:
Serial.println("10 Hz");
break;
case MPU6050_BAND_5_HZ:
Serial.println("5 Hz");
break;
}
}
int readSoilMoistureInput()
{
int analogSoil = analogRead(soilMoisturePin);
// 0 - 4095: status; 0 - 100: percentage
int soilPercentage = map(analogSoil, 0, 4095, 0, 100);
return soilPercentage;
}
void uploadSoil(int soilPercentage)
{
Serial.print("Soil Moisture = ");
Serial.print(soilPercentage);
Serial.println('%');
ThingSpeak.writeFields(channelNumber, writeApiKey);
// delay(15000); // Delay for ThingSpeak to update
}
int readRainDropInput()
{
int rainAmount = analogRead(rainDropAnalog);
Serial.print("Rain amount: ");
Serial.println(rainAmount);
return rainAmount;
}
void uploadRain(int rainAmount, int isRain)
{
Serial.print("Rain Amount = ");
Serial.println(rainAmount);
ThingSpeak.writeFields(channelNumber, writeApiKey);
// delay(15000); // Delay for ThingSpeak to update
}
void extractRainData()
{
Serial.println("Extracting rain data...");
Serial.println(ThingSpeak.readLongField(channelNumber, 2, readApiKey));
}
void uploadAcceleration_Gyro(float gyro_x, float gyro_y, float gyro_z, float temp)
{
Serial.print("Gyro_x = ");
Serial.println(gyro_x);
Serial.print("Gyro_y = ");
Serial.println(gyro_y);
Serial.print("Gyro_z = ");
Serial.println(gyro_z);
Serial.print("Temperature = ");
Serial.println(temp);
ThingSpeak.writeFields(channelNumber, writeApiKey);
// delay(15000); // Delay for ThingSpeak to update
}
void displayOnLCD(int soilPercentage, int isRain, float gx, float gy, float gz)
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Soil moisture: ");
lcd.print(soilPercentage);
lcd.print("%");
lcd.setCursor(0, 1);
lcd.print("Gx:");
lcd.print(gx);
lcd.print(" Gy:");
lcd.print(gy);
lcd.setCursor(0, 2);
lcd.print("Gz:");
lcd.print(gz);
lcd.setCursor(0, 3);
if (isRain == HIGH) {
lcd.print("Raining");
} else {
lcd.print("No raining");
}
}
void setup()
{
Serial.begin(115200);
wifiConnect();
mqttClient.setServer(mqttServer, port);
mqttClient.setCallback(callback);
mqttClient.setKeepAlive(10);
Serial.println("Wi-Fi connected");
Serial.println("Local IP: " + String(WiFi.localIP()));
Serial.println("==========================================");
WiFi.mode(WIFI_STA);
ThingSpeak.begin(client);
Wire.begin(LCD_SDA_PIN, LCD_SCL_PIN); // Khởi tạo Wire
delay(100);
lcd.begin(20, 4);
lcd.backlight();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Hello");
delay(100);
initSoilMoistureSensor();
delay(100);
delay(100);
initMPU6050();
printMPU6050Settings();
}
void loop()
{
int soilPercentage = readSoilMoistureInput();
int rainAmount = readRainDropInput();
int isRain = digitalRead(rainDropDigital);
ThingSpeak.setField(1, soilPercentage);
ThingSpeak.setField(2, rainAmount);
ThingSpeak.setField(3, isRain);
uploadSoil(soilPercentage);
uploadRain(rainAmount, isRain);
sensors_event_t a, g, temp; //a/16384, g/131
mpu.getEvent(&a, &g, &temp);
ThingSpeak.setField(4, g.gyro.x);
ThingSpeak.setField(5, g.gyro.y);
ThingSpeak.setField(6, g.gyro.z);
ThingSpeak.setField(7, temp.temperature);
uploadAcceleration_Gyro(abs(g.gyro.x), abs(g.gyro.y), abs(g.gyro.x), temp.temperature);
displayOnLCD(soilPercentage, isRain, g.gyro.x, g.gyro.y, g.gyro.z);
// Gửi dữ liệu lên MQTT
char buffer[50];
sprintf(buffer, "%d", soilPercentage);
mqttClient.publish("/Landslide/soilMoisture", buffer); // Gửi độ ẩm đất lên MQTT
sprintf(buffer, "%d", rainAmount);
mqttClient.publish("/Landslide/rainAmount", buffer); // Gửi lượng mưa lên MQTT
sprintf(buffer, "%d", isRain);
mqttClient.publish("/Landslide/isRain", buffer); // Gửi thông tin có mưa hay không lên MQTT
sprintf(buffer, "%f", g.gyro.x);
mqttClient.publish("/Landslide/gyroX", buffer); // Gửi gia tốc theo trục X lên MQTT
sprintf(buffer, "%f", g.gyro.y);
mqttClient.publish("/Landslide/gyroY", buffer); // Gửi gia tốc theo trục Y lên MQTT
sprintf(buffer, "%f", g.gyro.z);
mqttClient.publish("/Landslide/gyroZ", buffer); // Gửi gia tốc theo trục Z lên MQTT
sprintf(buffer, "%f", temp.temperature);
mqttClient.publish("/Landslide/temperature", buffer); // Gửi nhiệt độ lên MQTT
if (isRain == 1)
{
Serial.println("Rain detected");
Serial.println("Starting tracking the soil moisture and movement");
extractRainData();
delay(100);
if (soilPercentage > MOISTURE_THRESHOLD_LOW)
{
warningForSoilMoisture = true;
Serial.println("Warning: Alert for soil moisture");
digitalWrite(LED_RED, LOW);
digitalWrite(LED_YEL, HIGH);
digitalWrite(LED_GRE, LOW);
tone(BUZZ, 1000);
}
else if (soilPercentage > MOISTURE_THRESHOLD_HIGH)
{
warningForSoilMoisture = true;
Serial.println("Warning: Danger for soil moisture!!!!");
digitalWrite(LED_RED, HIGH);
digitalWrite(LED_YEL, LOW);
digitalWrite(LED_GRE, LOW);
tone(BUZZ, 1000);
}
if (abs(g.gyro.x) > inclinationThreshold || abs(g.gyro.y) > inclinationThreshold || abs(g.gyro.z) > inclinationThreshold)
{
Serial.println("Warning: Danger for gyro!");
digitalWrite(LED_RED, HIGH);
digitalWrite(LED_YEL, LOW);
digitalWrite(LED_GRE, LOW);
tone(BUZZ, 1000);
}
}
else
{
Serial.println("No rain detected");
digitalWrite(LED_RED, LOW);
digitalWrite(LED_YEL, LOW);
digitalWrite(LED_GRE, HIGH);
noTone(BUZZ);
}
delay(2000); // Delay for readability
noTone(BUZZ);
}