#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <DHT.h>
#include <Servo.h>
#include <Adafruit_NeoPixel.h>
// Параметры подключения
#define DHTPIN 2
#define DHTTYPE DHT22
#define PIRPIN 4
#define LIGHT_SENSOR_PIN A0
#define DOOR_SERVO_PIN 3
#define WINDOW_SERVO_PIN 5
#define BUZZER_PIN 6
#define RGB_PIN 7
#define NUM_PIXELS 12
#define BUTTON_UP 11
#define BUTTON_DOWN 12
#define BUTTON_SELECT 10
#define BUTTON_BACK 13
// Инициализация компонентов
LiquidCrystal_I2C lcd(0x27, 20, 4);
DHT dht(DHTPIN, DHTTYPE);
Adafruit_NeoPixel strip(NUM_PIXELS, RGB_PIN, NEO_GRB + NEO_KHZ800);
Servo doorServo;
Servo windowServo;
// Глобальные переменные
int currentPage = 0;
int lightingMode = 0; // 0: Выключено, 1: День, 2: Сигнализация, 3: Ночь
int lightThreshold = 500;
int tempThreshold = 25;
#define TOTAL_PAGES 7
bool alarmActive = false;
// Функции для меню
void displayMenu();
void navigateMenu();
void updateLCD();
// Функции для безопасности
void checkSecurity();
void triggerAlarm();
// Функции для климат-контроля
void checkClimate();
void controlWindow();
// Функции для освещения
void checkLighting();
void controlLightingMode(int mode);
void setup() {
// Инициализация компонентов
lcd.begin(20, 4);
lcd.backlight();
dht.begin();
strip.begin();
strip.show(); // Отключить все светодиоды
doorServo.attach(DOOR_SERVO_PIN);
windowServo.attach(WINDOW_SERVO_PIN);
// Пины кнопок
pinMode(BUTTON_UP, INPUT_PULLUP);
pinMode(BUTTON_DOWN, INPUT_PULLUP);
pinMode(BUTTON_SELECT, INPUT_PULLUP);
pinMode(BUTTON_BACK, INPUT_PULLUP);
// Датчик движения и буззер
pinMode(PIRPIN, INPUT);
pinMode(BUZZER_PIN, OUTPUT); // Убедитесь, что пин настроен как выход
lcd.setCursor(0, 0);
lcd.print("Smart Home");
delay(2000);
lcd.clear();
lcd.print("Sensor Data:");
updateSensorData();
}
void loop() {
navigateMenu();
// Проверка текущей страницы
if (currentPage == 0) { // Страница безопасности
checkSecurity();
} else if (currentPage == 4) { // Страница "Sensor Data"
updateSensorData(); // Обновляем данные на странице
}
checkSecurity();
checkTempForWindow();
checkLighting();
delay(100); // Небольшая задержка для стабильности
}
// -------------------- Функция обновления данных --------------------
void updateSensorData() {
lcd.setCursor(0, 1);
lcd.print("Temp: ");
lcd.print(dht.readTemperature());
lcd.print(" C "); // Пробелы для стирания старых символов
lcd.setCursor(0, 2);
lcd.print("Humid: ");
lcd.print(dht.readHumidity());
lcd.print(" % ");
lcd.setCursor(0, 3);
lcd.print("Light: ");
lcd.print(analogRead(LIGHT_SENSOR_PIN));
lcd.print(" ");
}
// -------------------- Пользовательский интерфейс --------------------
// Увеличиваем количество страниц меню
int subMenuIndex = 0; // Индекс для подменю
int editing = -1; // -1: ничего не редактируем, >=0: редактируем параметр
void displayMenu() {
lcd.clear();
if (editing == -1) { // Обычный режим
switch (currentPage) {
case 0: // Система безопасности
lcd.print("Security:");
lcd.setCursor(0, 1);
lcd.print(alarmActive ? "Enabled" : "Disabled");
lcd.setCursor(0, 2);
lcd.print("Up/Down to toggle");
lcd.setCursor(0, 3);
lcd.print("Select to confirm");
break;
case 1: // Климат-контроль
lcd.print("Climate Ctrl:");
lcd.setCursor(0, 1);
lcd.print("Temp > ");
lcd.print(tempThreshold);
lcd.print(" C");
lcd.setCursor(0, 2);
lcd.print("Up/Down to edit");
lcd.setCursor(0, 3);
lcd.print("Select to confirm");
break;
case 2: // Освещение
lcd.print("Lighting:");
lcd.setCursor(0, 1);
lcd.print("Light < ");
lcd.print(lightThreshold);
lcd.print(" lux");
lcd.setCursor(0, 2);
lcd.print("Up/Down to edit");
lcd.setCursor(0, 3);
lcd.print("Select to confirm");
break;
case 3: // Настройки
lcd.print("Settings:");
lcd.setCursor(0, 1);
lcd.print("Under Development");
break;
case 4: // Страница "Sensor Data"
lcd.print("Sensor Data:");
updateSensorData(); // Первичное заполнение данных
break;
case 5: // Управление дверью
lcd.print("Door Control:");
lcd.setCursor(0, 1);
lcd.print(doorServo.read() > 45 ? "Door: Open" : "Door: Closed");
lcd.setCursor(0, 2);
lcd.print("Select: Toggle");
break;
case 6: // Страница режима освещения
lcd.print("Lighting Mode:");
lcd.setCursor(0, 1);
switch (lightingMode) {
case 0: lcd.print("Off"); break;
case 1: lcd.print("Day"); break;
case 2: lcd.print("Night"); break;
case 3: lcd.print("Auto"); break;
}
lcd.setCursor(0, 2);
lcd.print("Select to toggle");
break;
default:
lcd.print("Invalid Page");
break;
}
}
}
void navigateMenu() {
if (editing == -1) { // Навигация по главному меню
if (!digitalRead(BUTTON_UP)) {
currentPage = (currentPage + 1) % TOTAL_PAGES; // Учитываем новое количество страниц
displayMenu();
delay(200);
} else if (!digitalRead(BUTTON_DOWN)) {
currentPage = (currentPage - 1 + TOTAL_PAGES) % TOTAL_PAGES;
displayMenu();
delay(200);
}
}
// Управление дверью
if (currentPage == 5) {
if (!digitalRead(BUTTON_SELECT)) {
toggleDoor(); // Переключаем состояние двери
displayMenu();
delay(200);
}
}
if (currentPage == 0) {
if (!digitalRead(BUTTON_SELECT)) {
alarmActive = !alarmActive;
displayMenu();
}
}
// Управление режимами освещения
if (currentPage == 6 && editing == -1) {
if (!digitalRead(BUTTON_SELECT)) {
lightingMode = (lightingMode + 1) % 4; // Переключаем режим освещения
displayMenu(); // Обновляем меню для отображения текущего режима
delay(200);
}
}
}
// -------------------- Система безопасности --------------------
void checkSecurity() {
if (digitalRead(PIRPIN) == HIGH && alarmActive) {
triggerAlarm(); // Запускаем сигнализацию
controlLightingMode(2); // Включаем красный свет (сигнализация)
} else if (alarmActive) { // Если сигнализация всё ещё включена
// После завершения сигнала возвращаем управление светом режиму времени суток
checkLighting();
}
}
void triggerAlarm() {
// Включаем красный свет и буззер
controlLightingMode(2); // Красный свет (сигнализация)
for (int i = 0; i < 5; i++) {
tone(BUZZER_PIN, 1000); // Звук с частотой 1000 Гц
delay(300);
noTone(BUZZER_PIN);
delay(300);
}
// После завершения работы сигнализации свет возвращается к текущему режиму
checkLighting();
}
// -------------------- Управление дверью --------------------
void toggleDoor() {
if (doorServo.read() > 45) {
doorServo.write(0); // Закрыть дверь
} else {
doorServo.write(90); // Открыть дверь
}
}
// -------------------- Климат-контроль --------------------
void checkTempForWindow (){
float temp = dht.readTemperature();
if (temp > tempThreshold) {
controlWindow(true);
} else {
controlWindow(false);
}
}
void checkClimate() {
float temp = dht.readTemperature();
lcd.setCursor(0, 0);
lcd.print("Temp: ");
lcd.print(temp);
}
void controlWindow(bool open) {
if (open) {
windowServo.write(90); // Открыть окно
} else {
windowServo.write(0); // Закрыть окно
}
}
// -------------------- Управление освещением --------------------
void checkLighting() {
int lightLevel = analogRead(LIGHT_SENSOR_PIN);
// Обычные режимы освещения
switch (lightingMode) {
case 0: // Выключено
controlLightingMode(0);
break;
case 1: // День
controlLightingMode(1); // Постоянный белый свет
break;
case 2: // Ночь
controlLightingMode(3); // Тусклый синий свет
break;
case 3: // Авто
if (lightLevel < lightThreshold) {
controlLightingMode(1); // Включить свет
} else {
controlLightingMode(0); // Выключить свет
}
break;
}
}
void controlLightingMode(int mode) {
switch (mode) {
case 0: // Выключить
strip.clear();
strip.show();
break;
case 1: // День
for (int i = 0; i < NUM_PIXELS; i++) {
strip.setPixelColor(i, strip.Color(255, 255, 255)); // Белый свет
}
strip.show();
break;
case 2: // Сигнализация (Красный свет)
for (int i = 0; i < NUM_PIXELS; i++) {
strip.setPixelColor(i, strip.Color(255, 0, 0)); // Красный свет
}
strip.show();
break;
case 3: // Ночь (Тусклый синий свет)
for (int i = 0; i < NUM_PIXELS; i++) {
strip.setPixelColor(i, strip.Color(50, 50, 255)); // Тусклый синий свет
}
strip.show();
break;
}
}