Първоначално термостатът е направен просто като термометър за контрол на температурата извън прозореца. След това, по време на студове, картофите започнаха да замръзват под земята и беше добавена функционалност за контрол на микроклимата. Паспортни данни на превключвателното реле - 250V и 10A (2.5kW). Тъй като топлината в ъндърграунда не е необходима, десет на киловат е достатъчно.
Необходими материали и инструменти:кутия за грижа за обувките
-USB таксуване за телефона (който и да е, най-малко 0.7A)
-
Arduino-Рио-Mini
-2-редов 8-символен дисплей (WH0802A-NGA-CT е по-компактен)
Енкодер с бутон (може да бъде закупен във всеки радио маг, бутонът не може да бъде вграден)
-защита с 5V реле (закупих куп китайски релета без оптична изолация наведнъж, така че имах нужда от друг Optocoupler PC817 и резистор 470 Ohm. Ако имате оптична изолация на табелката, можете да свържете табелката директно към порта arduino)
USB конектор
-2 3-метров USB удължителен кабел (единият за захранващия кабел, към втория спояваме DS1820)
- DS1820 (с всяка буква)
поялник
-пистолет за лепило
Табелка FTDI232
Стъпка 1: На първо място, ние трябва да флаш ардуино, тъй като имам Pro Mini (той върви без USB-RS232 конвертор), трябва да споя линийка с щифтове към arduino. От страната, където са извлечени DTR, TXD, RXD, VCC, GND, GND. Сега свържете FTDI232 DTR към DTR, VCC към VCC, GND към GND, TXD към RXD, RXD към TXD. Пуснете ардуино IDE, изтеглете скицата и я флаш (скица в края).
Стъпка 2: Сега нека се погрижим за корпуса. Откъсваме гъбата при „FUKS“, обезмасляваме всичко добре, дълбоката част на кутията може да бъде прокарана с мека кърпа (нещо ще се залепи по-добре). Маркирайте дупката за енкодера, USB-конектора (майка) и самия дисплей. Залепете релето към капака на кутията. Трябва да се опитаме да поставим релето далеч от процесора и да подредим компонентите така, че капакът да се затвори по-късно (има много място).
Стъпка 3: Сега взимаме USB удължителния кабел, отрязваме гнездото на конектора (майка). Отрязваме отрязания край, пробиваме дупка за кабела в тялото, вмъкваме го и лепим ключа с пистолет. Плюс това, кабелът има червено, минус черно (просто го проверявам), плюс плюс на конектора, минус минусът (не давам щифта на конектора - той е в Интернет). Между плюса на конектора и 2 среда (имам ги свързани), трябва да се спойка резистор 4.7kOhm.
Стъпка 4: Взимаме 2 USB удължителни кабела, отрязваме конектора (майка), изрязваме кабела. За всеки случай ще проверим дали всички сме правилно споени. Свързваме захранващия кабел с USB зареждане и към мрежата, залепваме нарязания кабел в USB конектора, поглеждаме тестера + на червено - на черно. Изваждаме кабела и спояваме DS1820: - към 1, + до 3 останалите 2 проводника до 2. След това покривам епоксидното съединение (за ремонт на резервоарите, радиаторите), оставяйки малко от корпуса на сензора навън, така че да има по-бърза реакция на температурни промени.Е, ние извършваме инсталацията според схемата (свързваме мощността и земята на релейната платка съответно с общи + и - вериги).
Стъпка 5: Всички компоненти на веригата са свързани. Свързваме нашия сензор (без него дисплеят ще остане черен), прилагаме захранване. В първия ред - стойността на температурата в 2, ако е включено „*“ - релето е включено, не - изключено. Сега нека се опитаме да зададем граници за превключване на релето. Натиснете вала на енкодера (или вашия бутон) се появява граничната стойност, при която релето ще се включи чрез завъртане на вала - стойността се увеличава или намалява. Като кликнем отново върху вала - получаваме горната граница (релето ще се изключи), задаваме стойността и натискаме отново. Устройството ще следи температурата, стойността на ограниченията се поддържа, когато захранването е изключено. Това е всичко.
#include
#include
#include
#define BUTTON_1_PIN 10 // изходният номер на бутон 1 е 12
OneWire ds (12); // на щифт 10 (необходим е 4.7K резистор)
// инициализирайте библиотеката с номера на интерфейсните пинове
Течен кристал lcd (3, 2, 4, 5, 6, 7);
неподписан дълъг currentTime;
const int pin_A = 8; // щифт 12
const int pin_B = 9; // щифт 11
неподписан char enc_A;
неподписан char enc_B;
неподписан char enc_A_prev = 0;
float n_pr = 24.1;
float b_pr = 26.2;
булев приз = невярно;
клас бутон {
публичния:
Бутон (байтов щифт, байтово време) Бутон); // описание на конструктора
булев флагPress; // бутона за знаме е натиснат
булев флагClick; // бутонът с флаг беше натиснат (щракнете)
void scanState (); // метод за проверка на състоянието на сигнала
void setPinTime (байтов пин, байт timeButton); // метод за настройка на изходния номер и времето за потвърждение (брой)
лично:
байт _buttonCount; // стабилен брояч за потвърждение на състоянието
байт _timeButton; // време за потвърждение на състоянието на бутона
байт _pin; // пинов номер
};
Бутон с бутон1 (BUTTON_1_PIN, 30);
void knopka () {
lcd.clear ();
lcd.setCursor (1,0);
lcd.print (n_pr);
// button1.scanState ();
докато (button1.flagClick == false) {
enc_A = digitalRead (pin_A);
enc_B = digitalRead (pin_B);
ако ((! enc_A) && (enc_A_prev)) {
ако (enc_B) {
n_pr = n_pr-0.1;
} else {
n_pr = n_pr + 0.1;
}
lcd.clear ();
lcd.setCursor (1,0);
lcd.print (n_pr);
}
enc_A_prev = enc_A;
button1.scanState ();
}
button1.flagClick = невярно;
lcd.clear ();
lcd.setCursor (1,0);
lcd.print (b_pr);
докато (button1.flagClick == false) {
enc_A = digitalRead (pin_A);
enc_B = digitalRead (pin_B);
ако ((! enc_A) && (enc_A_prev)) {
ако (enc_B) {
b_pr = b_pr-0.1;
} else {
b_pr = b_pr + 0.1;
}
lcd.clear ();
lcd.setCursor (1,0);
lcd.print (b_pr);
}
enc_A_prev = enc_A;
button1.scanState ();
}
button1.flagClick = невярно;
ако (n_pr> b_pr) {
float wr = n_pr;
n_pr = b_pr;
b_pr = wr;
}
int addr = 0;
EEPROM.write (addr, 'y');
addr = 1;
EEPROM.put (addr, n_pr);
addr + = sizeof (float);
EEPROM.put (addr, b_pr);
забавяне (300);
}
настройка за невалидност (void) {
pinMode (11, изход);
pinMode (pin_A, INPUT_PULLUP);
pinMode (pin_B, INPUT_PULLUP);
lcd.begin (8.2);
int addr = 0;
char c = EEPROM.read (addr);
addr = addr + 1;
ако (c == 'y') {
EEPROM.get (addr, n_pr);
addr + = sizeof (float);
EEPROM.get (addr, b_pr);
}
// Serial.begin (9600);
}
void loop (void) {
байт i;
присъствие на байт = 0;
тип байт_s;
данни за байтове [12];
байтова добавка [8];
поплавък Целзий;
ако (! ds.search (addr)) {
ds.reset_search ();
забавяне (250);
се върне;
}
ако (OneWire :: crc8 (addr, 7)! = addr [7]) {
се върне;
}
// първият байт ROM показва кой чип
превключвател (addr [0]) {
случай 0x10:
type_s = 1;
прекъсване;
случай 0x28:
type_s = 0;
прекъсване;
случай 0x22:
type_s = 0;
прекъсване;
По подразбиране:
се върне;
}
ds.reset ();
ds.select (addr);
ds.write (0x44, 1); // стартиране на преобразуването, с включена паразитна мощност в края
enc_A = digitalRead (pin_A);
enc_A_prev = enc_A;
currentTime = millis ();
докато ((millis () - currentTime) <2000) {
button1.scanState ();
ако (button1.flagClick == true) {
// имаше натискане на бутон
button1.flagClick = невярно; // нулиране на атрибута за щракване
knopka ();
}
}
// забавяне (1000); // може би 750ms е достатъчно, може би не
// тук може да направим ds.depower (), но нулирането ще се погрижи за това.
настояще = ds.reset ();
ds.select (addr);
ds.write (0xBE); // Прочетете Scratchpad
за (i = 0; i <9; i ++) {// имаме нужда от 9 байта
данни [i] = ds.read ();
}
// Преобразуване на данните в действителна температура
// защото резултатът е 16-битово подписано цяло число, би трябвало
// да се съхранява до тип "int16_t", който винаги е 16 бита
// дори когато е компилиран на 32 битов процесор.
int16_t raw = (данни [1] << 8) | данни [0];
ако (type_s) {
суров = суров << 3; // 9 битова резолюция по подразбиране
ако (данни [7] == 0x10) {
// "броя остава" дава пълна 12-битова резолюция
raw = (raw & 0xFFF0) + 12 - данни [6];
}
} else {
байт cfg = (данни [4] и 0x60);
// при по-ниска резолюция ниските битове са неопределени, така че нека ги нулираме
if (cfg == 0x00) raw = raw & ~ 7; // 9 битова резолюция, 93.75 ms
иначе ако (cfg == 0x20) raw = raw & ~ 3; // 10 битова резолюция, 187,5 ms
иначе ако (cfg == 0x40) raw = raw & ~ 1; // 11 битова резолюция, 375 ms
//// по подразбиране е 12 битова разделителна способност, 750 ms време за преобразуване
}
celsius = (float) суров / 16.0;
lcd.clear ();
lcd.setCursor (1,0);
lcd.принт (celsius);
ако (приз) {
lcd.setCursor (0,1);
lcd.print ('*');
}
ако (n_pr! = b_pr) {
ако (Целзий b_pr) {
digitalWrite (11, LOW);
приз = невярно;
}
}
}
// метод за проверка на състоянието на бутона
// flagPress = true - щракна
// flagPress = невярно - натиснато
// flagClick = true - щракна (щракни)
невалиден бутон :: scanState () {
ако (flagPress == (! digitalRead (_pin))) {
// състоянието на сигнала остава същото
_buttonCount = 0; // нулиране брояча на състоянието на сигнала
}
друго {
// състоянието на сигнала е променено
_buttonCount ++; // +1 към брояча на състоянието на сигнала
ако (_buttonCount> = _timeButton) {
// състоянието на сигнала не промени посоченото време
// състоянието на сигнала е станало стабилно
flagPress =! flagPress; // обратна на индикатора за състояние
_buttonCount = 0; // нулиране брояча на състоянието на сигнала
if (flagPress == true) flagClick = true; // знак за щракване върху щракване
}
}
}
// метод за настройка на изходния номер и времето за потвърждение
void Button :: setPinTime (байтов пин, байт timeButton) {
_pin = щифт;
_timeButton = timeButton;
pinMode (_pin, INPUT_PULLUP); // дефинирайте изхода като вход
}
// описание на конструктора на класа Button
Бутон :: Бутон (байтов пин, байтово време) Бутон {
_pin = щифт;
_timeButton = timeButton;
pinMode (_pin, INPUT_PULLUP); // дефинирайте изхода като вход
}