#include <dht.h>
#include <LiquidCrystal.h>
#include <pitches.h>
#include <RTClib.h>
#include <ArduinoJson.h>
dht DHT;
RTC_DS1307 rtc;
DateTime now = rtc.now();
#define DHT22_PIN 2
#define SPEAKER_PIN 3
#define RED_LED 13
#define GREEN_LED 5
#define BLUE_LED 4
#define PIR_inputPin 6
#define LDR_PIN_analog A0
#define BUTTON_PIN A3
#define normal_intensity_threshold 500
#define buzzer_duration 3000
#define BUTTON_DEBOUNCE_DELAY 200
#define LCD_UPDATE_INTERVAL 5000
#define SERIAL_UPDATE_INTERVAL 10000
#define MOTION_TIMEOUT 30000
boolean PIR_state = false;
boolean night_mode = false;
boolean buzzer_mode = false;
boolean intensity_level = false; //false = light, true=dark
boolean LCD_backlight = true;
int val = 0;
int pitch = 0;
int display_mode = 0;
float lux = 0.0;
float humidity, temperature = 0.00;
const float GAMMA = 0.7;
const float RL10 = 50;
int analogValue = 0;
float voltage = 0.0;
float resistance = 0.0;
LiquidCrystal lcd(12, 11, 10, 9, 8, 7 );
unsigned long buzzer_start_time = 0;
unsigned long last_button_press_time = 0;
unsigned long last_LCD_updation_time = 0;
unsigned long last_serial_monitor_updation_time = 0;
unsigned long last_motion_time = 0;
void read_DHT();
void read_photoresistor();
void read_PIR();
void check_buzzer();
void check_rtc();
void check_button();
void update_LED();
void update_response_LCD();
void update_serial_monitor();
void check_power_saving();
void setup()
{
Serial.begin(9600);
lcd.begin(16, 2);
lcd.clear();
lcd.print(" SMART HOME ");
lcd.setCursor(0, 1);
lcd.print(" ENVIRONMENT! ");
pinMode(RED_LED, OUTPUT);
pinMode(GREEN_LED, OUTPUT);
pinMode(BLUE_LED, OUTPUT);
pinMode(PIR_inputPin, INPUT);
pinMode(SPEAKER_PIN, OUTPUT);
pinMode(BUTTON_PIN, INPUT_PULLUP);
digitalWrite(RED_LED, LOW);
digitalWrite(GREEN_LED, LOW);
digitalWrite(BLUE_LED, LOW);
if (! rtc.begin())
{
Serial.println("Couldn't find RTC");
Serial.flush();
abort();
}
delay(2000);
}
void loop()
{
read_DHT();
read_photoresistor();
read_PIR();
check_button();
update_response_LCD();
update_LED();
check_buzzer();
update_serial_monitor();
check_power_saving();
check_rtc();
}
void read_DHT()
{
int chk = DHT.read22(DHT22_PIN);
humidity = DHT.humidity;
temperature = DHT.temperature;
}
void update_LED()
{
digitalWrite(BLUE_LED, temperature < 20.00);
digitalWrite(GREEN_LED, temperature >= 20.00 && temperature <= 30.00);
digitalWrite(RED_LED, temperature > 30.00);
}
void read_photoresistor()
{
// Convert the analog value into lux value:
analogValue = analogRead(LDR_PIN_analog);
voltage = analogValue / 1024. * 5;
resistance = 2000 * voltage / (1 - voltage / 5);
lux = pow(RL10 * 1e3 * pow(10, GAMMA) / resistance, (1 / GAMMA));
if (lux < normal_intensity_threshold)
intensity_level = true;
else intensity_level = false;
}
void read_PIR()
{
val = digitalRead(PIR_inputPin); // read input value of PIR sensor
if (val == HIGH)
{
if (PIR_state == LOW)
PIR_state = HIGH;
last_motion_time=millis();
}
else
{
if (PIR_state == HIGH)
PIR_state = LOW;
}
}
void check_buzzer()
{
if (intensity_level == true && PIR_state == HIGH && night_mode == false && buzzer_mode == false )
{
pitch = NOTE_C4;
buzzer_mode = true;
buzzer_start_time = millis();
tone(SPEAKER_PIN, pitch);
}
if (buzzer_mode == true && (millis - buzzer_start_time > buzzer_duration || night_mode == true))
{
pitch = 0;
noTone(SPEAKER_PIN);
buzzer_mode = false;
}
}
void check_rtc()
{ now = rtc.now();
if (now.hour() >= 22 || now.hour() <= 6)
night_mode = true;
else
night_mode = false;
}
void check_button()
{
if (digitalRead(BUTTON_PIN) == LOW && millis() - last_button_press_time > BUTTON_DEBOUNCE_DELAY)
{
display_mode = (display_mode + 1) % 3; // Cycle through 3 display modes
last_button_press_time = millis();
}
}
void update_response_LCD()
{
if (millis() - last_LCD_updation_time >= LCD_UPDATE_INTERVAL)
{
lcd.clear();
lcd.setCursor(0, 0);
switch (display_mode)
{
case 0: // Temperature and Humidity
lcd.print("Temp: ");
lcd.print(temperature, 1);
lcd.print("C");
lcd.setCursor(0, 1);
lcd.print("Humidity: ");
lcd.print(humidity, 1);
lcd.print("%");
break;
case 1: // Light and Motion
lcd.print("Light: ");
lcd.print(intensity_level);
lcd.setCursor(0, 1);
lcd.print("Motion: ");
lcd.print(PIR_state ? "Detected" : "None");
break;
case 2: // Time and Mode
lcd.print("Time: ");
lcd.print(now.hour());
lcd.print(':');
lcd.print(now.minute());
lcd.print(':');
lcd.print(now.second());
lcd.println();
lcd.setCursor(0, 1);
lcd.print("Mode: ");
lcd.print(night_mode ? "Night" : "Day");
break;
}
last_LCD_updation_time = millis();
}
}
void update_serial_monitor()
{
if (millis() - last_serial_monitor_updation_time >= SERIAL_UPDATE_INTERVAL) {
StaticJsonDocument<200> doc;
doc["Temperature"] = temperature;
doc["Humidity"] = humidity;
doc["LightLevel"] = intensity_level;
doc["MotionDetected"] = PIR_state;
char buffer[200];
serializeJson(doc, buffer);
Serial.println(buffer);
last_serial_monitor_updation_time = millis();
}
}
void check_power_saving()
{
if (millis() - last_motion_time >= MOTION_TIMEOUT)
{
if (LCD_backlight)
{
LCD_backlight = false;
lcd.noDisplay();
}
}
else
{
if (!LCD_backlight)
{
LCD_backlight = true;
lcd.display();
}
}
}