#include <Wire.h> // библиотека для работы с I2C
#include <RTClib.h> // библиотека для работы с модулем RTC
#include <LiquidCrystal_I2C.h> // библиотека для работы с дисплеем
#include <AccelStepper.h> // библиотека для работы с шаговыми двигателями и драйверами шагового двигателя
#include <NewPing.h> // библиотека для работы с датчиком расстояния
#define LED_PIN 9 // пин для подключения светодиода
#define I2C_ADDR 0x27 // Адрес дисплея
#define LCD_COLUMNS 20 // количество столбцов
#define LCD_LINES 4 // количество строк
// Определение пинов для подключения драйвера шагового двигателя
#define STEP_PIN 7
#define DIR_PIN 6
#define ENABLE_PIN 8
// Определение параметров двигателя
#define STEPS_PER_REV 200 // Количество оборотов
#define SPEED 100 // Скорость вращения в шагах в секунду
#define ACCELERATION 100 // Ускорение вращения в шагах в секунду в квадрате
// Определение параметров таймера
#define OPEN_HOUR 8 // час окрытия штор (0-24)
#define OPEN_MINUTE 0 // минуты открытия (0-60)
#define CLOSE_HOUR 20 // час закрытия штор (0-24)
#define CLOSE_MINUTE 0 // минуты закрытия(0-60)
#define BUTTON_PIN 10 // пин для подключения переключателя
#define POT_PIN A2 // пин для подключения потенциометра
// Переменные для хранения значений времени
int hours; // переменная для значений часов с модуля RTC
int minutes; // переменная для значений минут с модуля RTC
// Переменные для хранения значений расстояния, положения штор, освещенности и т.д.
int distance; // переменная для значений датчика расстояния
int position; // переменная для значений позиции штор по времени
int switchValue; // переменная для значений переключателя
int lightValue; // переменная для значений датчика света
int potValue; // переменная для значений потенциометра
int Value; // преобразуем значение в угол поворота сервопривода
bool manualMode = false; // флаг ручного управления
// Инициализация объектов библиотек
RTC_DS1307 rtc; // инициализация модуля RTC
NewPing sonar(4, 3, 500); // инициализация датчика расстояния
LiquidCrystal_I2C lcd(I2C_ADDR, LCD_COLUMNS, LCD_LINES); // Адрес I2C, количество столбцов и строк
// Создание объекта AccelStepper для управления двигателем
AccelStepper stepper(AccelStepper::DRIVER, STEP_PIN, DIR_PIN);
void setup() {
Serial.begin(9600); // инициализация последовательного порта
pinMode(LED_PIN, OUTPUT); // Настройка пина светодиода
pinMode(BUTTON_PIN, INPUT_PULLUP); // Настройка пина переключателя
Wire.begin(); // инициализация I2C
lcd.init(); // Инициализация дисплея
rtc.begin(); // инициализация модуля RTC
pinMode(ENABLE_PIN, OUTPUT); // Настройка пинов для управления драйвером
digitalWrite(ENABLE_PIN, LOW); // Включение драйвера
// Настройка параметров двигателя
stepper.setMaxSpeed(SPEED); // Скорость вращения в шагах в секунду
stepper.setAcceleration(ACCELERATION); // Ускорение вращения в шагах в секунду в квадрате
}
//Функция ручного управления шторами
void manualControl() {
switchValue = digitalRead(BUTTON_PIN); // Считываем состояние с переключателя
if (switchValue == 1) { // Если переключатель включён
manualMode = true; // Включаем ручной режим управления
while(manualMode == true) { // Пока ручной режим включен
Time(); // Обновляем время на дисплее
lcd.backlight(); // Включение подсветки
lcd.setCursor(0, 1); // Установка курсора в начало 2 строки
lcd.print("Manual mode "); // Вывод текста на дисплей
switchValue = digitalRead(BUTTON_PIN); // Считываем состояние с переключателя
potValue = analogRead(POT_PIN); // Считываем значение потенциометра
Value = map(potValue, 0, 1023, 0, STEPS_PER_REV); // Преобразуем значение потенциометра в количество шагов
// Serial.print(Value);
stepper.moveTo(Value); // Перемещаем шторы на указанное количество шагов
while (stepper.distanceToGo() != 0)
stepper.run();
if (switchValue != 1 && position == 0) { // Если переключатель выключён и шторы открыты
manualMode = false; // Выключаем ручной режим управления
openCurtains(); // Открыть шторы
return; // Завершаем функцию
} else if (switchValue != 1 && position == 1) { // Если переключатель выключён и шторы закрыты
manualMode = false; // Выключаем ручной режим управления
return; // Завершаем функцию
}
}
} else if (switchValue != 1) { // Если переключатель выключён
return; // Завершаем функцию
}
}
void loop() {
Time(); // Вызов функции для получения текущего времени
Timer(); // Вызов функции для автоматического открытия и закрытия штор в заданное время
manualControl(); // Вызов функции для перехода в режим ручного управления
lighting(); // Вызов функции для управления подсветкой дисплея в зависимости от освещённости
distanceSensor(); // Вызов функции для измерения расстояния до объекта
lcd.setCursor(0, 1); // Установка курсора в начало 2 строки
lcd.print("Automatic mode"); // Вывод текста на дисплей
/*
Serial.print(" \nTime: "); // вывод текущего времени в монитор порта
Serial.print(hours);
Serial.print(":");
if (minutes < 10) {
Serial.print("0");
}
Serial.print(minutes);
*/
}
// Функция для получения текущего времени с модуля RTC
void Time() {
DateTime now = rtc.now(); // получение текущего времени из модуля RTC
hours = now.hour(); // получение текущего часа
minutes = now.minute(); // получение текущей минуты
lcd.setCursor(0, 0); // Установка курсора в начало первой строки
lcd.print("Time: "); // Вывод текста на дисплей
lcd.print(hours); // Вывод часов на дисплей
lcd.print(":");
if (minutes < 10) {
lcd.print("0"); // Добавление ведущего нуля, если минуты меньше 10
}
lcd.print(minutes); // Вывод минут на дисплей
if (hours >= OPEN_HOUR && hours < CLOSE_HOUR) { // если текущее время находится в заданном интервале
position = 0; // Шторы открыты(светлое время суток)
} else {
position = 1; // Шторы закрыты (тёмное время суток)
}
}
// Функция для автоматического открытия и закрытия штор в заданное время
// Так же выводит на дисплей время открытия и закрытия штор
void Timer() {
lcd.setCursor(0, 2); // Установка курсора в начало 3 строки
lcd.print("Open curtain: "); // Вывод текста на дисплей
lcd.print(OPEN_HOUR); // Вывод часов на дисплей
lcd.print(":");
if ( OPEN_MINUTE < 10) {
lcd.print("0"); // Добавление ведущего нуля, если минуты меньше 10
}
lcd.print(OPEN_MINUTE); // Вывод минут на дисплей
lcd.setCursor(0, 3); // Установка курсора в начало 4 строки
lcd.print("Close curtain: "); // Вывод текста на дисплей
lcd.print(CLOSE_HOUR); // Вывод часов на дисплей
lcd.print(":");
if (CLOSE_MINUTE < 10) {
lcd.print("0"); // Добавление ведущего нуля, если минуты меньше 10
}
lcd.print(CLOSE_MINUTE); // Вывод минут на дисплей
if (hours == OPEN_HOUR && minutes == OPEN_MINUTE) { // Если текущее время совпадает с временем открытия
openCurtains(); // открыть шторы
} else if (hours == CLOSE_HOUR && minutes == CLOSE_MINUTE) { // Если текущее время совпадает с временем закрытия
closeCurtains(); // закрыть шторы
}
}
// Функция для управления подсветкой дисплея в зависимости от освещённости
bool lighting() {
lightValue = analogRead(A3); // получение значения с датчика освещённости
if (lightValue < 500 && position == 1) { // Если освещённость меньше 500 и шторы закрыты (тёмное время суток)
lcd.noBacklight(); // Выключение подсветки
} else if (lightValue > 500 && position == 0) { //Если освещённость больше 500 и шторы открыты(светлое время суток)
lcd.noBacklight(); // Выключение подсветки
} else if (lightValue < 500 && position == 0) { // Если освещённость меньше 500 и шторы открыты(светлое время суток)
lcd.backlight(); // Включение подсветки
}
// Serial.print(lightValue);
}
// Функция для измерения расстояния до объекта
void distanceSensor() {
distance = sonar.ping_cm(); // получение расстояния до объекта в сантиметрах
if (distance < 50 && position == 0) { // Если расстояние меньше 50 см и шторы открыты (светлое время суток)
digitalWrite(LED_PIN, HIGH); // Включить светодиод
openCurtains(); // открыть шторы
} else if (distance > 50 && position == 0) { // Если расстояние больше 50 см и шторы открыты (светлое время суток)
digitalWrite(LED_PIN, LOW); // Выключить светодиод
}
if (distance < 50 && position == 1) { // Если расстояние меньше 50 см и шторы закрыты (тёмное время суток)
lcd.backlight(); // Включение подсветки
digitalWrite(LED_PIN, HIGH); // Включить светодиод
openCurtains(); // открыть шторы
} else if (distance > 50 && position == 1) { // Если расстояние больше 50 см и шторы закрыты (тёмное время суток)
closeCurtains(); // закрыть шторы
digitalWrite(LED_PIN, LOW); // Выключить светодиод
}
}
// Функция для открытия штор
void openCurtains() {
Serial.println(", Opening curtains"); // вывод сообщения в монитор порта
stepper.moveTo(0); // Перемещение на начальную позицию
while (stepper.distanceToGo() != 0)
stepper.run();
}
// Функция для закрытия штор
void closeCurtains() {
Serial.println(", Closing curtains"); // вывод сообщения в монитор порта
stepper.moveTo(STEPS_PER_REV); // Перемещение на один оборот вперед
while (stepper.distanceToGo() != 0)
stepper.run();
}