Економимо електрика або таймер часу для нічного тарифу в електромережах

Як часто вам доводиться налаштовувати різні таймери? Будильник на смартфоні, таймер на хлібопічці, щоб до сніданку був свіжий хліб, та й мало коли потрібно щось почати. Не менш важливою виявляється завдання вчасно відключити або закінчити дію.

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

Отже, стоїть завдання включати електричний котел опалення для обігріву будинку в нічний період часу, коли тарифікація хоч трохи щадна. Що з цього вийшло — дивіться нижче.

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 display line
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, МБ);
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 display line
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, МБ);
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, щоб віддалено спостерігати і керувати системою опалення та вентиляції будинку.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.