Raspberry Pi 2 & Windows 10 IoTで実現するスマートホームオートメーション
部品と用品
| Arduino UNO | ×1 | 自動化したい部屋ごとに個別にArduino UNOを用意 |
| Raspberry Pi 2 Model B | ×1 | |
| ジャンパーワイヤー(汎用) | ×1 | |
| ブレッドボード(汎用) | ×1 | |
| LDR(光依存抵抗) | ×1 | 光の強さに応じて異なる電圧値を出力 |
| PIR人感センサー(汎用) | ×1 | 受動赤外線で人の存在を検知 |
| リレー(汎用) | ×1 | 任意のリレーモジュールを使用可能。リレー数=制御したいデバイス数 |
| Siemens コンタクタ (3TF32 00-0AP0) | ×1 | 最大AC3: 16A 415VACのウォーターポンプ制御用。購入前にポンプの定格と国の規格を確認。コイル定格は250VAC(3TF32 00-0AP0固有) |
| ミニチュアサーキットブレーカー (1P C16A) | ×1 | コンタクタの前に接続し、ウォーターポンプを電気的故障と過負荷から保護。コンタクタが16Aなので16A MCBを使用。状況に応じて変更可能 |
アプリとオンラインサービス
- Arduino IDE - Arduinoファームウェアの記述用。記事内で説明
- Microsoft Visual Studio 2015 - Community Edition推奨(5ユーザーまで無料)。ライセンス版があれば上位版も可
- Microsoft Windows 10 IoT Core - メインOSとして、Arduino経由でデバイスを制御し管理コンソールを提供
このプロジェクトについて
現代ではテクノロジーが人間の生活を向上させられます。テクノロジーは10年ごとに進化しています。オートメーションはかつてSFでしたが、今では現実です。最新テクノロジーと住宅を組み合わせることで、素晴らしいホームを構築できます。Raspberry PiとWindows 10を使えば、家庭用デバイスを自動的に操作できるホームオートメーションシステムを構築できます。
始める前に
プロジェクトを始める前に、まず基本を理解しましょう。以下の画像(全体構成)をご覧ください:

部屋の構成
部屋のシナリオを考えると、Arduino UNOがデバイスを制御しセンサーデータを読み取ります。定期的にRaspberry PiがArduino UNOから収集されたセンサーデータを要求します。「部屋のアーキテクチャ」図は、Arduino UNOがデバイスとセンサーとどう接続するかを示しています。各部屋には複数の制御可能デバイス(照明、扇風機、壁コンセントなど)、1つのPassiveIR(室内の人検知)、1つの温度センサー(LM35で室温取得)、1つのLDR(窓際の光強度検知)があります。

デバイスアドレスマッピング
最も重要なのはデバイスをどう識別するかです。シンプルです。部屋番号とデバイス番号を組み合わせてデバイスアドレスを作ります。
例:

ここまでで全体構成がわかりました。要約すると、Raspberry Piがプライマリコントローラーとして機能し、各部屋に独自のArduino UNOがあり、これがRaspberry Piのスレーブとして動作します。Raspberry PiとArduino UNO間の通信はI2Cで行います。
回路図
最初の部屋から実装を始めましょう。回路図を参照して正しく部品を接続してください。
I2Cバスストライプ: 複数のArduinoを接続する場合、以下のようにI2Cバスストライプを使用できます。



デバイスをリレーボードに配線する方法

ハードウェア側は完了です。次はソフトウェア構築です。
ソフトウェア
このプロジェクトはRaspberry Pi 2とArduino UNOで構成されます。Raspberry Pi 2のソフトウェアはVisual Studio 2015で開発されました。読者がVisual Studio 2015でのRaspberry Pi 2プロジェクト作成と、Arduinoフレームワーク、Visual C#、Windows Universal XAMLの中級知識があることを前提としています。
ソフトウェアを以下の構成で理解しましょう:
- プロトコル(Raspberry Pi 2とArduinoの通信方法)
- クラス構造(Raspberry Pi 2が複雑なデバイスと部屋をどう管理するか)
- ユーザーインターフェース(ワイヤーフレーム)
プロトコル(Raspberry Pi 2とArduinoのI2C通信)
まず、Raspberry PiとArduinoの通信方法を決めます。信頼性の高いプロトコルには、明確な目的や目標が必要です。このプロジェクトでは:
- センサー読み取り
- デバイス状態の読み取り
- デバイス状態の設定
プロトコルを定義します。プロトコルはバス上の通信ルールを定義し、バイト列に過ぎません。送信バイトは固定3バイト、受信バイト配列は14バイトです。
このプロジェクトで定義したプロトコルを理解するために以下の回路図を参照してください('X'はランダム値または'0'、通信時は無視):





'I2C_Helper'クラスには、PRi2のユニバーサルアプリプロジェクトでのプロトコル実装が含まれます。このクラスはUniversal Windows Projectで利用可能です。開くには:ソリューションエクスプローラー → ライブラリ → Communicationフォルダ。Arduino側では、I2Cライブラリは理解しやすいです。
これで、センサー、デバイスのステータスと値を取得し、デバイス状態を設定できる適切な通信スキームが定義できました。
クラス構造(Raspberry Pi 2がオブジェクトを維持する方法)
最初に議論した通り、このプロジェクトは家全体を考慮しています。家は複数の部屋で構成され、部屋は複数のデバイスで構成されます。このような構成のOOP構造は以下の通り:


主要クラス「Home」は、ジェネリックリスト(List<Room>)として複数の部屋オブジェクトで構成されます。Homeクラスは、後で使用するためにPi上でホームオブジェクトを読み込み・保存する静的メソッドを提供します。
Roomは、デバイスのジェネリックリスト(List<Device>)と、全センサーを一つにカプセル化したセンサー構造で構成されます。
Deviceは詳細と、プロトコルモード2を使用したオン/オフ機能で構成されます。AmbientLight、PassiveIR、Temperatureクラスは部屋の環境データへのアクセスを提供します。Roomオブジェクトはセンサーデータを維持し、プロトコルモード0を使用して定期的に更新します。
ユーザーインターフェース
あらゆるアプリケーションはユーザーフレンドリーでなければなりません。ユーザーフレンドリーなアプリを作るには、ワイヤーフレームから始めます。自分がこのアプリを使うと想定し、主要な目的とそれらをエンドユーザーにとって最も使いやすいよう統合する方法を見つけます。
このアプリケーションの主要目的は:
- 部屋管理
- デバイス管理
- GSM通信、インターネット通信などの外部サービス
これを以下に分割しました:
- ホームページ:基本的なデバイス状態、日時、ロック機能
- お気に入りデバイス:お気に入りデバイスへの直接アクセス
- ルームページ:設定済み部屋とそのデバイスへのアクセス
- 共通水デバイス:ウォーターポンプと給湯器
- 設定/構成:部屋とデバイスの管理
ワイヤーフレーム





ワイヤーフレームに基づきUIを開発しました。完全なソースコードはダウンロード可能です。記事末尾にリンクがあります。














UIはすでに開発済みです。ニーズに合わせて修正してください。質問があれば自由にコメントしてください。
設定方法
できるだけ簡単にしました。少しの設定で、このRaspberry Pi 2で直接デバイスを操作できます。ステップバイステップの設定手順:








ウォーターポンプと給湯器をこのアプリで制御するには?
ウォーターポンプと給湯器もデバイス追加と同じように接続できます。しかし、リレーボードに直接接続して電源を入れることはできません。リレーボードが破損し、危険です。
ウォーターポンプや給湯器を操作するには、コンタクタを介して接続し、コンタクタのコイルをリレーボードに接続します。これでデバイスを操作すると、リレーがコンタクタのコイルを駆動し、ポンプや給湯器が開始/停止します。コンタクタ購入前に、コイル定格とコンタクタ定格を必ず確認してください。コンタクタには多くの種類があります。ウォーターポンプの定格と照合し、少し高めの定格のコンタクタを購入することを推奨します。
このソリューションをRaspberry Pi 2にデプロイするには?
デプロイプロセスについてはこのリンクを参照してください。
このアプリをスタートアップアプリとして登録するには?
多くのホビイストは、Raspberry Pi 2起動直後にアプリケーションを開始させたいと考えています。方法については私の記事「Windows 10 IoT Core: Setting Startup App」を参照してください。
既知の問題
Arduino起動時の問題
Arduino起動時にD13ピンが点滅します。リレー制御にD13を使用していると、Arduino起動/再起動時にD13が一度点滅し、接続されたデバイスも点滅してしまいます。
解決策: 2つの選択肢があります。1つ目は単純にリレーをD13に接続しないこと。2つ目は少し複雑ですが、起動時にD13を使用しないArduinoのOptiBootファームウェアを書き換え、それをArduinoに書き込むことです。
時計の問題
Raspberry Pi 2にはオンボードのリアルタイムクロックチップがありません。したがって、停電や再起動後に時刻を維持できません。外部RTCを接続してプログラミングし、日時を維持する必要があります。
解決策: NTPが使用可能ですがインターネット接続が必要です。あるいはArduinoがRTCを扱い、Raspberry Piが起動時に日時を要求する方法もあります。外部RTCをRPi 2に直接接続するのも良い方法です。

デバッグの問題
C#でのユニバーサルアプリ開発中に多くの問題に直面しました。ユニバーサルアプリはWinRTのスーパーセットであり、多くの非同期操作が必要です。非同期操作でエラーが発生すると、解決が困難です。例外やエラーが発生すると、多くの場合以下の画面になります:

エラー行を指さない、プログラマーフレンドリーでないメッセージ、何もなし。ブレークポイントを大量に置いて原因を特定する必要がありました。デバッグ中、ユニバーサルアプリが突然前触れもなくシャットダウンし、ウォッチウィンドウが無意味になることも。この挙動の原因はこのリンクで説明されています。
解決策: エラーが発生しそうな行の前にブレークポイントを置く。
要するに、現時点(この記事公開時)ではユニバーサルアプリは優れていますが、従来のWindowsアプリケーションのようなデバッグ機能が不足しています。
将来展望
機能、新しいアイデア、既存の制約克服に限界はありません。しかし、全てを一度に追加するのは現実的ではありません。このリリースでは、Raspberry Pi 2とWindows IoTの真の力を理解していただくことを目的としています。Windows Universal XAMLはWindows 10 IoTとRaspberry Pi 2向けの優れたGUIフレームワークで、Raspberry Pi 2にはオンボードの優れたグラフィックプロセッサーがあります。これらを組み合わせることで、特別な見た目のGUIソリューションが作れます。さらに、Raspberry Pi 2には900MHzクアッドコアCPUがあり、マルチスレッド(UWPではTask)ソリューションにかなり適しています。これは、組み込みとソフトウェアシステムの基礎(I2Cバス通信、家電操作、カスタムプロトコル設計、実世界アプリケーションのOOP設計、ワイヤーフレーム)を学びたい人にとっての基礎から中級レベルのプロジェクトです。
将来的には、I2Cバスの代わりに無線周波数や赤外線でリモートデバイスと通信する機能、Azureを使ったWeb管理ポータルのモバイル統合、本格的なオートメーション(イベントベース操作、RTCチップによる時間ベース操作)を追加できます。例えば、午後7時に裏庭のライトを点け、午後10時に消す;環境光強度が特定値を下回ったら庭のライトを点ける、などイベントベースの好例です。新しいWindows 10 IoT CoreプラットフォームとRaspberry Pi 2には制限がありません。
Good Luck & Be Safe.
質問やヘルプがあれば自由に聞いてください。
コード
Arduinoスケッチ C/C++
/* Arduino Sketch v0.4 This sketch is written for "Home Automation using Raspberry Pi 2 and Window 10 IoT" Refer this link: https://www.hackster.io/AnuragVasanwala/home-automation This sketch is tested on Atmega328p only. This sketch prepares an Arduino device as slave device on I2C bus operated by Raspberry Pi 2 running Windows 10 IoT Core. Objectives: + Periodically collect sensor data (Function: loop) + OnRecevive, collect 3-bytes mode instruction and performa operation based upon it. (Function: ReceiveData) + OnRequest, send 14-bytes response array based on selected mode by OnReceive. (Function: SendData) This sketch is provided as it is without any WARRANTY. You can use it for personal as well as commercial use. I am not liable for any loss of data or injuries caused by this sketch. */ #include <Wire.h> #define _DEBUG_ /* Arduino's I2C Slave Address */ #define SLAVE_ADDRESS 0x40 /* PIN DECLARATION */ int Pin_AmbientLight_LDR = A0; int Pin_PassiveIR = 2; int Pin_Temperature = A1; /* Global Variable */ volatile short Value_AmbientLight_LDR, Value_Temperature; volatile bool Value_PassiveIR; /* Protocol Variable */ byte Mode, Pin, Value; byte Response[14]; void setup() { // Initialize pins pinMode(Pin_AmbientLight_LDR, INPUT); pinMode(Pin_PassiveIR, INPUT); pinMode(Pin_Temperature, INPUT); pinMode(0, OUTPUT); pinMode(1, OUTPUT); pinMode(3, OUTPUT); pinMode(4, OUTPUT); pinMode(5, OUTPUT); pinMode(6, OUTPUT); pinMode(7, OUTPUT); pinMode(8, OUTPUT); pinMode(9, OUTPUT); pinMode(10, OUTPUT); pinMode(11, OUTPUT); pinMode(12, OUTPUT); pinMode(13, OUTPUT); pinMode(A2, OUTPUT); pinMode(A3, OUTPUT); #ifdef _DEBUG_ Serial.begin(9600); #endif // Initialize I2C Slave on address 'SLAVE_ADDRESS' Wire.begin(SLAVE_ADDRESS); Wire.onRequest(SendData); Wire.onReceive(ReceiveData); } void loop() { // Read LDR // Arduino supports 10-bit Analog Read. // Thus we need to convert it into 8-bit. Value_AmbientLight_LDR = analogRead(Pin_AmbientLight_LDR); Value_AmbientLight_LDR = map(Value_AmbientLight_LDR, 0, 1023, 0, 255); // Read PassiveIR value Value_PassiveIR = (digitalRead(Pin_PassiveIR) == HIGH) ? true : false; // Read Temperature Sensor and Convert Voltage into Celsius Value_Temperature = (short)((float)(analogRead(Pin_Temperature) * 0.48828125)); // Wait for 100 ms delay(100); } // Callback for I2C Received Data void ReceiveData(int byteCount) { // Read first byte which is Protocol Mode Mode = Wire.read(); // Read second byte which is Pin. Only Valid for Mode 2 Pin = Wire.read(); // Read third byte which is Pin-Value. Only Valid for Mode 2 Value = Wire.read(); // Signal specified pin if Mode 2 is received if (Mode == 2) { digitalWrite(Pin, Value); } #ifdef _DEBUG_ Serial.print(Mode); Serial.print(" "); Serial.print(Pin); Serial.print(" "); Serial.println(Value); #endif } void SendData() { switch (Mode) { case 0: // Mode: Read Sensor Response[0] = (byte)Value_AmbientLight_LDR; // Value_PassiveIR is boolean so that we need to convert it into byte Response[1] = (byte)((Value_PassiveIR == true) ? 1 : 0); // Response[2] byte is Sign byte for Temperature // 0 - -ve Temperature // 1 - +ve Temperature Response[2] = (byte)((Value_Temperature < 0) ? 0 : 1); Serial.println(Value_Temperature); // -ve Temperature can't be sent in byte. Convert it into +ve equivalent Response[3] = (byte)((Value_Temperature < 0) ? (Value_Temperature*(-1)) : Value_Temperature); break; case 1: // Mode: Read Devices State Response[0] = (digitalRead(0) == HIGH) ? 1 : 0; Response[1] = (digitalRead(1) == HIGH) ? 1 : 0; Response[2] = (digitalRead(3) == HIGH) ? 1 : 0; Response[3] = (digitalRead(4) == HIGH) ? 1 : 0; Response[4] = (digitalRead(5) == HIGH) ? 1 : 0; Response[5] = (digitalRead(6) == HIGH) ? 1 : 0; Response[6] = (digitalRead(7) == HIGH) ? 1 : 0; Response[7] = (digitalRead(8) == HIGH) ? 1 : 0; Response[8] = (digitalRead(9) == HIGH) ? 1 : 0; Response[9] = (digitalRead(10) == HIGH) ? 1 : 0; Response[10] = (digitalRead(11) == HIGH) ? 1 : 0; Response[11] = (digitalRead(12) == HIGH) ? 1 : 0; Response[12] = (digitalRead(A2) == HIGH) ? 1 : 0; Response[13] = (digitalRead(A3) == HIGH) ? 1 : 0; break; case 2: // Mode: Set Device State Response[0] = (digitalRead(Pin) == HIGH) ? 1 : 0; break; default: break; } // Wire back response Wire.write(Response, 14); }
Raspberry Pi 2 (Windows Headed App) ソフトウェア
https://github.com/AnuragVasanwala/Home-Automation--RPi2-WinIoT-
回路図
個別のArduinoをユニークなI2Cスレーブアドレスでバスに接続することで、複数の部屋を追加できます。
Home%20Automation%20Schematic%20-%20Anurag%20S%20Vasanwala.fzz
製造プロセス
- Raspberry PiとPythonでリモート温度センサーを構築 – ステップバイステップガイド
- SensorflareとRaspberry Piで433MHzスマートホームコントローラーを構築
- Raspberry PiとTwilioで実現するトイレ占有センサー:音声通話とSMSで通知
- Raspberry Piダッシュボードで家庭の温度を監視する
- Raspberry Piで構築するホームオートメーションシステム:リモート制御対応
- Raspberry Pi 2からAzure Event HubsへAdafruit 10DOF IMUデータを送信(Windows 10 IoT Core)
- Windows 10 IoT CoreとSHT15センサーで高精度な温湿度モニタリング
- Raspberry Pi 3 Model B+へのWindows 10 IoT Coreインストール:ステップバイステップガイド
- Microsoft KinectをRaspberry Piと統合しSonbiロボットでリアルタイム人物検出
- 自動化とIoTがサプライチェーン管理の未来を形作る
- IoTとホームオートメーション:明日のスマートライフを形作る