#include <Wire.h>
#define DHTPIN 2
const float TEMP_THRESHOLD_HIGH = 28.0;
const float TEMP_THRESHOLD_LOW = 22.0;
const int SERVO_CLOSED = 0;
const int SERVO_OPEN = 90;
float temperature = 0;
bool windowOpen = false;
unsigned long lastReadTime = 0;
const unsigned long READ_INTERVAL = 2000;
byte data[5] = {0, 0, 0, 0, 0};
byte bits = 0;
byte cnt = 7;
byte idx = 0;
#define LCD_ADDR 0x27
#define LCD_COLS 16
#define LCD_ROWS 2
#define LCD_CLEAR 0x01
#define LCD_HOME 0x02
#define LCD_ENTRY_MODE 0x06
#define LCD_DISPLAY_ON 0x0C
#define LCD_FUNCTION_SET 0x28
#define LCD_SET_DDRAM_ADDR 0x80
void lcdSendCommand(byte cmd) {
Wire.beginTransmission(LCD_ADDR);
Wire.write(0x00);
Wire.write(cmd & 0xF0);
Wire.write((cmd << 4) & 0xF0);
delayMicroseconds(50);
Wire.endTransmission();
}
void lcdSendData(byte data) {
Wire.beginTransmission(LCD_ADDR);
Wire.write(0x40);
Wire.write(data & 0xF0);
Wire.write((data << 4) & 0xF0);
delayMicroseconds(50);
Wire.endTransmission();
}
void lcdInit() {
delay(50);
Wire.beginTransmission(LCD_ADDR);
Wire.write(0x30);
Wire.endTransmission();
delay(5);
Wire.beginTransmission(LCD_ADDR);
Wire.write(0x30);
Wire.endTransmission();
delayMicroseconds(150);
Wire.beginTransmission(LCD_ADDR);
Wire.write(0x30);
Wire.endTransmission();
Wire.beginTransmission(LCD_ADDR);
Wire.write(0x20);
Wire.endTransmission();
// Настройка дисплея
lcdSendCommand(LCD_FUNCTION_SET);
lcdSendCommand(LCD_DISPLAY_ON);
lcdSendCommand(LCD_CLEAR);
lcdSendCommand(LCD_ENTRY_MODE);
delay(2);
}
void lcdPrint(const char* str) {
while (*str) {
lcdSendData(*str++);
}
}
void lcdSetCursor(byte col, byte row) {
byte address = col;
if (row == 1) address += 0x40;
lcdSendCommand(LCD_SET_DDRAM_ADDR | address);
}
void servoWrite(int angle) {
int pulse = map(angle, 0, 180, 544, 2400);
digitalWrite(9, HIGH);
delayMicroseconds(pulse);
digitalWrite(9, LOW);
delay(20);
}
void dhtBegin() {
pinMode(DHTPIN, OUTPUT);
digitalWrite(DHTPIN, HIGH);
delay(250);
}
byte dhtRead() {
byte data = 0;
for (int i = 0; i < 8; i++) {
while (digitalRead(DHTPIN) == LOW);
delayMicroseconds(30); // Ждем 30 мкс
if (digitalRead(DHTPIN) == HIGH) {
data |= (1 << (7 - i));
}
while (digitalRead(DHTPIN) == HIGH);
}
return data;
}
float readTemperature() {
for (int i = 0; i < 5; i++) data[i] = 0;
pinMode(DHTPIN, OUTPUT);
digitalWrite(DHTPIN, LOW);
delay(2);
digitalWrite(DHTPIN, HIGH);
delayMicroseconds(40);
pinMode(DHTPIN, INPUT_PULLUP);
delayMicroseconds(10);
if (digitalRead(DHTPIN) == LOW) {
delayMicroseconds(80);
if (digitalRead(DHTPIN) == HIGH) {
delayMicroseconds(80);
for (int i = 0; i < 40; i++) {
while (digitalRead(DHTPIN) == LOW);
delayMicroseconds(30);
if (digitalRead(DHTPIN) == HIGH) {
data[i/8] |= (1 << (7 - (i % 8)));
}
while (digitalRead(DHTPIN) == HIGH);
}
byte checksum = data[0] + data[1] + data[2] + data[3];
if (data[4] == checksum) {
int tempRaw = (data[2] << 8) | data[3];
if (tempRaw & 0x8000) {
tempRaw = -(tempRaw & 0x7FFF);
}
return tempRaw / 10.0;
}
}
}
return NAN;
}
void setup() {
Serial.begin(9600);
Wire.begin();
lcdInit();
pinMode(9, OUTPUT);
servoWrite(SERVO_CLOSED);
dhtBegin();
lcdPrint("Thermostat v1.0");
delay(2000);
lcdSendCommand(LCD_CLEAR);
lcdPrint("Initializing...");
delay(1000);
lcdSendCommand(LCD_CLEAR);
}
void loop() {
unsigned long currentTime = millis();
if (currentTime - lastReadTime >= READ_INTERVAL) {
lastReadTime = currentTime;
temperature = readTemperature();
if (isnan(temperature)) {
Serial.println("Error reading DHT22!");
lcdSendCommand(LCD_CLEAR);
lcdPrint("DHT Error!");
return;
}
if (temperature > TEMP_THRESHOLD_HIGH && !windowOpen) {
for (int angle = SERVO_CLOSED; angle <= SERVO_OPEN; angle += 5) {
servoWrite(angle);
delay(50);
}
windowOpen = true;
Serial.println("Window: OPEN");
}
else if (temperature < TEMP_THRESHOLD_LOW && windowOpen) {
for (int angle = SERVO_OPEN; angle >= SERVO_CLOSED; angle -= 5) {
servoWrite(angle);
delay(50);
}
windowOpen = false;
Serial.println("Window: CLOSED");
}
Serial.print("Temperature: ");
Serial.print(temperature, 1);
Serial.print("C | Window: ");
Serial.println(windowOpen ? "Open" : "Closed");
lcdSetCursor(0, 0);
lcdPrint("Temp: ");
char tempStr[10];
dtostrf(temperature, 4, 1, tempStr);
lcdPrint(tempStr);
lcdPrint("C ");
lcdSetCursor(0, 1);
lcdPrint("Window: ");
lcdPrint(windowOpen ? "OPEN " : "CLOSED");
for (int i = 12; i < 16; i++) {
lcdSetCursor(i, 1);
lcdPrint(" ");
}
}
delay(100);
}