Экономим электричество или таймер времени для ночного тарифа в электросетях

в 8:33, , рубрики: arduino, DIY, diy или сделай сам, influxdb, IoT, openhab, opensource, Raspberry Pi, smart home, ночной тариф, программирование микроконтроллеров, реле, реле времени, таймеры, умный дом, Электроника для начинающих

Как часто вам приходится настраивать различные таймеры? Будильник на смартфоне, таймер на хлебопечке, чтобы к завтраку был свежий хлеб, да и мало ли когда нужно что-то начать. Не менее важной оказывается задача вовремя отключить или закончить действие.

Так я столкнулся с задачей автоматизации включения и отключения электроприбора. Можно было бы воспользоваться типовой розеткой с реле времени, но включать надо необычную нагрузку, поэтому контроллер и только контроллер.

Итак, стоит задача включать электрический котел отопления для обогрева дома в ночной период времени, когда тарификация хоть немного щадящая. Что из этого получилось — смотрите ниже.

image

Покупать готовое реле времени за 6-8 тысяч рублей (не говорим о простых девайсах, втыкаемых в розетку), которые будут замыкать нужные контакты по срабатыванию событий или по времени, просто неспортивно. Кроме того, контроллер с аналогичными функциями, а то и с хорошим запасом функционала обойдется раза в 4 дешевле, не говоря о разминке для мозгов. Началось все в новогодние праздники.

Задача работы в строго отведенное время требует знать текущее время и задать границы работы. Все бы хорошо, но желательно менять время работы и иногда подстраивать часы. Кроме того, удобнее реализовать задачу в виде конечного устройства, которое не будет требовать наличия компьютера для смены параметров. Также на контроллер будут повешены дополнительные функции, но это в версии 2.0, а пока — таймер времени.

Отсюда определился список устройств, необходимых для выполнения задачи:

1. Arduino Nano (чем дешевле модуль, тем лучше, так как задачи не ресурсоёмкие);
2. Модуль времени RTC;
3. Модуль реле ( 2 реле);
4. Адаптер питания для ардуино. Был выбран DC-DC преобразователь-стабилизатор 12В-5В;
5. Дисплей 4х20 символов для красоты (в наличии были 4-х строчный и 2-х строчный);
6. Адаптер I2C для дисплея.

Вот так это оказалось соединено в итоге:

image

Собрать это все на макетке было делом достаточно простым. Изучая Хабр, я давненько приметил работу с I2C -шиной и уж больно мне понравился дизайн часов товарища, поэтому я позаимствовал часть его кода и сделал основные часы в таком же стиле.

Дальше шел долгий процесс изучения работы с EEPROM и модулем часов, чтобы при сбое питания таймер времени и сами часы не сбивались. Поначалу часы выключались, но длительное изучение форумов привело к мысли, что в модуле RTC стоит Li-ION аккумулятор и он просто сел от долгого путешествия из Китая в Россию. Поддержка питанием в течении пары суток позволила восполнить разряд и больше время не сбивалось.

Осталось соединить все модули покрепче, написать код и начать отладку.

Скетч реле времени

// Date and time functions using a DS1307 RTC connected via I2C and Wire lib

#include <EEPROM.h>
#include <Wire.h>
#include <DS1307.h>
#include «RTClib.h»
#include <LiquidCrystal_I2C.h>
#define timePIN 10
#define RELE_1 12 //объявляем работу 1 реле на пине 7
#define RELE_2 11 //объявляем работу 2 реле на пине 8

//на пин A4 цепляем SDA монитора и SDA часов
//на пин A5 цепляем SCL монитора и SCL часов

int FullMinutesTimerOn = EEPROM.read(0);
int FullMinutesTimerOff = EEPROM.read(2);
int rtc[7];
byte rr[7];
int ledPin = 13;
LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x27 for a 16 chars and 2 line display
int button1 = 10; //кнопка на пин D10
int button2 = 9; //кнопка на пин D9
int button3 = 8; //кнопка на пин D8
int button4 = 7; //кнопка на пин D7
int button5 = 6; //кнопка на пин D6
int led = 5;
int rejim=0; //переменная режима изменения настроек таймера
int PrevSec=0;
int CurSec=0;
boolean lastButton=LOW;

byte LT[8] =
{

B00111,
B01111,
B11111,
B11111,
B11111,
B11111,
B11111,
B11111
};
byte UB[8] =
{
B11111,
B11111,
B11111,
B00000,
B00000,
B00000,
B00000,
B00000
};
byte RT[8] =
{

B11100,
B11110,
B11111,
B11111,
B11111,
B11111,
B11111,
B11111
};
byte LL[8] =
{

B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
B01111,
B00111
};
byte LB[8] =
{
B00000,
B00000,
B00000,
B00000,
B00000,
B11111,
B11111,
B11111
};
byte LR[8] =
{

B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
B11110,
B11100
};
byte MB[8] =
{
B11111,
B11111,
B11111,
B00000,
B00000,
B00000,
B11111,
B11111
};
byte block[8] =
{
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
B11111
};
// loop counter
int count = 0;

void setup () {
DDRC|=_BV(2) |_BV(3); // POWER:Vcc Gnd
PORTC |=_BV(3); // VCC PINC3
pinMode(ledPin, OUTPUT);
pinMode(timePIN, OUTPUT);
pinMode(RELE_1, OUTPUT); //инициируем реле только на выход
pinMode(RELE_2, OUTPUT); //инициируем реле только на выход
digitalWrite(RELE_1, HIGH); // запускаем реле выключенными
digitalWrite(RELE_2, HIGH); // запускаем реле выключенными

RTC.get(rtc,true);
lcd.init(); // initialize the lcd
lcd.backlight();
lcd.home();

lcd.createChar(0,LT);
lcd.createChar(1,UB);
lcd.createChar(2,RT);
lcd.createChar(3,LL);
lcd.createChar(4,LB);
lcd.createChar(5,LR);
lcd.createChar(6,MB);
lcd.createChar(7,block);

// sets the LCD's rows and colums:
lcd.clear();

RTC.SetOutput(DS1307_SQW32KHZ);
pinMode(led, OUTPUT);
pinMode(button1, INPUT);
pinMode(button2, INPUT);
pinMode(button3, INPUT);
}

void custom0(int x)
{ // uses segments to build the number 0

lcd.setCursor(x,0); // set cursor to column 0, line 0 (first row)
lcd.write(0); // call each segment to create
lcd.write(1); // top half of the number
lcd.write(2);
lcd.setCursor(x, 1); // set cursor to colum 0, line 1 (second row)
lcd.write(3); // call each segment to create
lcd.write(4); // bottom half of the number
lcd.write(5);
}

void custom1(int x)
{
lcd.setCursor(x,0);
lcd.write(1);
lcd.write(2);
lcd.print(" ");
lcd.setCursor(x,1);
lcd.write(4);
lcd.write(7);
lcd.write(4);
}

void custom2(int x)
{
lcd.setCursor(x,0);
lcd.write(6);
lcd.write(6);
lcd.write(2);
lcd.setCursor(x, 1);
lcd.write(3);
lcd.write(4);
lcd.write(4);
}

void custom3(int x)
{
lcd.setCursor(x,0);
lcd.write(6);
lcd.write(6);
lcd.write(2);
lcd.setCursor(x, 1);
lcd.write(4);
lcd.write(4);
lcd.write(5);
}

void custom4(int x)
{
lcd.setCursor(x,0);
lcd.write(3);
lcd.write(4);
lcd.write(7);
lcd.setCursor(x, 1);
lcd.print(" ");
lcd.print(" ");
lcd.write(7);
}

void custom5(int x)
{
lcd.setCursor(x,0);
lcd.write(3);
lcd.write(6);
lcd.write(6);
lcd.setCursor(x, 1);
lcd.write(4);
lcd.write(4);
lcd.write(5);
}

void custom6(int x)
{
lcd.setCursor(x,0);
lcd.write(0);
lcd.write(6);
lcd.write(6);
lcd.setCursor(x, 1);
lcd.write(3);
lcd.write(4);
lcd.write(5);
}

void custom7(int x)
{
lcd.setCursor(x,0);
lcd.write(1);
lcd.write(1);
lcd.write(2);
lcd.setCursor(x, 1);
lcd.print(" ");
lcd.print(" ");
lcd.write(7);
}

void custom8(int x)
{
lcd.setCursor(x,0);
lcd.write(0);
lcd.write(6);
lcd.write(2);
lcd.setCursor(x, 1);
lcd.write(3);
lcd.write(4);
lcd.write(5);
}

void custom9(int x)
{
lcd.setCursor(x,0);
lcd.write(0);
lcd.write(6);
lcd.write(2);
lcd.setCursor(x, 1);
lcd.print(" ");
lcd.print(" ");
lcd.write(7);

}

void digitalClockDisplay(){
// digital clock display of the time

printDigits(rtc[2]/10,0);
printDigits(rtc[2]%10,4);

printDigits(rtc[1]/10,9);
printDigits(rtc[1]%10,13);

if (rtc[0]%10%2==0){
lcd.setCursor(7, 0);
lcd.print("+ ");
lcd.setCursor(7, 1);
lcd.print(" +");
lcd.setCursor(3, 1);
lcd.print("+");
lcd.setCursor(12, 0);
lcd.print("+");
lcd.setCursor(3, 0);
lcd.print(" ");
lcd.setCursor(12, 1);
lcd.print(" ");
}
else
{
lcd.setCursor(7, 0);
lcd.print(" +");
lcd.setCursor(7, 1);
lcd.print("+ ");
lcd.setCursor(3, 0);
lcd.print("+");
lcd.setCursor(12, 1);
lcd.print("+");
lcd.setCursor(3, 1);
lcd.print(" ");
lcd.setCursor(12, 0);
lcd.print(" ");
}
//нарисовали двоеточие

}

void printDigits(int digits, int x){
// utility function for digital clock display: prints preceding colon and leading 0

switch (digits) {
case 0:
custom0(x);
break;
case 1:
custom1(x);
break;
case 2:
custom2(x);
break;
case 3:
custom3(x);
break;
case 4:
custom4(x);
break;
case 5:
custom5(x);
break;
case 6:
custom6(x);
break;
case 7:
custom7(x);
break;
case 8:
custom8(x);
break;
case 9:
custom9(x);
break;

}

}

void loop () {
int hourOn=EEPROM.read(110); //EEPROM.read(110)
int hourOff= EEPROM.read(112);; //EEPROM.read(112)
int minOn= EEPROM.read(111);; //EEPROM.read(111)
int minOff= EEPROM.read(113);; //EEPROM.read(113)

int Hour = rtc[2]; //присваиваем часы
int Minute = rtc[1]; //присваиваем минуты
int Second = rtc[0]; // присваиваем секунды
int FullMinutes = Hour * 60 + Minute; //приводим значение текущего времени к минутам
int FullMinutesTimerOn= hourOn*60+minOn; //приводим значение ВКЛЮЧЕНИЯ таймера к минутам
int FullMinutesTimerOff= hourOff*60+minOff; //приводим значение ВЫКЛЮЧЕНИЯ таймера к минутам
int sutki=0; // по умолчанию, таймер работает в одних сутках

if (hourOff-hourOn < 0) sutki=1; //если время выключения на следующие сутки, то включаем триггер сутки=1
else sutki=0;

if (sutki==1 && (FullMinutes >= FullMinutesTimerOn || FullMinutes <= FullMinutesTimerOff) )
{
lcd.setCursor(16, 2);
lcd.print(«VKL1»);
digitalWrite(RELE_1, LOW);
// если сутки перескакивают, то проверяем время оператором ИЛИ
}
else if (sutki==1)
{
lcd.print(" ");
digitalWrite(RELE_1, HIGH);
}

if (sutki == 0 && (FullMinutes >= FullMinutesTimerOn && FullMinutes <= FullMinutesTimerOff ))
{
lcd.setCursor(16, 2);
lcd.print(«VKL0»);
digitalWrite(RELE_1, LOW);
} // если сутки НЕ перескакивают, то проверяем время оператором И
else if (sutki == 0)
{
lcd.print(" ");
digitalWrite(RELE_1, HIGH);
}

RTC.get(rtc,true);
digitalClockDisplay(); //выводим красивенькие часики на 2 строки
strokatimera();

if (rejim==0)
{
lcd.setCursor(0, 2);
lcd.print («ojidayu komandi»);
}
if (rejim==1)
{
setTimerOn();
}
if (rejim==2)
{
setTimerOff();
}
if (rejim==3)
{
setTime();
}

if (digitalRead (button5) == HIGH)
{
rejim++;
if (rejim>3) rejim=0;
lcd.clear();
//}
}

}

void setTimerOn()
{
int hourOn= EEPROM.read(110);
int minOn= EEPROM.read(111);
lcd.setCursor(0, 2);
lcd.print(«nastroika VKL»);

if (digitalRead(button3)==HIGH) //нажимая верхнюю кнопку меняем часы
{
hourOn++;
if (hourOn >=24) hourOn=0;
}

if (!digitalRead(button4)) //нажимая нижнюю кнопку меняем минуты
{
minOn++;
if (minOn >=60)
{
minOn=0;
hourOn++;
if (hourOn >=24) hourOn=0;
}
}
strokatimera();
if (digitalRead(button2) == HIGH)
{
EEPROM.write(110, hourOn);
EEPROM.write(111, minOn);
lcd.clear();
}
}

void setTimerOff()
{
int hourOff= EEPROM.read(112);
int minOff= EEPROM.read(113);
lcd.setCursor(0, 2);
lcd.print(«nastroika VIKL»);

if (digitalRead(button3)==HIGH) //нажимая верхнюю кнопку меняем часы
{
hourOff++;
if (hourOff >=24) hourOff=0;
}

if (!digitalRead(button4)) //нажимая нижнюю кнопку меняем минуты
{
minOff++;
if (minOff >=60)
{
minOff=0;
hourOff++;
if (hourOff >=24) hourOff=0;
}
}
strokatimera();
if (digitalRead(button2) == HIGH)
{
EEPROM.write(112, hourOff);
EEPROM.write(113, minOff);
lcd.clear();
}
}

void setTime()
{
lcd.setCursor(0, 2);
//lcd.print («nastroika time_test»);
lcd.print («pustaya nastroika»);
}

void strokatimera()
{
int hourOn=EEPROM.read(110); //EEPROM.read(110)
int hourOff= EEPROM.read(112);; //EEPROM.read(112)
int minOn= EEPROM.read(111);; //EEPROM.read(111)
int minOff= EEPROM.read(113);; //EEPROM.read(113)
lcd.setCursor(0, 3); // вывод в последней строчке времени работы таймера
lcd.print(hourOn);
lcd.print(":");
lcd.print(minOn);
lcd.print("-");
lcd.print(hourOff);
lcd.print(":");
lcd.print(minOff);
}

А вот так это работает:

Для меня осталось загадкой, почему контроллер не хочет реагировать на нажатие отдельных кнопок изменения минут и часов, но охотно реагирует на нажатие другой кнопки, меняя минуты. Исходя из этого, допилил код до рабочего, хотя и индусского состояния, так как первый релиз таймера надо запускать в работу, а с остальным разбираться позже. Грешу на перегрев при пайке, хотя вывод на эти контакты стандартного Blink дает нормальное напряжение на пине. На данный момент пин D6 позволяет войти в меню изменения, а пин D9 листает минуты. Может кто подскажет, если сталкивался с подобным?

P.S. Уже после написания статьи я столкнулся с тем, что задачи, поставленные перед контроллером, надо расширять. Дело в том, что данный контроллер управляет электрическим котлом в дачном доме, а с ростом температуры стала повышаться влажность. Пришлось добавить в систему вентиляции канальный вентилятор аналогичный этому image и на второе реле повесить его включение. Опытным путем было установлено, что удачнее всего будет включать его каждый час на заданный промежуток времени. При этом включается он только с 9 до 21 часа, а ночью тепло из дома не выбрасывается. Регулировка времени включенного состояния также производится с кнопок, а вот время работы пока зашито в программе. На данный момент вытяжка включается на 10 минут каждый час. Оставлен задел на то, чтобы включать вытяжку автоматически, когда включается освещение в ванной или туалете.
Текущий код, который уверенно работает уже месяц, ниже:

Действующий код

// Date and time functions using a DS1307 RTC connected via I2C and Wire lib

#include <EEPROM.h>
#include <Wire.h>
#include <DS1307.h>
#include «RTClib.h»
#include <LiquidCrystal_I2C.h>
//#define timePIN 10
#define RELE_1 12 //объявляем работу 1 реле на пине 7
#define RELE_2 11 //объявляем работу 2 реле на пине 8

//на пин A4 цепляем SDA монитора и SDA часов
//на пин A5 цепляем SCL монитора и SCL часов

int FullMinutesTimerOn = EEPROM.read(0);
int FullMinutesTimerOff = EEPROM.read(2);
int rtc[7];
byte rr[7];
int ledPin = 13;
LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x27 for a 16 chars and 2 line display
int button1 = 10; //кнопка на пин D10
int button2 = 9; //кнопка на пин D9
int button3 = 8; //кнопка на пин D8
int button4 = 7; //кнопка на пин D7
int button5 = 6; //кнопка на пин D6
int led = 5;
int rejim=0; //переменная режима изменения настроек таймера
int PrevSec=0;
int CurSec=0;
boolean lastButton=LOW;

byte LT[8] =
{

B00111,
B01111,
B11111,
B11111,
B11111,
B11111,
B11111,
B11111
};
byte UB[8] =
{
B11111,
B11111,
B11111,
B00000,
B00000,
B00000,
B00000,
B00000
};
byte RT[8] =
{

B11100,
B11110,
B11111,
B11111,
B11111,
B11111,
B11111,
B11111
};
byte LL[8] =
{

B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
B01111,
B00111
};
byte LB[8] =
{
B00000,
B00000,
B00000,
B00000,
B00000,
B11111,
B11111,
B11111
};
byte LR[8] =
{

B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
B11110,
B11100
};
byte MB[8] =
{
B11111,
B11111,
B11111,
B00000,
B00000,
B00000,
B11111,
B11111
};
byte block[8] =
{
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
B11111
};
// loop counter
int count = 0;

void setup () {
DDRC|=_BV(2) |_BV(3); // POWER:Vcc Gnd
PORTC |=_BV(3); // VCC PINC3
pinMode(ledPin, OUTPUT);
//pinMode(timePIN, OUTPUT);
pinMode(RELE_1, OUTPUT); //инициируем реле только на выход
pinMode(RELE_2, OUTPUT); //инициируем реле только на выход
digitalWrite(RELE_1, HIGH); // запускаем реле выключенными
digitalWrite(RELE_2, HIGH); // запускаем реле выключенными

RTC.get(rtc,true);
lcd.init(); // initialize the lcd
lcd.backlight();
lcd.home();

lcd.createChar(0,LT);
lcd.createChar(1,UB);
lcd.createChar(2,RT);
lcd.createChar(3,LL);
lcd.createChar(4,LB);
lcd.createChar(5,LR);
lcd.createChar(6,MB);
lcd.createChar(7,block);

// sets the LCD's rows and colums:
lcd.clear();

RTC.SetOutput(DS1307_SQW32KHZ);
pinMode(led, OUTPUT);
pinMode(button1, INPUT);
pinMode(button2, INPUT);
pinMode(button3, INPUT);
}

void custom0(int x)
{ // uses segments to build the number 0

lcd.setCursor(x,0); // set cursor to column 0, line 0 (first row)
lcd.write(0); // call each segment to create
lcd.write(1); // top half of the number
lcd.write(2);
lcd.setCursor(x, 1); // set cursor to colum 0, line 1 (second row)
lcd.write(3); // call each segment to create
lcd.write(4); // bottom half of the number
lcd.write(5);
}

void custom1(int x)
{
lcd.setCursor(x,0);
lcd.write(1);
lcd.write(2);
lcd.print(" ");
lcd.setCursor(x,1);
lcd.write(4);
lcd.write(7);
lcd.write(4);
}

void custom2(int x)
{
lcd.setCursor(x,0);
lcd.write(6);
lcd.write(6);
lcd.write(2);
lcd.setCursor(x, 1);
lcd.write(3);
lcd.write(4);
lcd.write(4);
}

void custom3(int x)
{
lcd.setCursor(x,0);
lcd.write(6);
lcd.write(6);
lcd.write(2);
lcd.setCursor(x, 1);
lcd.write(4);
lcd.write(4);
lcd.write(5);
}

void custom4(int x)
{
lcd.setCursor(x,0);
lcd.write(3);
lcd.write(4);
lcd.write(7);
lcd.setCursor(x, 1);
lcd.print(" ");
lcd.print(" ");
lcd.write(7);
}

void custom5(int x)
{
lcd.setCursor(x,0);
lcd.write(3);
lcd.write(6);
lcd.write(6);
lcd.setCursor(x, 1);
lcd.write(4);
lcd.write(4);
lcd.write(5);
}

void custom6(int x)
{
lcd.setCursor(x,0);
lcd.write(0);
lcd.write(6);
lcd.write(6);
lcd.setCursor(x, 1);
lcd.write(3);
lcd.write(4);
lcd.write(5);
}

void custom7(int x)
{
lcd.setCursor(x,0);
lcd.write(1);
lcd.write(1);
lcd.write(2);
lcd.setCursor(x, 1);
lcd.print(" ");
lcd.print(" ");
lcd.write(7);
}

void custom8(int x)
{
lcd.setCursor(x,0);
lcd.write(0);
lcd.write(6);
lcd.write(2);
lcd.setCursor(x, 1);
lcd.write(3);
lcd.write(4);
lcd.write(5);
}

void custom9(int x)
{
lcd.setCursor(x,0);
lcd.write(0);
lcd.write(6);
lcd.write(2);
lcd.setCursor(x, 1);
lcd.print(" ");
lcd.print(" ");
lcd.write(7);

}

void digitalClockDisplay(){
// digital clock display of the time

printDigits(rtc[2]/10,0);
printDigits(rtc[2]%10,4);

printDigits(rtc[1]/10,9);
printDigits(rtc[1]%10,13);

if (rtc[0]%10%2==0){
lcd.setCursor(7, 0);
lcd.print("+ ");
lcd.setCursor(7, 1);
lcd.print(" +");
lcd.setCursor(3, 1);
lcd.print("+");
lcd.setCursor(12, 0);
lcd.print("+");
lcd.setCursor(3, 0);
lcd.print(" ");
lcd.setCursor(12, 1);
lcd.print(" ");
}
else
{
lcd.setCursor(7, 0);
lcd.print(" +");
lcd.setCursor(7, 1);
lcd.print("+ ");
lcd.setCursor(3, 0);
lcd.print("+");
lcd.setCursor(12, 1);
lcd.print("+");
lcd.setCursor(3, 1);
lcd.print(" ");
lcd.setCursor(12, 0);
lcd.print(" ");
}
//нарисовали двоеточие

}

void printDigits(int digits, int x){
// utility function for digital clock display: prints preceding colon and leading 0

switch (digits) {
case 0:
custom0(x);
break;
case 1:
custom1(x);
break;
case 2:
custom2(x);
break;
case 3:
custom3(x);
break;
case 4:
custom4(x);
break;
case 5:
custom5(x);
break;
case 6:
custom6(x);
break;
case 7:
custom7(x);
break;
case 8:
custom8(x);
break;
case 9:
custom9(x);
break;

}

}

void loop () {
int hourOn=EEPROM.read(110); //EEPROM.read(110)
int hourOff= EEPROM.read(112);; //EEPROM.read(112)
int minOn= EEPROM.read(111);; //EEPROM.read(111)
int minOff= EEPROM.read(113);; //EEPROM.read(113)
int minVent= EEPROM.read(114); //время работы вентилятора

int Hour = rtc[2]; //присваиваем часы
int Minute = rtc[1]; //присваиваем минуты
int Second = rtc[0]; // присваиваем секунды
int FullMinutes = Hour * 60 + Minute; //приводим значение текущего времени к минутам
int FullMinutesTimerOn= hourOn*60+minOn; //приводим значение ВКЛЮЧЕНИЯ таймера к минутам
int FullMinutesTimerOff= hourOff*60+minOff; //приводим значение ВЫКЛЮЧЕНИЯ таймера к минутам
int sutki=0; // по умолчанию, таймер работает в одних сутках

if (hourOff-hourOn < 0) sutki=1; //если время выключения на следующие сутки, то включаем триггер сутки=1
else sutki=0;

if (sutki==1 && (FullMinutes >= FullMinutesTimerOn || FullMinutes <= FullMinutesTimerOff) )
{
lcd.setCursor(16, 2);
lcd.print(«VKL1»);
digitalWrite(RELE_1, LOW);
// если сутки перескакивают, то проверяем время оператором ИЛИ
}
else if (sutki==1)
{
lcd.print(" ");
digitalWrite(RELE_1, HIGH);
}

if (sutki == 0 && (FullMinutes >= FullMinutesTimerOn && FullMinutes <= FullMinutesTimerOff ))
{
lcd.setCursor(16, 2);
lcd.print(«VKL0»);
digitalWrite(RELE_1, LOW);
} // если сутки НЕ перескакивают, то проверяем время оператором И
else if (sutki == 0)
{
lcd.print(" ");
digitalWrite(RELE_1, HIGH);
}

if ((Minute >= 0 && Minute <= minVent) && (Hour >= 9 && Hour <= 21))
{
lcd.setCursor(17, 1);
lcd.print(«VEN»);
digitalWrite(RELE_2, LOW);
}
if (Minute >= 0 && Minute > minVent)
{
lcd.setCursor(17, 1);
lcd.print(" ");
digitalWrite(RELE_2, HIGH);
}

RTC.get(rtc,true);
digitalClockDisplay(); //выводим красивенькие часики на 2 строки
strokatimera();

if (rejim==0)
{
lcd.setCursor(0, 2);
lcd.print («ojidayu komandi»);
}
if (rejim==1)
{
setTimerOn();
}
if (rejim==2)
{
setTimerOff();
}
if (rejim==3)
{
setTime();
}
if (rejim==4)
{
setVent();
}

if (digitalRead (button5) == HIGH)
{
rejim++;
if (rejim>4) rejim=0;
lcd.clear();
//}
}

}

void setTimerOn()
{
int hourOn= EEPROM.read(110);
int minOn= EEPROM.read(111);
lcd.setCursor(0, 2);
lcd.print(«nastroika VKL»);

if (digitalRead(button3)==HIGH) //нажимая верхнюю кнопку меняем часы
{
hourOn++;
if (hourOn >=24) hourOn=0;
}

if (!digitalRead(button4)) //нажимая нижнюю кнопку меняем минуты
{
minOn++;
if (minOn >=60)
{
minOn=0;
hourOn++;
if (hourOn >=24) hourOn=0;
}
}
strokatimera();
if (digitalRead(button2) == HIGH)
{
EEPROM.write(110, hourOn);
EEPROM.write(111, minOn);
lcd.clear();
}
}

void setTimerOff()
{
int hourOff= EEPROM.read(112);
int minOff= EEPROM.read(113);
lcd.setCursor(0, 2);
lcd.print(«nastroika VIKL»);

if (digitalRead(button3)==HIGH) //нажимая верхнюю кнопку меняем часы
{
hourOff++;
if (hourOff >=24) hourOff=0;
}

if (!digitalRead(button4)) //нажимая нижнюю кнопку меняем минуты
{
minOff++;
if (minOff >=60)
{
minOff=0;
hourOff++;
if (hourOff >=24) hourOff=0;
}
}
strokatimera();
if (digitalRead(button2) == HIGH)
{
EEPROM.write(112, hourOff);
EEPROM.write(113, minOff);
lcd.clear();
}
}

void setTime()
{
int Hour = rtc[2]; //присваиваем часы
int Minute = rtc[1];
//lcd.clear();
lcd.setCursor(0, 2);
lcd.print («nastroika time»);
RTC.get(rtc,true);

//lcd.setCursor(0, 3); // вывод в последней строчке времени работы таймера
// lcd.print(Hour);
// lcd.print(":");
// lcd.print(Minute);

if (!digitalRead(button4)) //нажимая нижнюю кнопку меняем минуты
{
Minute++;
if (Minute >=60)
{
Minute=0;
Hour++;
if (Hour >=24) Hour=0;
}
}

if (digitalRead(button2) == HIGH)
{
RTC.set(DS1307_MIN,Minute);
RTC.set(DS1307_HR,Hour);
lcd.clear();
}

}

void strokatimera()
{
int hourOn=EEPROM.read(110); //EEPROM.read(110)
int hourOff= EEPROM.read(112);; //EEPROM.read(112)
int minOn= EEPROM.read(111);; //EEPROM.read(111)
int minOff= EEPROM.read(113);; //EEPROM.read(113)
int minVent= EEPROM.read(114);
lcd.setCursor(0, 3); // вывод в последней строчке времени работы таймера
lcd.print(hourOn);
lcd.print(":");
lcd.print(minOn);
lcd.print("-");
lcd.print(hourOff);
lcd.print(":");
lcd.print(minOff);
lcd.print(" ");
lcd.print(«VENT:»);
lcd.print(minVent);

}

void setVent()
{

int minVent= EEPROM.read(114);
lcd.setCursor(0, 2);
lcd.print(«nastroika Vent»);

if (!digitalRead(button4)) //нажимая нижнюю кнопку меняем минуты
{
minVent++;
if (minVent >=60)
{
minVent=0;
}
}

strokatimera();
if (digitalRead(button2) == HIGH)
{
EEPROM.write(114, minVent);
lcd.clear();
}
}

В дальнейшем этот контроллер планируется подключить к OpenHab, чтобы удаленно наблюдать и управлять системой отопления и вентиляции дома.

Автор: shuvaevgl

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js