#include <LiquidCrystal_I2C.h>
#include <DHT.h>
#include <Servo.h>
#include <Stepper.h>
#define LDR_PIN A0
#define DHT_PIN 2
#define DHT_TYPE DHT22
#define lightRelayPin 3
#define nightButtonPin 13
#define servoPin 5
#define soil_sensor_pin A3
#define windowPin 4
#define buzzenPin 6
const int menuNextButtonPin = 11; // Пин кнопки для переключения на следующее меню
const int menuPrevButtonPin = 12; // Пин кнопки для переключения на предыдущее меню
const float GAMMA = 0.7;
const float RL10 = 50;
LiquidCrystal_I2C lcd(0x27, 20, 4);
DHT dht(DHT_PIN, DHT_TYPE);
Stepper myStepper(200, 7, 8, 9, 10);
Servo tap_servo;
bool isNight = false;
bool lastButtonStateNight = LOW;
bool isWindowOpen = false;
float minimalLux = 10000.0;
bool fanOn = false;
bool waterOn = false;
const int stepsPerRevolution = 180;
int currentMenu = 0; // Текущая страница меню
const int numMenus = 5; // Количество меню, включая новое меню для отображения текущих действий
void setup() {
Serial.begin(9600);
dht.begin();
tap_servo.attach(servoPin);
pinMode(LDR_PIN, INPUT);
pinMode(nightButtonPin, INPUT_PULLUP);
pinMode(windowPin, INPUT_PULLUP);
pinMode(menuNextButtonPin, INPUT_PULLUP);
pinMode(menuPrevButtonPin, INPUT_PULLUP);
pinMode(buzzenPin, OUTPUT); // Настроим пин для buzzer
lcd.init();
lcd.backlight();
pinMode(lightRelayPin, OUTPUT);
myStepper.setSpeed(60);
}
void displayMenu() {
lcd.clear();
switch (currentMenu) {
case 0:
lcd.setCursor(0, 0);
lcd.print("Page 1:");
lcd.setCursor(0, 1);
lcd.print("Fan: ");
lcd.print(fanOn ? "On" : "Off");
lcd.setCursor(0, 2);
lcd.print("Watering: ");
lcd.print(waterOn ? "Off" : "On");
break;
case 1:
lcd.setCursor(0, 0);
lcd.print("Page 2:");
lcd.setCursor(0, 1);
lcd.print("Time: ");
lcd.print(isNight ? "Night" : "Day");
break;
case 2:
lcd.setCursor(0, 0);
lcd.print("Page 3:");
lcd.setCursor(0, 1);
lcd.print("Temp.: ");
lcd.print(dht.readTemperature());
lcd.print(" C");
lcd.setCursor(0, 2);
lcd.print("Air Humid.: ");
lcd.print(dht.readHumidity());
lcd.print(" %");
break;
case 3:
lcd.setCursor(0, 0);
lcd.print("Page 4:");
lcd.setCursor(0, 1);
lcd.print("Soil Humid.: ");
lcd.print(float(analogRead(soil_sensor_pin)/10));
lcd.print(" %");
break;
case 4:
int analogValue = analogRead(LDR_PIN);
float voltage = analogValue / 1024.0 * 5;
float resistance = 2000 * voltage / (1 - voltage / 5);
float lux = pow(RL10 * 1e3 * pow(10, GAMMA) / resistance, (1 / GAMMA));
lcd.setCursor(0, 0);
lcd.print("Page 5:");
lcd.setCursor(0, 1);
lcd.print("Lux: ");
lcd.print(isNight ? minimalLux : lux);
break;
}
}
void handleMenuButtons() {
if (digitalRead(menuNextButtonPin) == LOW) {
currentMenu = (currentMenu + 1) % numMenus;
displayMenu();
delay(300); // Антидребезг
}
if (digitalRead(menuPrevButtonPin) == LOW) {
currentMenu = (currentMenu - 1 + numMenus) % numMenus;
displayMenu();
delay(300); // Антидребезг
}
}
void handleNight() {
bool buttonState = digitalRead(nightButtonPin);
if (buttonState != lastButtonStateNight && buttonState == LOW) {
isNight = !isNight;
displayMenu(); // Обновить меню при изменении
delay(300); // Антидребезг
}
digitalWrite(lightRelayPin, isNight ? LOW : HIGH);
lastButtonStateNight = buttonState;
}
void handleFan(float temperature) {
// Если температура выше 50 градусов, включаем вентилятор
if (temperature > 50) {
myStepper.step(10);
fanOn = true;
} else {
fanOn = false;
}
}
void handleSoilHumidity(int soil_humidity) {
int humidityPercentage = map(soil_humidity, 0, 1023, 0, 100);
if (humidityPercentage < 50) {
tap_servo.write(0); // Закрыть клапан при низкой влажности
waterOn = false;
} else {
tap_servo.write(90); // Открыть клапан при достаточной влажности
waterOn = true;
}
}
void checkCriticalValues() {
float temperature = dht.readTemperature();
int soil_humidity = analogRead(soil_sensor_pin);
int air_humidity = dht.readHumidity();
// Критические значения для buzzer
if (temperature < 0) {
tone(buzzenPin, 1000); // Включить buzzer (тон 1000 Гц) при низкой температуре
} else if (soil_humidity < 204) { // Пример: влажность почвы ниже 20% (значение 204 для аналогового сенсора)
tone(buzzenPin, 1500); // Включить buzzer (тон 1500 Гц) при низкой влажности почвы
} else if (air_humidity < 30) {
tone(buzzenPin, 2000); // Включить buzzer (тон 2000 Гц) при низкой влажности воздуха
} else {
noTone(buzzenPin); // Выключить buzzer, если все параметры в пределах нормы
}
}
void loop() {
handleNight();
handleMenuButtons();
// Обновление меню в реальном времени
displayMenu();
// Обработка сенсоров и вентиляторов
handleSoilHumidity(analogRead(soil_sensor_pin));
handleFan(dht.readTemperature());
// Проверка на критические значения
checkCriticalValues();
delay(500);
}