工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Manufacturing Technology >> 製造プロセス

Bluetoothを使用したスマートサーモスタット、放送および照明制御

コンポーネントと消耗品

>
Arduino Nano R3
× 1
HC-05Bluetoothモジュール
× 1
>
マキシムインテグレーテッドDS18B20プログラマブル解像度1-Wireデジタル温度計
× 1
oled 1306 I2C bicolor
× 1
>
ControlEverything.comI2C用4チャンネルリレーコントローラー
× 1

アプリとオンラインサービス

Android用MorichシリアルBluetoothターミナル
Android用ArduinoBluetoothコントロールデバイス

このプロジェクトについて

はじめに

Bluetoothを使用したシンプルで便利なDIYArduinoサーモスタットプロジェクト。

インテリジェントなサーモスタットルーチンがヒーターガスボイラーを制御し、システムがキッチンライトとバスルームの換気扇をリレーで切り替えます。ボタンとAndroidデバイスまたはコンピューターでBluetooth経由で制御できます。 摂氏 および華氏 バージョンもあります!すべてのパーツは手作りです。

Arduino Nano(またはそれ以降)ボードで開発され、Dallas DS18B20温度センサー、HC-05 / 06 Bluetoothアダプター、I2C128X64バイカラーOLEDディスプレイを使用–さまざまなLCD / OLEDディスプレイを選択でき、u8glibは多くのタイプをサポートします。

>

ビデオ

ビデオは、すべての重要な作業方法を示し、プロジェクトを最初から構築する方法のアイデアを提供します。

ヒーターの働き方

1:ワンタイムヒーティング(15分)タイミングモード 春/秋の夜に便利

2:サーモスタットモード(優先度が高い) 、EEPROMメモリに保存された調整済み目標温度

ボイラー保存アルゴリズム

頻繁な短期間の切り替えは、ヒーターガスボイラーの寿命を短くします。それを回避するために、プログラムは補正値を使用します。これらは、過熱と冷却の程度を宣言します。壁が冷たく、新たに加熱された空気からの暖かさをよりよく吸収するため、温度が低いほど補正値を大きくする必要があります。そのため、上記の効果はより強くなります。

開いているウィンドウの検出

プログラムは、窓が開いているかどうかを検出します。したがって、温度は1分間で少なくとも-0、2°C(-0、36F)低下します。ヒーターが停止または開始せず、エアファンがオンになります。空気をリフレッシュするのに役立ちます。環境の熱容量のために空気が少なくとも+ 0、12°C(+ 0、216F)暖かくなると、システムは通常モードに戻り、「ウィンドウアラート」イベントは閉じられます。

エラー検出

0°C(32F)未満または40°C(104F)を超える測定温度は、誤動作またはその他の問題(エラー、窓の破損、火災など)として評価され、すべてのデバイスがシャットダウンします。

Bluetooth通信

Android GUIアプリには8つのボタンがあり、時限ヒーターをオン(「A」)またはオフ(「a」)にするために大文字と小文字を送信します。「B」と「b」は放送をオンにします。 'および' c 'ライト…

私のプロジェクトのもう1つの強みは、オタク友達のBluetoothシリアル端末の使用法です。シリアル端末を使用してBluetooth経由でシステムとチャットするだけです。Androidアプリでもかまいませんが、ArduinoIDEのシリアルモニターなどの通常のPCでも可能です。

コントローラは毎分自動的に温度レポートを送信し、接続されたデバイスのオン/オフ、サーモスタットルーチンのアクティブ化など、すべてのイベントに関するインスタントレポートを送信します。

制御コード

制御コードを受け入れ、確認メッセージを送信します。 「XY」のような2桁の数字に基づく私のコマンド構造–ここで;

「X」はデバイスコード、「Y」はオペコード

30、31、32:点灯/消灯/論理状態の反転

40、41、42:放送オフ/オン/論理状態の反転

50、51、52:1回限りのヒータープログラムオフ/オン/論理状態の反転

サーモスタット機能の目標温度として10〜24の数値が受け入れられます

「r」–制御されたデバイスの動作状態に関するレポート

「w」–自動終了を待ちたくない場合は、「ウィンドウアラート」イベントを手動で無効にします

「a、a…H、h」–GUIアプリが送信したのと同じように文字が受け入れられます

華氏バージョン

私はすべての補正変数、参照値、比率値を変換したので、システムは計算と動作の特殊性を維持しました。

ほんの少しの変更。華氏バージョンの新しいデバイスコード:

1-照明(10:オフ、11:オン、12:フリップ状態)

2-放映

3-ヒーター

50〜76の数値は目標温度値です

続編

更新:内部Bluetoothリンクと音声制御を備えた完全なホームオートメーションシステム!

DallasTemperature、elapsedMillis、OneWire、SoftwareSerial、olikraus / u8glib

別のボタン抵抗を使用している場合、またはA0の読み取り値を確認する必要がある場合は、これを確認することをお勧めします:

http://blog.codebender.cc/2015/07/20/tutorial-multiple-buttons-on-1-analog-pin/

コード

  • Thermostatv11-摂氏version.ino
  • Thermostatv11-華氏version.ino
Thermostatv11-摂氏version.ino Arduino
プログラムコードはそれ自体を説明しており、初心者に役立ちます。よくコメントされ、すべての重要なステップについて説明します。何、なぜ、そしてどのように。機能ごとにモジュールに分割されているため、概要を簡単に説明できます。
 // Celsiusバージョンv1.1 //インテリジェントArduinoスマートホームサーモスタットソリューションのプログラムコード、// Arduino Nano(またはそれ以降)ボード、DS18B20サーモセンサーに基づくHC-05 Bluetoothアダプター、I2C 128X64バイカラーOLEDディスプレイ。//システムは、Bluetoothを介してボタンとAndroidスマートフォンで制御できます。////ヒーターガスボイラー、バスルームのエアリングベンチレーター、キッチンの照明を処理します。 .//ヒーターには2つの動作方法があります。 1:ワンタイムヒーティング(15分)タイミングモード、2:サーモスタットモード(優先度が高い)。調整された目標温度// EEPROMに保存されます。プログラムはハードウェアエラーとウィンドウのオープンを検出します-これらの場合、ヒーターは停止するか、起動しません。////GyulaOsiによって設計およびプログラムされています。//Allrightsreserved.//--------- -------------------------------------------------- -------------------------------------------------- ----------------------- // ----ディスプレイI2Cバス、SDA(TX)-> A4、SCL(RX)-> A5#include "U8glib.h" U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE); //コンストラクターバイトフレームを表示=0; //ロゴポインタを開始します// ----ポートと関連する宣言constbyte buzzer =9; // D9intへのブザーbtnVal; // buttonsconstバイトrelayA =11からのアナログ値を格納します; // airingbool aState =0; bool aStateByCmd; //「ウィンドウアラート」がなくなると、放送制御は元のstateconstバイトrelayL =13に戻ります。 // Lightingbool lState =0; constバイトrelayH =10; // heaterconstバイトledH =6; // PWMポートにより、brightnessconstバイトを変更するために使用される出力レベル調整が可能になりますledA =5; const byte ledL =3; const byte bright [3] ={0、10、100}; byte brightHeat =bright [2]; #define ledInterval 1000 //ヒーター主導の点滅間隔unsignedlong prev =0; // ----表示およびシリアルレポートの文字列#defineSTATE_ITEMS 3 //出力のデバイス状態インジケータ文字列// i-> 0 1 2const String state_str [STATE_ITEMS] ={"on。"、 "off。"、 "auto。"};文字列heaterState; String airingState; String LightingState; #define FUNCT_ITEMS 11 // i-> 0 1 2 3 4 5 6 7 8 9 10 String funct_str [FUNCT_ITEMS] ={"ヒーターは"、 "エアリングは"、 "照明は"、 "ウィンドウAlert! "、" Hardware Error! "、" Hit a Key>> "、" or send a Code! "、" Target tempr ="、" Temperature ="、" * "、"-"}; //- -温度測定とヒーター関連機能#include  lapsedMillis timer0; //関数elapsedMillis()#define sftyTmrInterval 15 * 60000で使用される8ビットのPWMタイマー// 1回の加熱(15分)時間指定モード間隔[ms] bool sftyTmrEnded; //ブール値の起動、timer0が終了しました#include  byte tTarget; //調整されたターゲットtemprconstint addr =0; // EEPROMメモリ内のtTarget変数の現在のアドレスboolhState =0; //ヒーターブールstateboolhThermostat =0; //サーモスタットブール状態#include "OneWire.h" #include "DallasTemperature.h" #define DS18B20 2 // D2OneWireでOneWireバスをセットアップtemprWire(DS18B20); // OneWireバスで動作するようにDS18B20を設定しますDallasTemperatureセンサー(&temprWire); float tempr; //測定値floattemprPrev; //トレンド分析の測定値のコピーboolwindowAlrt =0; //指定された次数のtemprdropbool measError =0; //測定されたtempr値がnormalconstlong temprInterval =60000として指定された範囲外です。 //周期的な温度測定間隔[ms] unsigned long temprTmrPrev =0; // temprMeas()がfloat heatCorrValと呼ばれる場合、経過は前回になります。 //過熱と冷却の程度を宣言します。tempMeas()関数を参照してください// ----仮想RXD / TXD#include でのシリアル通信の構成// HC-05constのSWシリアルRXおよびTXピンint RX1 =8; const int TX1 =4; SoftwareSerial sUART(RX1、TX1); char RX [2]; //受信したシリアルデータを保存しますboolerrMsgSentBySys =0; bool startup =1; // startupconstでBTレポートの重複を避けてくださいuint8_tframe1 [] U8G_PROGMEM ={// XBMマップ0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF 、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0x 、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0x 、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0x3F、0x00、0xFE、0xFF、0xFF、0xFF、0x07、0xFF、0x 、0x7F、0x00、0xFC、0xFF、0x7F、0xF0、0x3F、0x00、0xFE、0xFF、0xFF、0xFF、0x07、0xFF、0xFF、0xFF、0x7F、0x00、0xFC、0xFF、0x7F、0xF0 、0xFF、0xFF、0xFF、0x1F、0xFF、0xFF、0xFF、0x1F、0xFF、0xF1、0xFF、0xFF、0xFF、0x8F、0xFF、0xFF、0xFF、0xFF、0xFF、0x1F、0xFF、0xFF、0x 、0xF1、0xFF、0xFF、0xFF、0x8F、0xFF、0x1F、0x7F、0x8C 、0x3F、0x1E、0xFF、0x00、0xFE、0x1F、0xFF、0xF1、0x00、0x18、0xC0、0x8F、0xFF、0x1F、0x7F、0x8C、0x3F、0x1E、0xFF、0x00、0xFE、0x 、0x18、0xC0、0x8F、0xFF、0x1F、0x1F、0x0C、0x3E、0x1E、0xFF、0xFF、0xF8、0x1F、0xFF、0x31、0xFE、0x7F、0xFC、0x8F、0xFF、0x1 、0xFF、0xFF、0xF8、0x1F、0xFF、0x31、0xFE、0x7F、0xFC、0x0F、0x0E、0x18、0x1F、0x0C、0x3E、0x1E、0xFC、0x00、0xF8、0x1F、0x7 、0x0F、0x0E、0x18、0x1F、0x0C、0x3E、0x1E、0xFC、0x00、0xF8、0x1F、0x7C、0x30、0xFE、0x7F、0xF0、0x0F、0xFE、0x18、0x1F、0x 、0xF8、0x1F、0x7C、0xF0、0x00、0x7E、0xF0、0x0F、0xFE、0x18、0x1F、0x0C、0x3E、0x1E、0x3C、0x3E、0xF8、0x1F、0x7C、0x 、0x18、0x1F、0x0C、0x3E、0x1E、0x3C、0x3E、0xF8、0x1F、0x7C、0xF0、0x3F、0x78、0xF0、0x0F、0xFE、0x18、0x1F、0x0C、0x1 、0x7C、0xF0、0x3F、0x78、0xF0、0x0F、0xFE、0x18、0x1F、0x0C、0x3E、0x1E、0x3C、0x3E、 0xF8、0x1F、0x7C、0xF0、0x3F、0x78、0xF0、0x0F、0xFE、0x18、0x1F、0x0C、0x3E、0x1E、0x3C、0x3E、0xF8、0x1F、0x7C、0xF8、0x1F、0x7C、0xF0 0x7E、0x00、0x3C、0x80、0x07、0xF0、0x00、0xF8、0x7F、0x00、0x3C、0x00、0x1E、0xC0、0x3F、0x00、0x7E、0x00、0x3C、0x80、0x07、0x 0x00、0x3C、0x00、0x1E、0xC0、0xFF、0xFF、0xFF、0x1F、0xFC、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF 0xFC、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0x7F、0x00、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF 0xFF、0xFF、0xFF、0xFF、0xFF、0x7F、0x00、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF 0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF 0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xF F、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF 0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF 0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF 0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF、0xFF 0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00 0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00 0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、 0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00 0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00 0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00 0x00、0x00、0x00、0x00、0x7E、0x06、0xE6、0x3F、0x06、0xC6、0x7F、0xFE、0xE7、0x3F、0x7E、0xFE、0xC7、0x7F、0x00、0x00、0x30、0x06 0x66、0x00、0x60、0x60、0x60、0x30、0x06、0x60、0x00、0x00、0x00、0x30、0x06、0x66、0x60、0x06、0x66、0x00、0x60、0x60、0x60、0x30、0x06、0x60 0x00、0x00、0x30、0x1E、0x66、0x60、0x06、0x66、0x00、0x60、0x60、0x60、0x30、0x06、0x60、0x00、0x00、0x00、0x30、0x3E、0x66、0x60、0x06、0x66 0x60、0x60、0x60、0x30、0x06、0x60、0x00、0x00、0x00、0x3C、0x7E、0xE6、0x61、0x1E、0 xC7、0x3F、0x70、0xE0、0x3F、0x3C、0xFE、0xC3、0x3F、0x00、0x00、0x3C、0x7E、0xE6、0x61、0x1E、0xC7、0x3F、0x70、0xE0、0x3 0x00、0x00、0x3C、0xDE、0xE7、0x61、0x1E、0x07、0x70、0x70、0xE0、0x1D、0x3C、0x1E、0x00、0x70、0x00、0x00、0x3C、0x1E、0xE7、0x61 0x70、0xE0、0x31、0x3C、0x1E、0x00、0x70、0x00、0x00、0x3C、0x1E、0xE6、0x61、0x1E、0x07、0x70、0x70、0xE0、0x61、0x3C、0x1E、0x00 0x3C、0x1E、0xE6、0x61、0x1E、0x07、0x70、0x70、0xE0、0x61、0x3C、0x1E、0x00、0x70、0x00、0x00、0x7F、0x1E、0xE6、0x3F、0xFC、0x 0x61、0x7E、0xFE、0xE7、0x3F、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00 0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00 0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00 、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00 、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00 、0x00、0x00、0x00、}; void setup(){sUART.begin(9600); pinMode(relayH、OUTPUT); replyHandlerH(4); //動作状態を取得しますpinMode(ledH、OUTPUT); pinMode(relayA、OUTPUT); replyHandlerA(4); pinMode(ledA、OUTPUT); pinMode(relayL、OUTPUT); replyHandlerL(4); pinMode(ledL、OUTPUT); pinMode(ブザー、出力); Sensors.begin(); // DS18B20を開始しますtemprMeas(); // meas.timerを待たずに、起動時に関数を1回呼び出しますtTarget =EEPROM.read(addr); //起動時のEEPROMの現在のアドレスから以前に保存されたtTarget値を読み取ります=0; if(!measError){sTX(8); //起動後の動作状態のインスタントレポートを要求します} else {sTX(2); }} void loop(){temprTimer(); ledHandler(); btnReadings(); sRX(); SafetyTmr(); u8g.firstPage(); // scrループdo {draw(); } while(u8g.nextPage()); if(frame ==0){delay(3000);フレーム=1; clrScr(); }} void btnReadings(){// --------- Btn Readings btnVal =analogRead(A0); // A0からアナログ値を読み取りますif(btnVal> =510 &&btnVal <=516){// btn Lighting delay(100); // btnデバウンスbuzz(3、1); replyHandlerL(2); //論理状態フリップオペコードをパラメータとして適切な関数を呼び出す} else if(btnVal> =849 &&btnVal <=855){// btn Airing if(windowAlrt ==1){//システムがウィンドウアラートモードの場合、それを無効にするwindowAlrt =0; buzz(4、3); replyHandlerA(3); } else {// else人工呼吸器のオン/オフdelay(100); buzz(3、1); replyHandlerA(2); }} else if(btnVal> =927 &&btnVal <=933){// btnワンタイムヒーティング(15分)時限モードdelay(100); buzz(3、1); replyHandlerH(2); } else if(btnVal> =767 &&btnVal <=777){// btn減少tTargetdelay(100); tTargetHandler(0); } else if(btnVal> =687 &&btnVal <=697){// btn増加tTargetdelay(100); tTargetHandler(1); } else if(btnVal> =856 &&btnVal <=862){// incとdecbtnsを同時にtTarget =14; // <====初期値-最初の電源投入時にこれらのボタンを押してください! }} void sRX(){// -------------シリアルデータを受信するwhile(sUART.available()> 0){//データを読み取ることができる場合(byte i =0; i <2; i ++){RX [i] =sUART.read(); }} int iRX [2]; for(byte i =0; i <2; i ++){iRX [i] =RX [i]-'0'; } switch(RX [0]){// ------------ SINGLEALPHABETICAL制御コードを受け入れるcase'A ':relayHandlerH(1); // 1 =休憩中;ケース 'a':relayHandlerH(0); // 0 =オフブレーク; //受信したシリアルデータは、「Arduinoケース 'B':// Bluetoothコントロールデバイス」Androidアプリからの1つのアルファベット文字にすることができます。適切なアルファベット順のrelayHandlerA(1);の場合//文字が到着すると、プログラムコードは2番目の文字を待機しません。 //ただし、適切な操作コードを使用して該当する関数を呼び出します。 case'b '://結合された数値データのケースを以下に示します。 replyHandlerA(0);壊す;ケース 'C':relayHandlerL(1);壊す;ケース 'c':relayHandlerL(0);壊す;ケース 'D':ケース 'd':tTarget =21; tTargetEEPROM(); buzz(3、1);壊す;ケース 'E':ケース 'e':tTarget =19; tTargetEEPROM(); buzz(3、1);壊す;ケース 'F':ケース 'f':tTarget =14; tTargetEEPROM(); buzz(3、1);壊す;ケース 'R'://制御されたデバイスに関する概要レポートを要求するケース 'r':sTX(8);壊す; case'W '://ウィンドウアラート状態を無効にするcase'w':windowAlrt =0; buzz(4、3); replyHandlerA(3);壊す; } // ----------------------- COMBINED NUMERIC制御コードを受け入れる//この場合、2桁の数値制御コードがchar形式で到着します//たとえば、AndroidのBluetoothシリアルアプリから。文字から整数への変換後(最初の文字が「1」または「2」の場合のみ)、//マージプロセスが続き、//条件とステートメントのシステムが決定を下して実行します。 //適切な数値コードは次のとおりです。////----------------目標温度:// 10-24の値がサーモスタット機能の目標温度として受け入れられます。 // // ----------------デバイス制御コード://最初の=デバイスコード、2番目の=オペレーターコード// 30、31、32は照明をオンにします:30 =オフ、 31 =オン// 32 =論理状態を反転(オン->オフ/オフ->オン)// 40、41、42は人工呼吸器に対して同じことを行います// 50、51、52は1回限りの加熱を処理します(15 mins)上記のタイミングヒータープログラム// // ----------------分類されたオペレーターコード:// X3、X4は分類され、内部プログラムシーケンスによる関数呼び出しにのみ使用されますif( RX [0] =='3'){relayHandlerL(iRX [1]); } if(RX [0] =='4'){relayHandlerA(iRX [1]); } if(RX [0] =='5'){relayHandlerH(iRX [1]); } if((iRX [0] * 10 + iRX [1] <=24)&&(iRX [0] * 10 + iRX [1]> =10)){// 10〜24の数値のみを受け入れるtTarget =iRX [0] * 10 + iRX [1]; // 2つの整数をマージし、tTargetを設定しますtTargetEEPROM(); //設定後、EEPROMハンドラー関数を呼び出し、buzz(3、1); // tTarget値をEEPROMの適切なバイトに書き込みます} if(RX [0] =='0'){//(byte i =1; i <5; i ++){buzz(5、2)をテストします; }} for(byte i =0; i <2; i ++){//すべてのメッセージ受信者と変換変数を空にするRX [i] ='Z'; }} void relayHandlerL(byte lOperator){//ライティングハンドラシーケンス//演算子は次のとおりです:0 =オフ、1 =オン、2 =状態を反転、4 =ライティング状態を塗りつぶす/補充するcharvar。 if((measError)&&((lOperator ==1)||(lOperator ==2))){sTX(4);戻る; } if((lOperator ==2)||(lOperator ==0)&&(lState)||(lOperator ==1)&&(!lState)){lState =!lState; digitalWrite(relayL、lState); buzz(2、1); } if(lOperator> =0){//動作状態の文字を適切な状態インジケーター文字列で埋めるif(lState){lightingState =state_str [0]; } else {lightingState =state_str [1]; } if(!startup){sTX(7); }}} void replyHandlerA(byte aOperator){//エアリングハンドラシーケンスif((measError)&&((aOperator ==1)||(aOperator ==2))){//演算子は次のとおりです:0 =off、1 =オン、2 =状態を反転、sTX(4); // 3 =temprMeas()関数によって呼び出されます。4=放送状態のcharvarを塗りつぶし/補充します。戻る; } aState =digitalRead(relayA); if(!windowAlrt){if((aOperator ==2)||(aState)&&(aOperator ==0)||(!aState)&&(aOperator ==1)){aState =!aState; digitalWrite(relayA、aState); aStateByCmd =digitalRead(relayA); buzz(2、1); }} if(aOperator ==3){// temprMeas()関数によって呼び出され、 'windowAlrt'が終了または開始if((!aState)&&(windowAlrt)||(aState)&&(!windowAlrt)&&(!aStateByCmd )){digitalWrite(relayA、windowAlrt); }} aState =digitalRead(relayA); if(aOperator> =0){if(aState){if(windowAlrt){airingState =state_str [2]; } else {airingState =state_str [0]; }} else {airingState =state_str [1]; }} if(!startup){sTX(6); }} void replyHandlerH(byte hOperator){//ヒーターハンドラーシーケンス//演算子は次のとおりです:0 =オフ、1 =オン、2 =状態を反転、// 3 =temprMeas()関数によって呼び出されます。4=塗りつぶし/補充ヒーター状態charvar。 if((measError)&&((hOperator ==1)||(hOperator ==2))){sTX(4);戻る; } if((!hThermostat)&&(!windowAlrt)&&(!measError)){//ワンタイムヒーティング(15分)タイミングモードのオン/オフif((hOperator ==2)||(hOperator ==1 )&&(!hState)||(!hOperator)&&(hState)){buzz(2、1); hState =!hState; sftyTmrEnded =0; timer0 =0; digitalWrite(relayH、hState); }} if(windowAlrt){sTX(3); } if(hOperator ==3){// temprMeas()関数によって呼び出されるこの関数(op 3)// windowAlrt&measErrorブール値を調べるためif((windowAlrt)&&(hState)){//ウィンドウは開いて、ヒーターが実行されているdigitalWrite(relayH、0); buzz(5、3); } if((!windowAlrt)&&(!measError)){if((hThermostat)||(!hThermostat)&&(hState)&&(sftyTmrEnded)){digitalWrite(relayH、hThermostat); //サーモスタットルーチンのコマンドを続行します}}} hState =digitalRead(relayH); if(hOperator> =0){if(hState){if(hThermostat){heaterState =state_str [2]; } else {heaterState =state_str [0]; }} else {heaterState =state_str [1]; } if((((!windowAlrt)&&(hOperator!=3))||(hState))&&(!startup)){sTX(5); }}} void SafetyTmr(){//ワンタイムヒーティング(15分のタイミング)モードのタイマーif((hState)&&(!sftyTmrEnded)&&(timer0> sftyTmrInterval)&&(!hThermostat)){sftyTmrEnded =1; replyHandlerH(0); for(byte i =1; i <5; i ++){buzz(i、2); }}} void temprTimer(){// temprMeas()のサイクリックタイマーunsigned long temprTmrCurr =millis(); if(temprInterval <=temprTmrCurr --temprTmrPrev){temprTmrPrev =temprTmrCurr; temprMeas(); }} void temprMeas(){// -----------温度測定と比較シーケンスtemprPrev =tempr; //次の比較のために値を保存しますsensors.requestTemperatures(); //センサーの読み取り値を更新しますtempr =Sensors.getTempCByIndex(0); //温度を読み取るif((tempr> =40)||(tempr <=0)){//極端な測定値:if(!errMsgSentBySys){// -127、-196.60はHWエラー、+ 85は通常SWエラーですが、sTX(4); //火災、または壊れたウィンドウの可能性があります} errMsgSentBySys =1; hThermostat =0; if(hState){relayHandlerH(0); } if(aState){relayHandlerA(0); } if(lState){relayHandlerL(0); } measError =1; for(byte i =1; i <10; i ++){buzz(4、1); delay(50); }} else {temprPrev =tempr; measError =0; errMsgSentBySys =0; } if(!measError){// ------------温度分析シーケンスの開始if(tempr <=17){//ヒーターガスボイラーの頻繁な短期間の切り替えは短くなりますその寿命、heatCorrVal =0.5; // heatCorrVal値は、それを回避し続けるのに役立ちます。過熱および冷却の程度を宣言します。 } //温度が低いほど、より多くのheatCorrValが必要になります。これは、壁が冷たく、if((tempr> 17)&&(tempr <19)){//新たに加熱された空気からの暖かさを吸収するためです。したがって、上記の効果は次のようになります。より効果的。 heatCorrVal =0.4; } if(tempr> =19){heatCorrVal =0.3; } if(tTarget --tempr> =heatCorrVal){//差がheatCorrVal sftyTmrEnded =1以上の場合、ターゲットから測定値を減算します。 // hThermostat =1を実行している場合、ワンタイムヒーティング(15分)タイミングプログラムを非アクティブ化します。 //サーモスタットをオンにしますbuzz(1、1); } if((tTarget --tempr <=-1 * heatCorrVal)&&(hThermostat)){hThermostat =0; } if((temprPrev --tempr> =0.2)&&(!windowAlrt)&&(tempr <=20)){//測定サイクルおよび暖房シーズンの温度windowAlrt =1; //ドロップし、ウィンドウが開いていると評価されますsftyTmrEnded =1; for(byte i =1; i <5; i ++){buzz(4、1); delay(50); } replyHandlerA(3); //空気をリフレッシュするためにairing関数(opcode =3)を呼び出します} if((temprPrev --tempr <=-0.12)&&(windowAlrt)){// tempr。落下が終わり、空気が暖かくなりましたwindowAlrt =0; //環境の熱容量のため、buzz(4、3); //したがって、通常モードに戻りますrelayHandlerA(3); } replyHandlerH(3); //関数は呼び出し元のparam(3)&windowAlrt&measErrorブール値を調べますif(!windowAlrt){sTX(1); }}} void tTargetHandler(bool set){//必要なtemprを増減して設定if(!set){// incr if(tTarget <24){//上限に達するまでtTarget ++; buzz(3、1); } else {buzz(2、3); }} else {// decr if(tTarget> 10){tTarget--; buzz(3、1); } else { buzz(2, 3); } } tTargetEEPROM();}void tTargetEEPROM() { EEPROM.write(addr, tTarget); // after incr/decr/set, write the tTarget value to the appropriate byte of the EEPROM delay(10); sTX(2);}void draw(void) { // logo handler if (frame ==0) { u8g.drawXBMP( 0, 0, 128, 64, frame1); } else if (frame ==1) screenFunctState(); } void screenFunctState(void) { // function state screen temprWriteOut(0, 64); u8g.drawHLine(0, 46, 128); u8g.setFont(u8g_font_unifont); if (!windowAlrt) { u8g.setPrintPos( 0, 14); u8g.print(funct_str[0]); u8g.setPrintPos(84, 14); u8g.print(heaterState); } else { u8g.setPrintPos( 0, 14); u8g.print(funct_str[3]); } u8g.setPrintPos( 0, 28); u8g.print(funct_str[1]); u8g.setPrintPos(88, 28); u8g.print(airingState); u8g.setPrintPos( 0, 42); u8g.print(funct_str[2]); u8g.setPrintPos(95, 42); u8g.print(lightingState); if ((!hState) &&(!aState) &&(!lState)) { screenStndby(); // if all of controlled devices are in off, call standby screen }}void screenStndby() { // standby scr u8g.firstPage(); do { u8g.setFontRefHeightText(); u8g.setFont(u8g_font_unifont); if (!measError) { u8g.setPrintPos(33, 52); u8g.print(funct_str[5]); u8g.setPrintPos( 8, 64); u8g.print(funct_str[6]); } else { u8g.setPrintPos( 4, 48); u8g.print(funct_str[4]); } temprWriteOut(0, 16); } while( u8g.nextPage() );}void temprWriteOut (byte tX, byte tY) { // draw tempr &tTarget variables onto different coordinates u8g.setFont(u8g_font_courB14);//u8g.setFont(u8g_font_6x12); // you can save ~10% of prog.memory using this font with 2x2 scale char buftTarget[9]; sprintf (buftTarget, "%d", tTarget); // int to char//u8g.setScale2x2();//tY =tY / 2; u8g.setPrintPos(tX, tY); u8g.print(buftTarget); u8g.setPrintPos(tX+18, tY); u8g.print(funct_str[9]); u8g.setPrintPos(tX+50, tY); u8g.print(tempr); u8g.print(char(176)); u8g.print("C");//u8g.undoScale();}void clrScr(){ u8g.firstPage(); do { } while( u8g.nextPage() );}void ledHandler() { // the brightness of a led is low, if the indicated device is off, and high, if its on if (aState) { analogWrite(ledA, bright[2]); } else { analogWrite(ledA, bright[1]); } if (lState) { analogWrite(ledL, bright[2]); } else { analogWrite(ledL, bright[1]); } if (hState) { if (!hThermostat) { ledBlnk(); // the heater led blinks when the One Time Heating (15 mins) timed mode is activated, } else { brightHeat =bright[2]; // and constant bright, if the thermostat routine is active } } else { brightHeat =bright[1]; } analogWrite(ledH, brightHeat);}void ledBlnk() { unsigned long curr =millis(); if (ledInterval <=curr - prev) { // subtract prev value from current, if the difference equals or greater than ledInterval const. prev =curr; // overwrite the earlier value with the current and flip brightness level if (brightHeat ==bright[1]) { brightHeat =bright[2]; } else { brightHeat =bright[1]; } } analogWrite(ledH, brightHeat);}void buzz(byte b, byte d) { // call with frequency and delay parameters tone(buzzer, b * 1000); delay(d * 100); noTone(buzzer);}void sTX(byte reportTX) { // sending serial reports switch (reportTX) { case 0:for (byte i =0; i <9; i++) { sUART.print(funct_str[10]); } sUART.println(funct_str[10]);壊す; case 1:sUART.print(funct_str[8]); // Tempr. sUART.print(tempr); sUART.print(char(176)); sUART.println("C");壊す; case 2:sUART.print(funct_str[7]); // TTemp sUART.print(tTarget); sUART.print(char(176)); sUART.println("C");壊す; case 3:sUART.print(funct_str[3]); // Window Alert sUART.print(funct_str[9]); sUART.print(tempr); sUART.print(char(176)); sUART.println("C");壊す; case 4:sUART.println(funct_str[4]); // Error report break; case 5:sUART.print(funct_str[0]); // Working state of devices sUART.println(heaterState);壊す; case 6:sUART.print(funct_str[1]); sUART.println(airingState);壊す; case 7:sUART.print(funct_str[2]); sUART.println(lightingState);壊す; case 8:// Overview report sTX(0); relayHandlerH(4); relayHandlerA(4); relayHandlerL(4); sTX(2); if (measError) { sTX(4); } break; }} 
Thermostat v11 - Fahrenheit version.inoArduino
The program code explains itself, useful for beginners. Well commented, describes every important steps; what, why and how. Divided into modules by functions, that’s why easy to overview.
Works in Fahrenheit, I changed only the Target temperature values (50-76), and the device codes (1, 2 and 3).
// Fahrenheit version v1.1// Program code of an intelligent Arduino smarthome thermostat solution, // based on Arduino Nano (or higher) board, DS18B20 thermo sensor, HC-05 Bluetooth adapter, I2C 128X64 bicolor OLED display.// The system can be controlled by buttons and Android smartphone via bluetooth.//// It handles the HEATER gas boiler, the bathroom AIRING ventilator and the kitchen LIGHTING - swithed with relays.// The heater has two working ways. 1:One Time Heating (15 mins) timed mode, 2:Thermostat mode (higher priority). The adjusted target tempr.// stored in EEPROM. The program detects hardware errors and window opening - in these cases the heater stops and/or will not start.//// Designed and programmed by Gyula Osi.// All rights reserved.// ------------------------------------------------------------------------------------------------------------------------------------// ---- Display I2C Bus, SDA(TX) -> A4, SCL(RX) -> A5#include "U8glib.h"U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE); // display constructorbyte frame =0; // start logo pointer// ---- Ports and related declarationsconst byte buzzer =9; // buzzer to D9int btnVal; // stores analog values from buttonsconst byte relayA =11; // airingbool aState =0;bool aStateByCmd; // if "window alert" is gone, the airing control goes back to the original stateconst byte relayL =13; // lightingbool lState =0;const byte relayH =10; // heaterconst byte ledH =6; // PWM ports allow output level adjustment used to change brightnessconst byte ledA =5; const byte ledL =3;const byte bright[3] ={0, 10, 100};byte brightHeat =bright[2];#define ledInterval 1000 // heater led blinking intervalunsigned long prev =0;// ---- Strings for Display and Serial Reports #define STATE_ITEMS 3 // device state indicator strings for outputs// i -> 0 1 2const String state_str[STATE_ITEMS] ={"on.", "off.", "auto."}; String heaterState; String airingState;String lightingState;#define FUNCT_ITEMS 11// i -> 0 1 2 3 4 5 6 7 8 9 10 String funct_str[FUNCT_ITEMS] ={"Heater is ", "Airing is ", "Lighting is ", "Window Alert!", "Hardware Error!", "Hit a Key>>", "or send a Code!", "Target tempr =", "Temperature =", " * ", " -"};// ---- Temperature Measurement and Heater Related Features#include  elapsedMillis timer0; // 8-bit, PWM timer, used by function elapsedMillis()#define sftyTmrInterval 15 * 60000 // one Time Heating (15 mins) timed mode interval [ms]bool sftyTmrEnded; // boolean startup, the timer0 has ended#include byte tTarget; // adjusted target temprconst int addr =0; // the current address of the tTarget variable in the EEPROM memorybool hState =0; // heater boolean statebool hThermostat =0; // thermostat boolean state#include "OneWire.h" #include "DallasTemperature.h"#define DS18B20 2 // setup the OneWire bus on D2OneWire temprWire(DS18B20); // setup DS18B20 to work on the OneWire busDallasTemperature sensors(&temprWire);float tempr; // measured valuefloat temprPrev; // copy of measured value for trend analysisbool windowAlrt =0; // specified degree of tempr dropbool measError =0; // measured tempr value is out of the range specified as normalconst long temprInterval =60000; // cyclic tempr measurement interval [ms]unsigned long temprTmrPrev =0; // the elapsed will be the previous when temprMeas() calledfloat heatCorrVal; // declares the degree of overheating and cooling back, see tempMeas() function// ---- Configuration of Serial Communication on virtual RXD/TXD#include  // SW serial RX &TX pins for HC-05const int RX1 =8;const int TX1 =4;SoftwareSerial sUART(RX1,TX1); char RX[2]; // store received serial databool errMsgSentBySys =0; bool startup =1; // keep avoid a duplicate BT report at startupconst uint8_t frame1[] U8G_PROGMEM ={ // XBM map 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFC, 0xFF, 0x7F, 0xF0, 0x3F, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFC, 0xFF, 0x7F, 0xF0, 0x8F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xF1, 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xF1, 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0x1F, 0x7F, 0x8C , 0x3F, 0x1E, 0xFF, 0x00, 0xFE, 0x1F, 0xFF, 0xF1, 0x00, 0x18, 0xC0, 0x8F, 0xFF, 0x1F, 0x7F, 0x8C, 0x3F, 0x1E, 0xFF, 0x00, 0xFE, 0x1F, 0xFF, 0xF1, 0x00, 0x18, 0xC0, 0x8F, 0xFF, 0x1F, 0x1F, 0x0C, 0x3E, 0x1E, 0xFF, 0xFF, 0xF8, 0x1F, 0xFF, 0x31, 0xFE, 0x7F, 0xFC, 0x8F, 0xFF, 0x1F, 0x1F, 0x0C, 0x3E, 0x1E, 0xFF, 0xFF, 0xF8, 0x1F, 0xFF, 0x31, 0xFE, 0x7F, 0xFC, 0x0F, 0x0E, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0xFC, 0x00, 0xF8, 0x1F, 0x7C, 0x30, 0xFE, 0x7F, 0xF0, 0x0F, 0x0E, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0xFC, 0x00, 0xF8, 0x1F, 0x7C, 0x30, 0xFE, 0x7F, 0xF0, 0x0F, 0xFE, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0x3C, 0x3E, 0xF8, 0x1F, 0x7C, 0xF0, 0x00, 0x7E, 0xF0, 0x0F, 0xFE, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0x3C, 0x3E, 0xF8, 0x1F, 0x7C, 0xF0, 0x00, 0x7E, 0xF0, 0x0F, 0xFE, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0x3C, 0x3E, 0xF8, 0x1F, 0x7C, 0xF0, 0x3F, 0x78, 0xF0, 0x0F, 0xFE, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0x3C, 0x3E, 0xF8, 0x1F, 0x7C, 0xF0, 0x3F, 0x78, 0xF0, 0x0F, 0xFE, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0x3C, 0x3E, 0xF8, 0x1F, 0x7C, 0xF0, 0x3F, 0x78, 0xF0, 0x0F, 0xFE, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0x3C, 0x3E, 0xF8, 0x1F, 0x7C, 0xF0, 0x3F, 0x78, 0xF0, 0x3F, 0x00, 0x7E, 0x00, 0x3C, 0x80, 0x07, 0xF0, 0x00, 0xF8, 0x7F, 0x00, 0x3C, 0x00, 0x1E, 0xC0, 0x3F, 0x00, 0x7E, 0x00, 0x3C, 0x80, 0x07, 0xF0, 0x00, 0xF8, 0x7F, 0x00, 0x3C, 0x00, 0x1E, 0xC0, 0xFF, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x06, 0xE6, 0x3F, 0x06, 0xC6, 0x7F, 0xFE, 0xE7, 0x3F, 0x7E, 0xFE, 0xC7, 0x7F, 0x00, 0x00, 0x30, 0x06, 0x66, 0x60, 0x06, 0x66, 0x00, 0x60, 0x60, 0x60, 0x30, 0x06, 0x60, 0x00, 0x00, 0x00, 0x30, 0x06, 0x66, 0x60, 0x06, 0x66, 0x00, 0x60, 0x60, 0x60, 0x30, 0x06, 0x60, 0x00, 0x00, 0x00, 0x30, 0x1E, 0x66, 0x60, 0x06, 0x66, 0x00, 0x60, 0x60, 0x60, 0x30, 0x06, 0x60, 0x00, 0x00, 0x00, 0x30, 0x3E, 0x66, 0x60, 0x06, 0x66, 0x00, 0x60, 0x60, 0x60, 0x30, 0x06, 0x60, 0x00, 0x00, 0x00, 0x3C, 0x7E, 0xE6, 0x61, 0x1E, 0 xC7, 0x3F, 0x70, 0xE0, 0x3F, 0x3C, 0xFE, 0xC3, 0x3F, 0x00, 0x00, 0x3C, 0x7E, 0xE6, 0x61, 0x1E, 0xC7, 0x3F, 0x70, 0xE0, 0x3F, 0x3C, 0xFE, 0xC3, 0x3F, 0x00, 0x00, 0x3C, 0xDE, 0xE7, 0x61, 0x1E, 0x07, 0x70, 0x70, 0xE0, 0x1D, 0x3C, 0x1E, 0x00, 0x70, 0x00, 0x00, 0x3C, 0x1E, 0xE7, 0x61, 0x1E, 0x07, 0x70, 0x70, 0xE0, 0x31, 0x3C, 0x1E, 0x00, 0x70, 0x00, 0x00, 0x3C, 0x1E, 0xE6, 0x61, 0x1E, 0x07, 0x70, 0x70, 0xE0, 0x61, 0x3C, 0x1E, 0x00, 0x70, 0x00, 0x00, 0x3C, 0x1E, 0xE6, 0x61, 0x1E, 0x07, 0x70, 0x70, 0xE0, 0x61, 0x3C, 0x1E, 0x00, 0x70, 0x00, 0x00, 0x7F, 0x1E, 0xE6, 0x3F, 0xFC, 0xE3, 0x3F, 0x70, 0xE0, 0x61, 0x7E, 0xFE, 0xE7, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };void setup() { sUART.begin(9600); pinMode(relayH, OUTPUT); relayHandlerH(4); // get the working state pinMode(ledH, OUTPUT); pinMode(relayA, OUTPUT); relayHandlerA(4); pinMode(ledA, OUTPUT); pinMode(relayL, OUTPUT); relayHandlerL(4); pinMode(ledL, OUTPUT); pinMode(buzzer, OUTPUT); Sensors.begin(); // start DS18B20 temprMeas(); // do not wait for the meas.timer, call the function once at startup tTarget =EEPROM.read(addr); // read the previously stored tTarget value from the current address of the EEPROM at startup startup =0; if (!measError) { sTX(8); // call for instant report of working states after startup } else { sTX(2); }}void loop() { temprTimer(); ledHandler(); btnReadings(); sRX(); safetyTmr(); u8g.firstPage(); // scr loop do { draw(); } while( u8g.nextPage() ); if (frame ==0) { delay(3000); frame =1; clrScr(); }}void btnReadings() { // --------- Btn Readings btnVal =analogRead(A0); // read analog val from A0 if (btnVal>=510 &&btnVal <=516) { // btn Lighting delay(100); // btn debounce buzz(3, 1); relayHandlerL(2); // call proper function with logical state flip opcode as parameter } else if (btnVal>=849 &&btnVal <=855){ // btn Airing if (windowAlrt ==1) { // if the system is in Window Alert mode, disable it windowAlrt =0; buzz(4, 3); relayHandlerA(3); } else { // else turn on/off the airing ventilator delay(100); buzz(3, 1); relayHandlerA(2); } } else if (btnVal>=927 &&btnVal <=933){ // btn One Time Heating (15 mins) timed mode delay(100); buzz(3, 1); relayHandlerH(2); } else if (btnVal>=767 &&btnVal <=777) { // btn decrease tTarget delay(100); tTargetHandler(0); } else if (btnVal>=687 &&btnVal <=697) { // btn increase tTarget delay(100); tTargetHandler(1); } else if (btnVal>=856 &&btnVal <=862) { // inc &dec btns at the same time tTarget =14; // <====initial value - press these buttons at the very first powerup! }}void sRX() { // ------------- Receive Serial Data while (sUART.available()> 0) { // if data is available to read for (byte i =0; i <2; i++) { RX[i] =sUART.read(); } } int iRX[2]; for (byte i =0; i <2; i++) { iRX[i] =RX[i] - '0'; } switch (RX[0]) { // ------------ accept SINGLE ALPHABETICAL control codes case 'A':relayHandlerH(1); // 1 =on break; case 'a':relayHandlerH(0); // 0 =off break; // Received serial data can be a single alphabetical letter from "Arduino case 'B':// Bluetooth Control Device" Android app. If a proper alphabetical relayHandlerA(1); // character arrives, the program code will not wait for the second one, break; // but calls the applicable function with a proper operation code. case 'b':// Cases of combined numeric data can be seen below. relayHandlerA(0);壊す; case 'C':relayHandlerL(1);壊す; case 'c':relayHandlerL(0);壊す; case 'D':case 'd':tTarget =21; tTargetEEPROM(); buzz(3, 1);壊す; case 'E':case 'e':tTarget =19; tTargetEEPROM(); buzz(3, 1);壊す; case 'F':case 'f':tTarget =14; tTargetEEPROM(); buzz(3, 1);壊す; case 'R':// call for an overview report about controlled devices case 'r':sTX(8);壊す; case 'W':// disable Window Alert state case 'w':windowAlrt =0; buzz(4, 3); relayHandlerA(3);壊す; } // ----------------------- accept COMBINED NUMERIC control codes // In this case a two-digit numeric control code arrives in char format, // from an Android bluetooth serial app for instance. After a char to integer // conversion (only if the first char is '1' or '2') a merge-process will follow, // and the system of conditions and statements will make a decision and execute it. // Appropriate numeric codes are:// // ---------------- Target Temperature:// 50 - 76 values will be accepted as a target temperature for the thermostat function. // // ---------------- Device Control Codes:// First =device code, Second =operator code // 10, 11, 12 turns the lighting:10=off, 11=on // 12=flip logical state (on -> off / off -> on) // 20, 21, 22 will do the same to the airing ventilator // 30, 31, 32 handles the One Time Heating (15 mins) timed heater program as above // // ---------------- Classified Operator Codes:// X3, X4 are classified, used only for function calls by inner program sequences if (RX[0] =='1') { relayHandlerL(iRX[1]); } if (RX[0] =='2') { relayHandlerA(iRX[1]); } if (RX[0] =='3') { relayHandlerH(iRX[1]); } if ((iRX[0] * 10 + iRX[1] <=76) &&(iRX[0] * 10 + iRX[1]>=50)) { // accept only numeric values between 50 &76 tTarget =iRX[0] * 10 + iRX[1]; // merge two integers and set tTarget tTargetEEPROM(); // after set, call the EEPROM handler function, and buzz(3, 1); // write the tTarget value to the appropriate byte of the EEPROM } if (RX[0] =='0') { // test for (byte i =1; i <5; i++) { buzz(5, 2); } } for (byte i =0; i <2; i++) { // empty all message receiver and conversion variables RX[i] ='Z'; } }void relayHandlerL(byte lOperator) { // Lighting Handler Sequence // operators are:0=off, 1=on, 2=flip the state, 4=fill/refill the lighting state char var. if ((measError) &&((lOperator ==1) || (lOperator ==2))) { sTX(4);戻る; } if ((lOperator ==2) || (lOperator ==0) &&(lState) || (lOperator ==1) &&(!lState)) { lState =!lState; digitalWrite(relayL, lState); buzz(2, 1); } if (lOperator>=0) { // fill up the working state char with the proper state indicator string if (lState) { lightingState =state_str[0]; } else { lightingState =state_str[1]; } if (!startup) { sTX(7); } }}void relayHandlerA(byte aOperator) { // Airing Handler Sequence if ((measError) &&((aOperator ==1) || (aOperator ==2))) { // operators are:0=off, 1=on, 2=flip the state, sTX(4); // 3=called by temprMeas() funct., 4=fill/refill the airing state char var.戻る; } aState =digitalRead(relayA); if (!windowAlrt) { if ((aOperator ==2) || (aState) &&(aOperator ==0) || (!aState) &&(aOperator ==1)) { aState =!aState; digitalWrite(relayA, aState); aStateByCmd =digitalRead(relayA); buzz(2, 1); } } if (aOperator ==3) { // called by the temprMeas() function, 'windowAlrt' ended or started if ((!aState) &&(windowAlrt) || (aState) &&(!windowAlrt) &&(!aStateByCmd)) { digitalWrite(relayA, windowAlrt); } } aState =digitalRead(relayA); if (aOperator>=0) { if (aState) { if (windowAlrt) { airingState =state_str[2]; } else { airingState =state_str[0]; } } else { airingState =state_str[1]; } } if (!startup) { sTX(6); }} void relayHandlerH(byte hOperator) { // Heater Handler Sequence // operators are:0=off, 1=on, 2=flip the state, // 3=called by temprMeas() funct., 4=fill/refill the heater state char var. if ((measError) &&((hOperator ==1) || (hOperator ==2))) { sTX(4);戻る; } if ((!hThermostat) &&(!windowAlrt) &&(!measError)) { // turn on/off the One Time Heating (15 mins) timed mode if ((hOperator ==2) || (hOperator ==1) &&(!hState) || (!hOperator) &&(hState)) { buzz(2, 1); hState =!hState; sftyTmrEnded =0; timer0 =0; digitalWrite(relayH, hState); } } if (windowAlrt) { sTX(3); } if (hOperator ==3) { // this function called by the temprMeas() function (op 3) // in order to examine windowAlrt &measError booleans if ((windowAlrt) &&(hState)) { // a window is open and the heater is running digitalWrite(relayH, 0); buzz(5, 3); } if ((!windowAlrt) &&(!measError)) { if ((hThermostat) || (!hThermostat) &&(hState) &&(sftyTmrEnded)) { digitalWrite(relayH, hThermostat); // proceed the command of the Thermostat Routine } } } hState =digitalRead(relayH); if (hOperator>=0) { if (hState) { if (hThermostat) { heaterState =state_str[2]; } else { heaterState =state_str[0]; } } else { heaterState =state_str[1]; } if ((((!windowAlrt) &&(hOperator !=3)) || (hState)) &&(!startup)) { sTX(5); } }}void safetyTmr () { // Timer for the One Time Heating (15 mins timed) mode if ((hState) &&(!sftyTmrEnded) &&(timer0> sftyTmrInterval) &&(!hThermostat)) { sftyTmrEnded =1; relayHandlerH(0); for (byte i =1; i <5; i++) { buzz(i, 2); } }}void temprTimer() { // Cyclic Timer for temprMeas() unsigned long temprTmrCurr =millis(); if (temprInterval <=temprTmrCurr - temprTmrPrev) { temprTmrPrev =temprTmrCurr; temprMeas(); } }void temprMeas() { // ----------- Temperature Measurement &Comparison Sequence temprPrev =tempr; // save the value for next comparison sensors.requestTemperatures(); // update sensor readings tempr =sensors.getTempFByIndex(0); // read remperature if ((tempr>=104) || (tempr <=32)) { // extreme meas values:if (!errMsgSentBySys) { // -127, -196.60 are HW errors, +85 is tipically SW error, but sTX(4); // can be fire, or a broken window } errMsgSentBySys =1; hThermostat =0; if (hState) { relayHandlerH(0); } if (aState) { relayHandlerA(0); } if (lState) { relayHandlerL(0); } measError =1; for (byte i =1; i <10; i++) { buzz(4, 1); delay(50); } } else { temprPrev =tempr; measError =0; errMsgSentBySys =0; } if (!measError) { // ------------ Start of Temperature Analysis Sequence if (tempr <=62.6) { // Frequent, short-term switching of the heater gas boiler would cut short its lifetime, the heatCorrVal =0.9; // heatCorrVal value helps to keep avoid it. Declares the degree of overheating and cooling back. } // Lower temperature demands greater heatCorrVal, because the walls are colder and adsorb better the if ((tempr> 62.6) &&(tempr <66.2)) { // warmth from the freshly heated-up air, so the above described effect would more effective. heatCorrVal =0.72; } if (tempr>=66.2) { heatCorrVal =0.54; } if (tTarget - tempr>=heatCorrVal) { // subtract measured value from target, if the difference equals or greater than heatCorrVal sftyTmrEnded =1; // deactivate the One Time Heating (15 mins) timed program if it is running hThermostat =1; // turn on the thermostat buzz(1, 1); } if ((tTarget - tempr <=-1 * heatCorrVal) &&(hThermostat)) { hThermostat =0; } if ((temprPrev - tempr>=0.36) &&(!windowAlrt) &&(tempr <=68)) { // in a measurement cycle and in heating season the temperature windowAlrt =1; // drops, it will evaluate as a window is open sftyTmrEnded =1; for (byte i =1; i <5; i++) { buzz(4, 1); delay(50); } relayHandlerA(3); // call airing function (opcode =3), to help refresh the air } if ((temprPrev - tempr <=-0.216) &&(windowAlrt)) { // the tempr. falling is over, the air became warmer windowAlrt =0; // due to the heat capacity of the environment, buzz(4, 3); // so switch back to normal mode relayHandlerA(3); } relayHandlerH(3); // the function will examine caller param(3) &windowAlrt &measError booleans if (!windowAlrt) { sTX(1); } }}void tTargetHandler (bool set) { // set the needed tempr by increasing or decreasing if (!set) { // incr if (tTarget <76) { // until it reaches the upper limit tTarget++; buzz(3, 1); } else { buzz(2, 3); } } else { // decr if (tTarget> 50) { tTarget--; buzz(3, 1); } else { buzz(2, 3); } } tTargetEEPROM();}void tTargetEEPROM() { EEPROM.write(addr, tTarget); // after incr/decr/set, write the tTarget value to the appropriate byte of the EEPROM delay(10); sTX(2);}void draw(void) { // logo handler if (frame ==0) { u8g.drawXBMP( 0, 0, 128, 64, frame1); } else if (frame ==1) screenFunctState(); } void screenFunctState(void) { // function state screen temprWriteOut(0, 64); u8g.drawHLine(0, 46, 128); u8g.setFont(u8g_font_unifont); if (!windowAlrt) { u8g.setPrintPos( 0, 14); u8g.print(funct_str[0]); u8g.setPrintPos(84, 14); u8g.print(heaterState); } else { u8g.setPrintPos( 0, 14); u8g.print(funct_str[3]); } u8g.setPrintPos( 0, 28); u8g.print(funct_str[1]); u8g.setPrintPos(88, 28); u8g.print(airingState); u8g.setPrintPos( 0, 42); u8g.print(funct_str[2]); u8g.setPrintPos(95, 42); u8g.print(lightingState); if ((!hState) &&(!aState) &&(!lState)) { screenStndby(); // if all of controlled devices are in off, call standby screen }}void screenStndby() { // standby scr u8g.firstPage(); do { u8g.setFontRefHeightText(); u8g.setFont(u8g_font_unifont); if (!measError) { u8g.setPrintPos(33, 52); u8g.print(funct_str[5]); u8g.setPrintPos( 8, 64); u8g.print(funct_str[6]); } else { u8g.setPrintPos( 4, 48); u8g.print(funct_str[4]); } temprWriteOut(0, 16); } while( u8g.nextPage() );}void temprWriteOut (byte tX, byte tY) { // draw tempr &tTarget variables onto different coordinates u8g.setFont(u8g_font_courB14);//u8g.setFont(u8g_font_6x12); // you can save ~10% of prog.memory using this font with 2x2 scale char buftTarget[9]; sprintf (buftTarget, "%d", tTarget); // int to char//u8g.setScale2x2();//tY =tY / 2; u8g.setPrintPos(tX, tY); u8g.print(buftTarget); u8g.setPrintPos(tX+18, tY); u8g.print(funct_str[9]); u8g.setPrintPos(tX+50, tY); u8g.print(tempr); //u8g.print(char(176)); u8g.print("F");//u8g.undoScale();}void clrScr(){ u8g.firstPage(); do { } while( u8g.nextPage() );}void ledHandler() { // the brightness of a led is low, if the indicated device is off, and high, if its on if (aState) { analogWrite(ledA, bright[2]); } else { analogWrite(ledA, bright[1]); } if (lState) { analogWrite(ledL, bright[2]); } else { analogWrite(ledL, bright[1]); } if (hState) { if (!hThermostat) { ledBlnk(); // the heater led blinks when the One Time Heating (15 mins) timed mode is activated, } else { brightHeat =bright[2]; // and constant bright, if the thermostat routine is active } } else { brightHeat =bright[1]; } analogWrite(ledH, brightHeat);}void ledBlnk() { unsigned long curr =millis(); if (ledInterval <=curr - prev) { // subtract prev value from current, if the difference equals or greater than ledInterval const. prev =curr; // overwrite the earlier value with the current and flip brightness level if (brightHeat ==bright[1]) { brightHeat =bright[2]; } else { brightHeat =bright[1]; } } analogWrite(ledH, brightHeat);}void buzz(byte b, byte d) { // call with frequency and delay parameters tone(buzzer, b * 1000); delay(d * 100); noTone(buzzer);}void sTX(byte reportTX) { // sending serial reports switch (reportTX) { case 0:for (byte i =0; i <9; i++) { sUART.print(funct_str[10]); } sUART.println(funct_str[10]);壊す; case 1:sUART.print(funct_str[8]); // Tempr. sUART.print(tempr); //sUART.print(char(176)); sUART.println("F");壊す; case 2:sUART.print(funct_str[7]); // TTemp sUART.print(tTarget); //sUART.print(char(176)); sUART.println("F");壊す; case 3:sUART.print(funct_str[3]); // Window Alert sUART.print(funct_str[9]); sUART.print(tempr); //sUART.print(char(176)); sUART.println("F");壊す; case 4:sUART.println(funct_str[4]); // Error report break; case 5:sUART.print(funct_str[0]); // Working state of devices sUART.println(heaterState);壊す; case 6:sUART.print(funct_str[1]); sUART.println(airingState);壊す; case 7:sUART.print(funct_str[2]); sUART.println(lightingState);壊す; case 8:// Overview report sTX(0); relayHandlerH(4); relayHandlerA(4); relayHandlerL(4); sTX(2); if (measError) { sTX(4); } break; }} 

回路図

For jumper wire test... You have to solder it

製造プロセス

  1. QR、RFID、温度検証によるアクセス制御
  2. Arduino、1Sheeld、Androidを使用したユニバーサルリモコン
  3. Arduinoでコインアクセプターを制御する
  4. Arduinoを使用した自動植物散水システム
  5. LEDを制御するBluetoothを搭載したArduino!
  6. スマートシューズ(自動レーシングおよび発電)
  7. Arduino Nano:ジョイスティックで2つのステッピングモーターを制御
  8. ArduinoとMPU6050によるサーボモーターの制御
  9. OKGoogleのBluetooth音声制御アプライアンス
  10. ArduinoUnoとBluetoothによる車の制御
  11. スマートディスプレイを備えたスマートバッテリー充電器マルチプレクサ