スマートホーム向け高度マルチゾーン床暖房制御システム
必要な部品と材料
| 部品 | 詳細 | 数量 |
|---|---|---|
| Arduino UNO | 5ゾーンまで制御可能。6ゾーン以上ならMega推奨 | 1 |
| Keyes 8チャネル 5Vリレーボード | 2ゾーン制御なら4リレーで可。追加ゾーンごとに1リレー必要 | 1 |
| Honeywell MT8-230-NC サーモアクチュエータ (230V AC) | ゾーンごとに1個必要(床暖房バルブ駆動)。他機種も可 | 1 |
このプロジェクトについて
リビングの単一サーモスタットではキッチンが暑すぎたり寒すぎたりする問題を解決するため自作。市販のマルチゾーン制御システム(EvoHome等)は高価ですが、Arduino Unoで同等の知能を実現しました。完全に問題を解決しています。
主な特徴
- ピン配置とゾーン数の設定のみで導入可能
- Unoで最大5つの床暖房ゾーンを制御
- Megaならゾーン数はほぼ無制限
制御対象
- 床暖房循環ポンプ
- 全ゾーンを1つのサーモスタットとして中央暖房ボイラー(CV)に集約
- 各ゾーンの開閉バルブ
- ウォッチドッグタイマーによる堅牢な動作保証
ゾーン別個別制御
- ゾーンごとにサーモスタット(加熱要求検知)とリレー(バルブ制御)を配置
- 1部屋に複数の床暖房グループがある場合、バルブを並列接続して1ゾーンとして扱い可能
- 「暑すぎ/寒すぎ」を防ぎ、快適性と省エネを両立
循環ポンプ制御
- 加熱要求がある時のみポンプ運転(24時間運転比で年間100〜200ユーロの電気代削減。80W×24h=1.92kWh/日≒0.5ユーロ/日)
- 加熱要求がない期間(夏場)は36時間ごとに8分間強制運転し、ポンプ固着を防止
- バルブ開放(3〜5分)完了までポンプ起動を待機
床暖房のない部屋(ラジエーター暖房等)もオプションで制御可能
- 各部屋のサーモスタットノブを併用し、寒い部屋だけ暖まる仕組みを維持
- 制御したい部屋にサーモスタットを追加し、No_Zone入力に並列接続
設計方針
- 全ゾーンを制御する必要はない。手動調整で問題ないゾーンはノブ任せ
- 意図的にインターネット接続しない:
- 故障リスク増大を避ける(確実な動作が最優先)
- スマートサーモスタットで遠隔操作可能。本コントローラーに遠隔機能は不要
コード
ProjectCV.ino (メインスケッチ)
/* Floor Unit heating controller for multiple Rooms/Zones v1.0
* Copyright: GPL-3.0 by Eric Kreuwels, 2017
* Credits: Peter Kreuwels for use-case definitions
*
* 注意: 実機でFAST_MODE使用時はバルブ開放待ち時間が短縮されるためポンプ損傷の恐れあり。
* テスト時のみ使用し、実運用ではコメントアウトのこと。
*/
#include <avr/wdt.h> // Watchdog
// #define FAST_MODE // テスト用:ループ50倍速
#define VALVE_TIME 3000L // バルブ開閉待ち 5分 (3000カウント @ 10Hz)
#ifdef FAST_MODE
#define PUMP_MAINTENANCE_TIME 108000L // 4分ごとにメンテナンス運転
#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 // 加熱中LED(クールダウン時は点滅)
#define INDICATION_LED 13 // 動作表示LED(オンボードLED兼用)
// ゾーン定義
#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; i 0); }
bool checkCoolDownNeeded() { return (cooldownCount > 0); }
void Print() {
switch(_State) {
case idle: Serial.print("idle"); break;
case on: Serial.print("on"); break;
case cooldown: Serial.print("cooldown"); break;
}
}
};
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 3 hours instead once per 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); // Watchdog 1秒
}
void loop() {
#ifdef FAST_MODE
delay(2);
#else
delay(100); // 約10Hz
#endif
iLED.Alternate(); // 生存表示
FUPump.Update();
for(int i=0; i
Devices.h (デバイス抽象化クラス)
// IOデバイス基底クラス
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.print(") = "); Serial.println(_IsOn ? "On" : "Off"); }
};
// サーモスタット: デジタル入力(チャタリング抑制付き)
class Thermostat : public IODevice {
private: 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;
}
};
// マニピュレータ: 基本出力デバイス
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; }
};
// バルブ: 開閉に3-5分かかるため遷移時間を管理
class Valve : public Manipulator {
private: 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--; }
}
};
// ポンプ: 定期メンテナンス運転管理
class Pump : public Manipulator {
private: 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(counter250) { counter=0; if(IsOn()) Off(); else On(); }
#else
if(counter++>5) { counter=0; if(IsOn()) Off(); else On(); }
#endif
}
};
回路図・資料
- ポンプ・バルブ・サーモスタット・LEDの詳細配線図
- 複数コントローラーをカスケード接続する例(床暖房システムごとに1台)
- シリアルモニターログ実例(バルブ開放からポンプ起動まで5分の遅延等が確認可能)
製造プロセス
- ソーラー暖房システム:パッシブからアクティブまで、持続可能な住宅暖房ソリューション
- Raspberry Piでセントラルヒーティングボイラーを監視 – ハードウェア、ソフトウェア、セットアップガイド
- Web制御DMX照明システム:Arduino Megaマスターコントローラー
- ゲーマー向け自動操作デバイス──Arduinoとサーボでコントローラのボタンを自動連打
- DIY Arduino USBゲームコントローラー - 高性能ゲームパッドを自作
- Unopad: Ableton Live連携シームレスなArduino MIDIコントローラー
- Arduinoベースの蛍光表示管(VFD)コントローラーキット
- セントラルヒーティングをArduinoでスマート制御:OpenThermシールド活用ガイド
- Alexa対応Arduinoホームコントローラー:音声でスマートホーム自動化
- PWM電力コントローラ:パルス幅変調ランプドライバの構築
- 床洗浄機(フロアスクラバー)を最高性能で維持する必須メンテナンスガイド