Продвинутая система многозонного отопления для умного дома на Arduino
Компоненты и материалы
| Компонент | Количество / Примечание |
|---|---|
| Arduino UNO (или Mega для >5 зон) | 1 |
| Релейный модуль 8 каналов 5В (Keyes) | 1 (4 реле на 2 зоны: 1 насос, 1 котел, 2 клапана; +1 реле на каждую доп. зону) |
| Термоэлектрические приводы клапанов Honeywell MT8-230-NC (230В AC) | 1 на зону (на группу контуров теплого пола) |
О проекте
Автор собрал это устройство, потому что кухня была то слишком горячей, то слишком холодной при едином термостате в гостиной. Коммерческие многозонные системы (например, EvoHome) очень дороги. Этот скетч на Arduino Uno реализует их интеллект за копейки. Проблема полностью решена.
Ключевые особенности
- Настройка только пинов и количества зон
- Uno управляет до 5 зон теплого пола; Mega — практически неограниченное число
- Управление: насос теплого пола, агрегация зон в один термостат для котла, клапаны зон, Watchdog-таймер
- Индивидуальное отопление по зонам: свой термостат и реле клапанов на зону. Несколько групп контуров в одной комнате — параллельно на одно реле
- Экономия энергии: комнаты не перегреваются
- Умное управление насосом: работает только при необходимости (экономия 100–200 €/год vs 24/7). Профилактика: запуск на 8 мин каждые 36 часов летом. Запуск насоса только после открытия клапанов (3–5 мин)
- Опционально: управление остальными комнатами (радиаторы с термоголовками) через вход
No_Zone - Не все зоны нужно автоматизировать — только проблемные
- Осознанно нет подключения к интернету: надежность, умные термостаты уже дают удаленный доступ
Код
Основной скетч: ProjectCV.ino
/*
* Floor Unit heating controller for multiple Rooms/Zones v1.0
* GPL-3.0, Eric Kreuwels, 2017
* Use cases: Peter Kreuwels
* Tested >1 year on ground floor. No liability. Test before use.
*/
#include <avr/wdt.h>
// #define FAST_MODE // для тестов: loop в 50x быстрее. НЕ для реального насоса!
#define VALVE_TIME 3000L // 5 мин на открытие/закрытие клапана
#ifdef FAST_MODE
#define PUMP_MAINTENANCE_TIME 108000L // 3 часа в быстром режиме
#else
#define PUMP_MAINTENANCE_TIME 1300000L // 36 часов в норме
#endif
#define PUMP_ACTIVATION_TIME 5000L // 8 мин работы насоса
#define COOLDOWN_TIME 18000L // 30 мин обогрева после отключения
#include "./Devices.h"
struct Zone {
String name;
Valve valve;
Thermostat thermostat;
};
////////////////////////////////////////////////////
// КОНФИГУРАЦИЯ (перепишите под свои пины)
#define HEATER_PIN 4 // реле → термостат котла
#define FU_PUMP_PIN 5 // реле → насос теплого пола
#define LIVING_VALVE 7 // зона 1: клапан
#define KITCHEN_VALVE 6 // зона 2: клапан
#define DINING_VALVE 3 // зона 3: клапан
#define LIVING_THERMO 8 // зона 1: термостат (вход)
#define KITCHEN_THERMO 9 // зона 2: термостат
#define DINING_THERMO 11 // зона 3: термостат
#define NO_ZONE_THERMO 10 // опционально: термостаты радиаторов без теплого пола
#define HEATING_LED 12 // индикация отопления
#define INDICATION_LED 13 // heartbeat (можно убрать, освободив пин)
#define NR_ZONES 3
Zone Zones[NR_ZONES] = {
{"Living Room", Valve(LIVING_VALVE, "Living Valve"), Thermostat(LIVING_THERMO, "Living Thermostat")},
{"Kitchen Area", Valve(KITCHEN_VALVE, "Kitchen Valve"), Thermostat(KITCHEN_THERMO, "Kitchen Thermostat")},
{"Dining Room", Valve(DINING_VALVE, "Dining Valve"), Thermostat(DINING_THERMO, "Dining Thermostat")}
};
// КОНЕЦ КОНФИГУРАЦИИ
////////////////////////////////////////////////////
LED iLED(INDICATION_LED, "Indicator LED");
LED hLED(HEATING_LED, "Heating LED");
Manipulator CV(HEATER_PIN, "CV Heater");
Pump FUPump(FU_PUMP_PIN, "Floor Unit Pump");
Thermostat ZonelessThermo(NO_ZONE_THERMO, "Zoneless Thermostat");
void printConfiguration() {
Serial.println("------ Board Configuration: ---------");
iLED.Print(); hLED.Print(); CV.Print(); FUPump.Print(); ZonelessThermo.Print();
for (int i=0; i0) cooldownCount--; return cooldownCount>0; }
bool checkCoolDownNeeded() { return cooldownCount>0; }
void printState(states s) { if(s==idle)Serial.print("idle"); else if(s==on)Serial.print("on"); else Serial.print("cooldown"); }
};
State CVState;
void setup() {
Serial.begin(115200);
printTimeStamp(); Serial.print(": ");
#ifdef FAST_MODE
Serial.println("CV Zone Controller started in TestMode!\n - Board time runs ca 50 times faster\n - Pump maintenance cycle runs ever 4 min instead of 36 hours");
#else
Serial.println("CV Zone Controller started. Time stamps (dd:hh:mm:ss)");
#endif
Serial.println(" - Time stamps format (dd:hh:mm:ss)");
printConfiguration();
wdt_enable(WDTO_1S);
}
void loop() {
#ifdef FAST_MODE
delay(2);
#else
delay(100);
#endif
iLED.Alternate();
FUPump.Update();
for (int i=0; i
Devices.h — классы устройств
// Базовый класс IODevice
class IODevice {
protected: bool _IsOn; int _Pin; String _Name;
public:
IODevice(int pin, String name) : _IsOn(false), _Pin(pin), _Name(name) {}
virtual bool IsOn() = 0;
bool IsOff() { return !IsOn(); }
void DebugPrint() { printTimeStamp(); Serial.print(": "); Print(); }
void Print() { Serial.print(_Name); Serial.print(" on pin("); Serial.print(_Pin); Serial.println(_IsOn ? ") = On" : ") = Off"); }
};
// Thermostat — цифровой вход с антидребезгом (5 согласованных чтений)
class Thermostat : public IODevice {
int _Counter;
public:
Thermostat(int pin, String name) : IODevice(pin, name), _Counter(0) { pinMode(_Pin, INPUT_PULLUP); }
bool IsOn() {
if (digitalRead(_Pin)==HIGH && _IsOn) { if(++_Counter>5) { _IsOn=false; DebugPrint(); _Counter=0; } }
else if (digitalRead(_Pin)==LOW && !_IsOn) { if(++_Counter>5) { _IsOn=true; DebugPrint(); _Counter=0; } }
else _Counter=0;
return _IsOn;
}
};
// Manipulator — базовое цифровое выходное устройство
class Manipulator : public IODevice {
public:
Manipulator(int pin, String name) : IODevice(pin, name) { pinMode(_Pin, OUTPUT); digitalWrite(_Pin, HIGH); }
void On() { if(!_IsOn) { _IsOn=true; digitalWrite(_Pin, LOW); onSwitch(); } }
void Off() { if(_IsOn) { _IsOn=false; digitalWrite(_Pin, HIGH); onSwitch(); } }
virtual void onSwitch() { DebugPrint(); }
bool IsOn() { return _IsOn; }
};
// Valve — клапан с учетом времени перехода (3-5 мин)
class Valve : public Manipulator {
long transitionCount;
public:
Valve(int pin, String name) : Manipulator(pin, name), transitionCount(0) {}
bool ValveIsOpen() { return IsOn() && transitionCount >= VALVE_TIME; }
void Update() { if(IsOn()) { if(transitionCount0) transitionCount--; } }
};
// Pump — насос с периодическим профилактическим запуском
class Pump : public Manipulator {
long counter; bool doMaintenance;
public:
Pump(int pin, String name) : Manipulator(pin, name), counter(0), doMaintenance(false) {}
bool doMaintenanceRun() { return doMaintenance; }
void onSwitch() { Manipulator::onSwitch(); counter=0; }
void Update() {
if (IsOn()) {
if (counter < PUMP_ACTIVATION_TIME) counter++;
else if (doMaintenance) { printTimeStamp(); Serial.println(": Pump Maintenance cleared"); doMaintenance=false; }
} else {
if (counter < PUMP_MAINTENANCE_TIME) counter++;
else if (!doMaintenance) { printTimeStamp(); Serial.println(": Pump Maintenance needed"); doMaintenance=true; }
}
}
};
// LED с миганием 1 Гц (вызывать Alternate() в loop)
class LED : public Manipulator {
long counter;
public:
LED(int pin, String name) : Manipulator(pin, name), counter(0) {}
void onSwitch() {} // без дебаг-вывода
void Alternate() {
#ifdef FAST_MODE
if (counter++ > 250) { counter=0; IsOn()?Off():On(); }
#else
if (counter++ > 5) { counter=0; IsOn()?Off():On(); }
#endif
}
};
Схемы и логи
— подключение насоса, клапанов, термостатов, LED
— пример каскадирования нескольких контроллеров (по одному на теплый пол)logexample_fTczkAa0tf.txt— пример лога Serial Monitor с таймстампами (видна задержка 5 мин между открытием клапанов и стартом насоса)
Производственный процесс
- PWM контроллер мощности: сборка драйвера лампы с пульсирующей шириной модуляции
- Солнечные отопительные системы: от пассивных к активным решениям для устойчивого отопления домов
- Мониторинг центрального отопительного котла на Raspberry Pi — железо, софт и настройка
- Основное руководство по обслуживанию полотерки для полов для пиковой производительности
- Веб-управляемая DMX-система освещения: Arduino Mega как мастер-контроллер
- Автоматизированный игровой помощник: устройство для автонажатия кнопок на геймпаде
- DIY USB-геймпад на Arduino: собственный высокопроизводительный контроллер
- Unopad: Бесшовный Arduino MIDI-контроллер для Ableton Live
- Контроллер вакуумно-люминесцентного дисплея (VFD) на Arduino — DIY набор
- Интеграция центрального отопления с Arduino: умное управление по OpenTherm