マルチゾーン暖房コントローラー
コンポーネントと消耗品
> |
| × | 1 | |||
| × | 1 | ||||
| × | 1 |
このプロジェクトについて
私のキッチンは、生活の中で1つのサーモスタットを使って暖めるか冷やすかのどちらかだったので、このデバイスを作成しました。市販のマルチゾーン暖房コントローラー(EvoHomeなど)は非常に高価です。このプログラムは、シンプルなArduinoUnoボードでホストされているこれらの高価なシステムのインテリジェンスをキャプチャします。これで私の問題は完全に解決しました。
ハイライト/機能:
- ピン留めとゾーン数を設定するだけで済みます
- シンプルなArduinoUnoは、最大5つのフロアユニットゾーンを制御できます
- Arduino Megaを使用すると、ゾーンの数はほぼ制限されません。
提供されるプログラムコントロール:
- フロアユニットポンプ
- すべてのゾーンをセントラルヒーティングへの1つのサーモスタットとして集約します
- ゾーンの開閉に使用されるバルブ
- 堅実な動作を保証するウォッチドッグタイマー
ゾーンごとに個別の暖房を許可:
- ゾーンごとにサーモスタットを使用して、暖房の要求を検知します
- ゾーンごとに、そのゾーンのフロアユニットグループを開閉するための1つまたは複数のバルブを制御するリレー
- 複数のフロアユニットグループがある部屋は、1つの暖房ゾーンと見なすことができます(ゾーンリレーと平行にバルブを配線します)
- これは便利なだけでなく、エネルギーを節約するだけでなく、部屋が暖かくなりすぎないようにします。
フロアユニットポンプを制御します:
- 基本的には、加熱に必要な場合にのみポンプを作動させます。これにより、年間100〜200ユーロの電力がすでに節約されます(同じポンプを24時間年中無休で稼働させる場合と比較して(80ワットは1日2kW時間=1日0.50ユーロ)
- 床ユニットのポンプを少なくとも36時間に1回、暖房の要求がない場合は8分間作動させます(夏)
- 最初にバルブを開かずにポンプを運転することを防ぎます。これらのバルブを考慮すると、3〜5分かかります
オプションで、家の残りの部分(床暖房のない部屋)も制御できます:
- ここでは通常、ラジエーターにサーモスタットノブがあります。そのため、寒い部屋だけが熱くなります
- 制御したい部屋にサーモスタットを追加するだけです。これらのサーモスタットをNo_Zone入力と並列に配線します
最後の注意:
すべてのゾーンを制御する必要はありません。暖かくなるか冷たくなりすぎるゾーンのみ(それ以外の場合は、フロアユニットの手動調整可能なノブを使用してください)
デバイスをインターネットに接続しないことを明示的に決定しました:
- 機能不全のリスクが高まります(堅固である必要があります)
- スマートサーモスタットを使用して家を制御できます。このコントローラーは、リモートで適応するための特別なものは何も提供していません
コード
- ProjectCV.ino
- Devices.h
ProjectCV.ino C / C ++
/ **複数の部屋/ゾーンv1.0用のフロアユニット暖房コントローラー**著作権:EricKreuwelsによるGNUGeneral Public Licenseバージョン3(GPL-3.0)、2017 *クレジット:すべてのユースケースを定義するためのPeter Kreuwelsそれを考慮する必要がありました**このセットアップは私の1階ですでに1年以上実行されていますが、コードのエラーについては責任を負いません*それはあなた自身のニーズの良い基盤として使用でき、使用前にテスト済み**ハイライト/機能:*-ピン留めとゾーン数を構成するだけで済みます*-シンプルなArduinoUnoは最大5フロアユニットゾーンを制御できます* -ArduinoMegaではゾーン数はほぼ無制限です* -提供されるプログラム制御:*-フロアユニットポンプ* -CVヒーターへの1つのサーモスタットとしてすべてのゾーンを集約します*-ゾーンを開閉するバルブ*-ゾーンごとに個別の加熱を可能にします。 *-ゾーンごとに暖房の要求を感知するサーモスタット*-ゾーンごとに1つ以上のバルブを制御してそのゾーンのフロアユニットグループを開閉するリレー*-複数のフロアユニットグループがある部屋は1つの暖房と見なすことができますゾーン(ゾーンリレーと平行にバルブを配線する)*-これは便利であるだけでなく、エネルギーを節約し、部屋が暖かくなりすぎないようにします*-フロアユニットポンプを制御します*-基本的にポンプを実行するのは次の場合のみです暖房に必要です。これにより、年間100〜200ユーロの電力がすでに節約されます。*同じポンプを24時間年中無休で稼働させる場合と比較して(80ワットは1日2kW時間=1日0.50ユーロ)*-フロアユニットポンプを少なくとも36時間に1回作動させます。加熱要求がなかった場合は8分間(夏)*-最初にバルブを開かずにポンプを運転できないようにします。これらのバルブを考慮すると、3〜5分かかります*-オプションで、家の残りの部分(床暖房のない部屋)も制御できます*-ここでは、通常、ラジエーターにサーモスタットノブがあります。そのため、寒い部屋だけが熱くなります*-制御したい部屋にサーモスタットを追加するだけです。これらのサーモスタットをNo_Zone入力と並列に配線します*-最後の注意:*-すべてのゾーンを制御する必要はありません。 *フロアユニットの手動調整ノブで暖まるか冷たくなりすぎるゾーンのみ* /#include//ウォッチドッグ用//警告:FAST_MODEはテスト/評価/デバッグ用です(ループは50倍速く実行されます)//閉じたバルブで損傷する可能性があるため、実際のフロアユニットポンプでFAST_MODEを使用する場合は注意してください//バルブを開くのに必要な時間は最低3分です。 FAST_MODEでは、プログラムはポンプを開始する前に十分な時間待機しません// #define FAST_MODE // 50倍高速な実行;実際のCV / Pumpを切断することを検討してください!//通常の操作では、ループ実行は1秒間に10回実行されます。したがって、10カウント/秒(600は約1分を表します)#defineVALVE_TIME 3000L //バルブの開閉に5分(安全な場所で、通常3〜5分かかります)#ifdef FAST_MODE#define PUMP_MAINTENANCE_TIME 108000L //評価用、4分ごとに1回フロアユニットポンプメンテナンス実行をアクティブにします(タイムスタンプ3時間)#else#define PUMP_MAINTENANCE_TIME 1300000L // 36時間ごとに1回フロアユニットポンプメンテナンス実行をアクティブにします。ポンプの動作を維持するために必要#endif#define PUMP_ACTIVATION_TIME 5000L //ポンプを約8分間アクティブにします(テストモードでは10秒)#define COOLDOWN_TIME 18000L //加熱が完了したら、さらに30分間(テストでは40秒)水循環を続けますmode)//これにより、床への熱のさらなる放散が可能になります(通常、15〜30分かかります)#include "./Devices.h" //バルブ、ポンプ、サーモスタットクラス(上記で定義された定数を使用)struct Zone {String name;バルブバルブ;サーモスタットサーモスタット;}; ///////////////////////////////////////////// ///////// CONFIGURATION BLOCK //ピンを好きなように構成/並べ替えます(これはArduino Unoの私の配線です); //注:ピン1と2は、追加のゾーンを自由に追加できます#define HEATER_PIN 4 //暖房システムのサーモスタット入力に配線されたリレーへの出力#defineFU_PUMP_PIN 5 //スイッチを切り替えるリレーへの出力フロアユニットポンプ#defineLIVING_VALVE 7 //ゾーン1:バルブを制御するリレーへの出力#define KITCHEN_VALVE 6 //ゾーン2:バルブを制御するリレーへの出力#define DINING_VALVE 3 //ゾーン3:バルブを制御するリレーへの出力#define LIVING_THERMO 8 //ゾーン1;リビングのサーモスタットに配線された入力#defineKITCHEN_THERMO 9 //ゾーン2;キッチンのサーモスタットに配線された入力#defineDINING_THERMO 11 //ゾーン3;ダイニングのサーモスタットに配線された入力#defineNO_ZONE_THERMO 10 //オプション:床暖房のない部屋のサーモスタット#defineHEATING_LED 12 //暖房時にオン、クールダウン中に交互、アイドルモードでオフ#define INDICATION_LED 13 //オンを交互にボードの実行を示すボードLED。簡単に取り外して、余分なIOピンを解放できます!! //フロアユニットのゾーン/部屋を構成します。各ゾーン/部屋には、名前、バルブ、サーモスタットがあります。 "キッチンエリア"、バルブ(KITCHEN_VALVE、 "キッチンバルブ")、サーモスタット(KITCHEN_THERMO、 "キッチンサーモスタット")}、{"ダイニングルーム"、バルブ(DINING_VALVE、 "ダイニングバルブ")、サーモスタット(DINING_THERMO、 "ダイニングサーモスタット" )}}; //構成ブロックの終了///////////////////////////////////////// ///////////一部の固定デバイス:LED iLED(INDICATION_LED、 "インジケーターLED"); // IOの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 、 "ゾーンレスサーモスタット"); //家の残りの部分については、フロアユニットゾーンとは関係ありませんvoid printConfiguration(){Serial.println( "------ Board Configuration:---------"); iLED.Print(); hLED.Print(); CV.Print(); FUPump.Print(); ZonelessThermo.Print(); for(int i =0; i 0){cooldownCount--; } return checkCoolDownNeeded(); } bool checkCoolDownNeeded(){return(cooldownCount> 0); } void Print(){switch(_State){case idle:Serial.print( "idle");壊す;ケースオン:Serial.print( "on");壊す;ケースのクールダウン:Serial.print( "cooldown");壊す; }}}; //グローバル状態machineStateCVState; void setup(){//初期化Serial.begin(115200); printTimeStamp(); Serial.print( ":"); #ifdef FAST_MODE Serial.println( "CVゾーンコントローラーがTestModeで開始されました!\ n" "-ボード時間は約50倍速くなります\ n" "-ポンプのメンテナンスサイクルは3時間ごとに1回ではなく実行されます36時間あたり ");#elseSerial.println(" CVゾーンコントローラーが開始しました。タイムスタンプ(dd:hh:mm:ss) ");#endif Serial.println("-タイムスタンプ形式(dd:hh:mm: ss) "); printConfiguration(); wdt_enable(WDTO_1S); //ウォッチドッグ:「犬をなでる」が受信されなかった場合、1秒後にボードをリセットします} void loop(){#ifdef FAST_MODE delay(2); // 50倍速いので、デバッグの目的で分はおよそ秒になります。したがって、クールダウンまたはアイドルのすべてのカウントは0.002秒です。#elsedelay(100); //通常の操作:1秒間に約10回ループします。したがって、クールダウンまたはアイドルのすべてのカウントは0.1秒です。#endif //表示LEDを使用して、ボードが動作していることを示しますiLED.Alternate(); // loop()ごとに1回、ポンプとバルブはhteir administatrion FUPump.Update();を選択する必要があります。 for(int i =0; i この状態のままにするif(FloorPumpingAllowed()){FUPump.On(); } else {FUPump.Off(); }} else if(CVState.checkCoolDownNeeded()){//クールダウン状態を継続して、しばらくの間ポンプを稼働させ続けますCVState(State ::cooldown); } else {//フロアユニットのクールダウンをスキップし、アイドル状態に戻りますCVState(State ::idle); }} void coolDownProcessing(){hLED.Alternate(); if(HeatingRequested()){//サーモスタットの1つが閉じているときにtrueを返しますCVState(State ::on); } else {if(CVState.whileCoolDownNeeded()){if(FloorPumpingAllowed()){FUPump.On(); } else {FUPump.Off(); }} else {CVState(State ::idle); }}} void idleProcessing(){if(HeatingRequested()){//サーモスタットの1つが閉じている場合はtrueを返しますCVState(State ::on); } else {//アイドル期間中、このチェックはフロアユニットポンプを36時間ごとに8分間アクティブにして、それらを操作可能に保ちますif(FUPump.doMaintenanceRun()){if(FUPump.IsOff()){if(allValvesOpen()==false){//一度だけ開き始めますprintTimeStamp(); Serial.println( ":フロアユニットポンプの毎日のサイクルを開始します;バルブを開きます:"); allValvesOn(); } if(FloorPumpingAllowed()){//これはバルブをアクティブにしてから約5分かかります(テストモードでは6秒)printTimeStamp(); Serial.println( ":フロアユニットポンプの毎日のサイクルを開始します;ポンプを開始します"); FUPump.On(); }}} else if(FUPump.IsOn()){//メンテナンスは必要ありません。したがって、まだprintTimeStamp()を実行している場合は、ポンプを停止します。 Serial.println( ":フロアユニットポンプの毎日のサイクルを停止します。ポンプを停止してバルブを閉じます"); FUPump.Off(); allValvesOff(); }}} /////////////////////////////////////////////// ///////////////////////状態ハンドラーによって使用されるヘルパーメソッド//////////////////// ///////////////////// void allValvesOff(){for(int i =0; i Devices.h C / C ++
// IOデバイスのヘルパークラスexternvoid printTimeStamp(); //メインのinoファイルで定義// IODevice:すべてのIOデバイスの基本クラス。 specializationclass IODevice {// vars protected:bool_IsOn;が必要ですint _Pin;文字列_名前; //コンストラクターpublic:IODevice(int pin、String name){_ IsOn =false; _ピン=ピン; _Name =名前; } //メソッドvirtualbool IsOn()=0; //抽象仮想boolIsOff(){//すべてのデフォルトreturn!IsOn(); } void DebugPrint(){printTimeStamp(); Serial.print( ":"); Print(); } void Print(){Serial.print(_Name); Serial.print( "on pin("); Serial.print(_Pin); if(_IsOn)Serial.println( ")=On"); else Serial.println( ")=Off"); }}; //サーモスタット:デジタル入力を読み取り、いくつかのデンダー抑制クラスを追加しますサーモスタット:public IODevice {// vars private:int _Counter; //断続的なスイッチングの読み取りを防ぐために使用されます(dender)//コンストラクターpublic:Thermostat(int pin、String name):IODevice(pin、name){_ Counter =0; pinMode(_Pin、INPUT_PULLUP); } //メソッドvirtualbool IsOn(){if(digitalRead(_Pin)==HIGH &&_IsOn ==true)//オン中に連絡先を開く{if(_Counter ++> 5)//同じ読み出しの5回後にのみ動作する{ _IsOn =false; DebugPrint(); _Counter =0; }} else if(digitalRead(_Pin)==LOW &&_IsOn ==false)//オフのときに連絡先を閉じます{if(_Counter ++> 5)//同じ読み出しの5回後にのみ動作します{_IsOn =true; DebugPrint(); _Counter =0; }} else {_Counter =0; } return _IsOn; }}; //マニピュレーター:デジタル出力クラスで最も基本的な動作デバイスマニピュレーター:public IODevice {// vars private://コンストラクターpublic:Manipulator(int pin、String name):IODevice(pin、name){pinMode( _ピン、出力); digitalWrite(_Pin、HIGH); } //メソッドvoidOn(){if(_IsOn ==false){_ IsOn =true; digitalWrite(_Pin、LOW); onSwitch(); }} void Off(){if(_IsOn ==true){_ IsOn =false; digitalWrite(_Pin、HIGH); onSwitch(); }} virtual void onSwitch(){//子句のトリガー;オン/オフ状態の変更DebugPrint(); } virtual bool IsOn(){return _IsOn; }}; //バルブ:デジタル出力の静水圧バルブを制御します。 //これらのバルブはゆっくりと反応するため(3〜5分)、このクラスはこの遷移認識を追加します// loop()はUpdate()を呼び出して、バルブが完全に開いているか閉じているかを追跡する必要があります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)); //状態で少なくとも5分} //スケッチloop()のパスごとに1回実行!!! void Update(){if(IsOn()){if(transitionCount0)transitionCount--; }}}; //ポンプ:ポンプを動かし続けるには、週に数回ポンプを作動させる必要があります。 // loop()はUpdate()を呼び出して、メンテナンスのアクティブ化が必要なタイミングを追跡する必要がありますclass Pump:public Manipulator {//バルブの反応が遅い(3〜5分)ため、このクラスはこの遷移認識を追加しますprivate:long counter; bool doMaintenance; //コンストラクターpublic:Pump(int pin、String name):Manipulator(pin、name){counter =0; doMaintenance =false; } bool doMaintenanceRun(){return doMaintenance; } virtual void onSwitch(){//オン/オフ状態の変更Manipulator ::onSwitch();カウンター=0; } // loop()のすべてのパスでこのメソッドを実行しますvoid Update(){if(IsOn()){if(counter 250)#else if(counter ++> 5)#endif {/ / LEDカウンターを切り替える=0; if(IsOn())Off(); else On(); }}};
回路図
周辺機器の詳細な配線(ポンプ、バルブ、サーモスタット、LED) 複数の「カスケード」コントローラーの配線例。フロアユニットごとに1つのコントローラー 機能を理解するための、シリアルモニターの実際のログ。タイムスタンプは、たとえばバルブを開いてから実際にフロアユニットポンプを始動するまでに5分の遅延。製造プロセス