#define BLYNK_PRINT Serial
#define BLYNK_TEMPLATE_ID "TMPL6ZhZufyqA"
#define BLYNK_TEMPLATE_NAME "wator"
#define BLYNK_AUTH_TOKEN "yo_irz_3silctp6m7xXt6lY-KfxBA1uC"
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <WiFi.h>
#include <WiFiClient.h>
#include <HTTPClient.h>
#include <BlynkSimpleEsp32.h>
// WiFi Credentials
char ssid[] = "Wokwi-GUEST";
char pass[] = "";
// LINE Notify Access Token
String lineToken = "83jNlCXVFod5ZNB7S21X7wmUrKTLp1k2YmRlD3KVtua"; // Replace with your LINE Notify Access Token
// Ultrasonic Sensor Pins
#define TRIG_PIN 15
#define ECHO_PIN 4
#define BUZZER_PIN 5
// Variables
long echo;
float distance;
int currentLevel = -1; // Keeps track of current alert level (-1 = undefined)
int notifyCount[3] = {0}; // Array to track LINE Notify count for each level
// LCD Configuration (I2C)
LiquidCrystal_I2C lcd(0x27, 16, 2); // I2C Address: 0x27, 16 columns, 2 rows
void setup() {
Serial.begin(9600);
// Set up I2C pins manually for ESP32
Wire.begin(22, 21); // SDA = D22, SCL = D21
// Initialize pins
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
pinMode(BUZZER_PIN, OUTPUT);
// Initialize LCD
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Initializing...");
// Connect to WiFi
connectToWiFi();
// Connect to Blynk
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Connecting Blynk");
Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
lcd.setCursor(0, 1);
lcd.print("Blynk Connected!");
delay(2000);
lcd.clear();
}
void loop() {
// Check WiFi connection
if (WiFi.status() != WL_CONNECTED) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("WiFi Disconnected!");
delay(3000); // Wait for 3 seconds before retrying
connectToWiFi();
} else {
Blynk.run();
readSensor();
}
}
void connectToWiFi() {
lcd.setCursor(0, 1);
lcd.print("Connecting WiFi");
WiFi.begin(ssid, pass);
int dotCount = 0;
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
lcd.setCursor(15 - dotCount, 1); // Add dots as connecting
lcd.print(".");
dotCount++;
if (dotCount > 15) {
lcd.setCursor(0, 1);
lcd.print("Connecting WiFi");
dotCount = 0;
}
}
lcd.setCursor(0, 1);
lcd.print("WiFi Connected! ");
Serial.println("\nWiFi Connected!");
delay(2000);
}
long previousMillis = 0;
void readSensor() {
if (millis() - previousMillis > 2000) { // Run every 2 seconds
previousMillis = millis();
// Trigger ultrasonic sensor
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
// Read echo time and calculate distance
echo = pulseIn(ECHO_PIN, HIGH);
distance = (echo / 2.0) / 29.1; // Convert to cm
// Display distance on LCD
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Distance:");
lcd.print(distance);
lcd.print(" cm");
// Send distance to API
sendToAPI(distance);
// Determine the alert level based on distance
int newLevel;
if (distance > 50) {
newLevel = 0; // Level 0: Safe Distance
} else if (distance <= 50 && distance >= 20) {
newLevel = 1; // Level 1: Caution
} else {
newLevel = 2; // Level 2: Danger
}
// Handle notifications and actions when level changes
if (newLevel != currentLevel) {
currentLevel = newLevel;
switch (currentLevel) {
case 0: // Safe Distance
lcd.setCursor(0, 1);
lcd.print("Safe Distance");
digitalWrite(BUZZER_PIN, LOW); // Turn off buzzer
sendLineNotify("สถานะปลอดภัย: ระยะห่างคือ " + String(distance) + " ซม.");
resetNotifyCount(); // Reset all notification counts
break;
case 1: // Caution
if (notifyCount[1] == 0) { // Send notification only once
lcd.setCursor(0, 1);
lcd.print("Caution!");
sendLineNotify("สถานะเตือน: ระยะห่างคือ " + String(distance) + " ซม.");
notifyCount[1]++;
}
digitalWrite(BUZZER_PIN, LOW); // Ensure buzzer is off
break;
case 2: // Danger
if (notifyCount[2] == 0) { // Send notification only once
lcd.setCursor(0, 1);
lcd.print("Danger! Too Close");
sendLineNotify("สถานะอันตราย: ระยะห่างคือ " + String(distance) + " ซม. ใกล้เกินไป!");
notifyCount[2]++;
}
digitalWrite(BUZZER_PIN, HIGH); // Turn on buzzer
break;
}
}
// Send distance to Blynk
Blynk.virtualWrite(V0, distance);
// Debugging in Serial Monitor
Serial.print("Distance: ");
Serial.print(distance);
Serial.println(" cm");
}
}
void sendToAPI(float distance) {
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
String apiUrl = "https://sandbox.thaikoon.co.th/APITKS/sensor/esp32wokwi";
http.begin(apiUrl);
http.addHeader("Content-Type", "application/json");
// Prepare JSON payload
String payload = "{\"distance\": " + String(distance) + "}";
Serial.println("Sending to API: " + payload);
int httpResponseCode = http.POST(payload);
if (httpResponseCode > 0) {
String response = http.getString();
Serial.println("Response: " + response);
} else {
Serial.println("Error sending to API.");
}
http.end();
} else {
Serial.println("WiFi not connected. Cannot send to API.");
}
}
void resetNotifyCount() {
// Reset notification counts for all levels
for (int i = 0; i < 3; i++) {
notifyCount[i] = 0;
}
Serial.println("Notification counts reset.");
}
void sendLineNotify(String message) {
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
http.begin("https://notify-api.line.me/api/notify");
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
http.addHeader("Authorization", "Bearer " + lineToken);
String payload = "message=" + message;
int httpResponseCode = http.POST(payload);
if (httpResponseCode > 0) {
Serial.println("LINE Notify Sent!");
} else {
Serial.println("Error sending LINE Notify.");
}
http.end();
} else {
Serial.println("WiFi not connected. Cannot send LINE Notify.");
}
}