// Схема подключения и симуляция https://wokwi.com/arduino/projects/https://wokwi.com/arduino/projects/322863857963893330
#include <EEPROM.h>
#include <LiquidCrystal_I2C.h> // библиотека для дисплея
LiquidCrystal_I2C LCD(0x27, 16, 2); // присваиваем имя дисплею
#include <PID_v2.h>
#define RELAY_PIN 12
#include "DHT.h"
#define DHTPIN 5
//#define DHTTYPE DHT11
//#define DHTTYPE DHT21
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
#define LED 13
int LEDStatus = LOW;
#define ENCODER_CLK 2 // пин 2 подключаем к CLK энкодера
#define ENCODER_DT 3 // пин 3 подключаем к DT энкодера
#define ENCODER_SW 4 // пин 11 подключаем к SW энкодера
#define T_MAX 40.0 // Установка: максимальная температура
#define T_MIN 37.0 // Установка: минимальная температура
#define H_MAX 70.0 // Установка: максимальная влажность
#define H_MIN 40.0 // Установка: минимальная влажность
#define WindowSize 500
unsigned long windowStartTime;
int lastClk = HIGH;
double Input, Output, T_SETUP = T_MIN, H_SETUP = H_MIN;
double Kp=2, Ki=5, Kd=1.5;
PID T_PID(&Input, &Output, &T_SETUP, Kp, Ki, Kd, DIRECT);
void setup() {
dht.begin();
pinMode(LED, OUTPUT);
pinMode(ENCODER_CLK, INPUT);
pinMode(ENCODER_DT, INPUT);
pinMode(ENCODER_SW, INPUT);
pinMode(RELAY_PIN, OUTPUT);
LCD.init(); // инициализация LCD дисплея и подсветки
LCD.backlight();
T_PID.SetOutputLimits(0, WindowSize);
T_PID.SetMode(AUTOMATIC);
if (EEPROM.read(0) == 255 && EEPROM.read(3) == 255) {
EEPROM.update(0, 0);
EEPROM.update(1, 0);
EEPROM.update(2, 20);
EEPROM.update(3, 66);
}
EEPROM.get(0, T_SETUP);
if (EEPROM.read(4) == 255 && EEPROM.read(7) == 255) {
EEPROM.update(4, 0);
EEPROM.update(5, 0);
EEPROM.update(6, 32);
EEPROM.update(7, 66);
}
EEPROM.get(4, H_SETUP);
}
void loop() {
float T_CURRENT = dht.readTemperature();
float H_CURRENT = dht.readHumidity();
Input = T_CURRENT;
T_PID.Compute();
if (digitalRead(ENCODER_SW) == LOW) {
int newClk = digitalRead(ENCODER_CLK);
if (newClk != lastClk) {
lastClk = newClk;
int dtValue = digitalRead(ENCODER_DT);
if (newClk == LOW && dtValue == HIGH) {
T_SETUP += .1;
if (T_SETUP > T_MAX) T_SETUP = T_MAX;
}
if (newClk == LOW && dtValue == LOW) {
T_SETUP -= .1;
if (T_SETUP < T_MIN) T_SETUP = T_MIN;
}
EEPROM.put(0, T_SETUP);
}
LCD.clear();
LCD.setCursor(0, 0);
LCD.print(T_SETUP, 1);
LCD.print("\xDF ");
LCD.setCursor(6, 0);
LCD.print(H_SETUP, 0);
LCD.print("% ");
} else {
LCD.setCursor(0, 0);
LCD.print(T_CURRENT, 1);
LCD.print("\xDF ");
LCD.setCursor(6, 0);
LCD.print(H_CURRENT, 0);
LCD.print("% ");
LCD.setCursor(0, 1);
LCD.print(Output, 0);
LCD.print("mS ");
LCD.setCursor(6, 1);
LCD.print(map(Output, 0, WindowSize, 0, 100));
LCD.print("% ");
}
if (millis() - windowStartTime >= WindowSize) {
windowStartTime += WindowSize;
if (windowStartTime > millis()) windowStartTime = 0;
}
if (Output < millis() - windowStartTime) {
digitalWrite(RELAY_PIN, LOW);
LEDStatus = LOW;
} else {
digitalWrite(RELAY_PIN, HIGH);
LEDStatus = !LEDStatus;
}
digitalWrite(LED, LEDStatus);
}