#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);
const int trigPin = 9;
const int echoPin = 10;
const int greenLED = 6;
const int redLED = 7;
const int buzzer = 8;
const int ldrPin = A0;
long duration;
int distance;
int lightValue;
unsigned long startTime;
unsigned long lastBreakTime = 0;
const unsigned long breakInterval = 120000; // 2 minutes
// --- Helper Function to Draw Labels ---
void printLabels() {
lcd.setCursor(0, 0);
lcd.print("Distance: ");
lcd.setCursor(0, 1);
lcd.print("Posture: ");
lcd.setCursor(0, 2);
lcd.print("Screen Time: ");
lcd.setCursor(0, 3);
lcd.print("Light: ");
}
void setup()
{
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
pinMode(greenLED, OUTPUT);
pinMode(redLED, OUTPUT);
pinMode(buzzer, OUTPUT);
lcd.init();
lcd.backlight();
startTime = millis();
lcd.setCursor(0, 0);
lcd.print("Eye Strain &");
lcd.setCursor(0, 1);
lcd.print("Posture Detector");
delay(2000);
lcd.clear();
// Print the static labels ONCE here
printLabels();
}
void loop()
{
// -------- Measure Distance --------
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
distance = duration * 0.034 / 2;
// -------- Read Light --------
lightValue = analogRead(ldrPin);
// -------- Screen Time --------
unsigned long currentTime = millis();
unsigned long totalSeconds = (currentTime - startTime) / 1000;
int minutes = totalSeconds / 60;
int seconds = totalSeconds % 60;
// -------- Default OFF --------
digitalWrite(greenLED, LOW);
digitalWrite(redLED, LOW);
noTone(buzzer);
String posture = "GOOD";
String lightStatus = "SAFE";
// -------- Posture Check --------
if (distance <= 45)
{
posture = "BAD "; // Added space to ensure it overwrites "GOOD" cleanly
digitalWrite(redLED, HIGH);
tone(buzzer, 1000);
}
// -------- Light Check --------
if (lightValue < 200)
{
lightStatus = "LOW "; // Added space for clean overwrite
digitalWrite(redLED, HIGH);
delay(50);
digitalWrite(redLED, LOW);
delay(50);
}
else if (lightValue > 700)
{
lightStatus = "HIGH";
digitalWrite(redLED, HIGH);
delay(50);
digitalWrite(redLED, LOW);
delay(50);
}
else
{
lightStatus = "SAFE";
}
// -------- Ideal Condition --------
if (distance > 45 && lightValue >= 200 && lightValue <= 700)
{
digitalWrite(greenLED, HIGH);
}
// -------- Water Break Reminder --------
if (currentTime - lastBreakTime >= breakInterval)
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("*** WATER BREAK ***");
lcd.setCursor(0, 1);
lcd.print("Drink Water");
lcd.setCursor(0, 2);
lcd.print("Relax Eyes");
for (int i = 0; i < 6; i++)
{
digitalWrite(greenLED, HIGH);
digitalWrite(redLED, HIGH);
tone(buzzer, 1000);
delay(650);
digitalWrite(greenLED, LOW);
digitalWrite(redLED, LOW);
noTone(buzzer);
delay(650);
}
lastBreakTime = currentTime;
lcd.clear();
// Restore the static labels after clearing the screen
printLabels();
}
// -------- Display ONLY Changing Values --------
// Update Distance (Cursor placed right after "Distance: ")
lcd.setCursor(10, 0);
lcd.print(distance);
lcd.print(" cm "); // Spaces clear out any leftover digits if distance goes from 100 to 99
// Update Posture (Cursor placed right after "Posture: ")
lcd.setCursor(9, 1);
lcd.print(posture);
lcd.print(" ");
// Update Screen Time (Cursor placed right after "Screen Time: ")
lcd.setCursor(13, 2);
if (minutes < 10) lcd.print("0");
lcd.print(minutes);
lcd.print(":");
if (seconds < 10) lcd.print("0");
lcd.print(seconds);
lcd.print(" ");
// Update Light Status (Cursor placed right after "Light: ")
lcd.setCursor(7, 3);
lcd.print(lightStatus);
lcd.print(" ");
delay(200);
}