スマートプラントIoT
コンポーネントと消耗品
> |
| × | 1 | |||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 |
アプリとオンラインサービス
> |
| |||
|
このプロジェクトについて
2019年中国-米国ヤングメーカーコンペティションに更新
はじめに
ガーデニングは、一部の人にとっては楽しい趣味かもしれませんが、他の多くの人にとっては、対処するのが非常に面倒です。この記事では、センサーデータをAzure IoT Hubに送信し、Azure関数を介してAzure SQLに保存すると同時に、プラントの水を自動およびリモートで制御するスマートIoTプラントを構築する方法に関する簡単なガイドを作成しています。
Helium IoTHubはAzureIoT Hubにシームレスに接続します。この記事では、プロセス全体がどのように機能するかを説明します。プロジェクト全体がサーバーレスであるため、プロセス全体が機能するために必要なコードは、AzureFunctionとArduinoのコードだけです。
ステップ1:コンポーネントを収集する
を使用してシンプルな製品を構築しています
- Arduino UNO
- SEEED GroveBaseシールド
- ヘリウム原子+ヘリウムArduinoブレイクアウトボードを備えたヘリウムエレメント
- ポンプ
- 温度/湿度センサー、湿気センサー、UV光センサー
- グローブOLEDディスプレイ
ステップ2:ヘリウムとセンサーを使用してArduinoをセットアップする
この記事では、アプリとしてArduinoを使用することに焦点を当てます。まず、HeliumAtomからHeliumHubにデータをプッシュします。まず、Atomをヘリウムネットワークダッシュボードに登録する必要があります。
<図>Atomをセットアップした後、アクセスポイントであるElementも登録する必要があります(セルラーバージョンの電源を入れている場合はそうします)。
<図>要素をアクティブ化すると、アクセスポイントに表示されます。
<図>次に、すべてのセンサーとヘリウム原子を接続する必要があります。すべてが完了すると、このようになり、少し面倒になりますが、後でクリーンアップできます。
<図>次のコードを実行して、プログラムが実行されていることを確認できます。
#include "Arduino.h" #include "Board.h" #include "Helium.h" #include "HeliumUtil.h" #include #include "Arduino.h" #include "Wire.h" #include #include #define CHANNEL_NAME "Azure IoT App" Helium helium(&atom_serial); Channel channel(&helium); int relay =5; void setDisplayToOriginalState() {SeeedGrayOled.init(SSD1327);} void setup(){//セットアップコードをここに配置して、1回実行します:Serial.begin(9600); pinMode(リレー、出力); delay(150); / * HP20x_devをリセットします* / TH02.begin(); delay(100); Serial.println( "TH02_devが利用可能です。\ n"); DBG_PRINTLN(F( "開始")); //ヘリウム原子との通信を開始します//ボーレートはサポートされているボードごとに異なります//Board.hで構成されますhelium.begin(HELIUM_BAUD_RATE); //アトムをヘリウムネットワークに接続しますhelium_connect(&helium); //チャネルとの通信を開始します。 //これは1回だけ実行する必要があります。 HeliumUtil関数は、チャネルが切断された場合にチャネルを再作成するための単純な再試行ロジックを//追加します。 channel_create(&channel、CHANNEL_NAME); Wire.begin();} void loop(){//騒音公害intmoisture =0; for(int i =0; i <32; i ++){湿気+ =analogRead(A0); } int uvlight =0; for(int i =0; i <32; i ++){uvlight + =analogRead(A1); } floattemper =TH02.ReadTemperature();フロート湿度=TH02.ReadHumidity(); String dataString ="Moisture =" + String(moisture)+ "&UVLight =" + String(uvlight)+ "&Temperature =" + String(temper)+ "&Humidity =" + String(humidity); char data [dataString.length()]; dataString.toCharArray(data、dataString.length()); channel_send(&channel、CHANNEL_NAME、data、strlen(data)); Serial.println(data); setDisplayToOriginalState(); SeeedGrayOled.clearDisplay(); //表示をクリアします。 SeeedGrayOled.setNormalDisplay(); //通常の表示モードを設定SeeedGrayOled.setVerticalMode(); //テキストを表示するために垂直モードに設定しますSeeedGrayOled.setTextXY(0、0); //カーソルを0行、0列目に設定しますStringmoisturestring ="Moisture:" + String(moisture); char moibuffer [moisturestring.length()];モイスチャーストリング.toCharArray(moibuffer、moisturestring.length()); SeeedGrayOled.putString(moibuffer); SeeedGrayOled.setTextXY(2、0); String uvstring ="UVLight:" + String(uvlight); char uvbuffer [uvstring.length()]; uvstring.toCharArray(uvbuffer、uvstring.length()); SeeedGrayOled.putString(uvbuffer); SeeedGrayOled.setTextXY(4、0);文字列temperaturestring =String(temper)+ "C"; char tempbuffer [temperaturestring.length()]; temperaturestring.toCharArray(tempbuffer、temperaturestring.length()); SeeedGrayOled.putString(tempbuffer); SeeedGrayOled.setTextXY(6、0);文字列humidstring ="Humid:" + String(humidity); charhumidbuffer [temperaturestring.length()];湿った文字列.toCharArray(humidbuffer、humidstring.length()); SeeedGrayOled.putString(humidbuffer); if(moisture <100){digitalWrite(relay、HIGH); delay(5000); digitalWrite(relay、LOW); } delay(60000);}
ウォーターポンプは12Vを必要としますが、通常のArduinoは最大5Vしか出力しないため、ロックを機能させるために、下の画像のように電源に2本のワイヤーをはんだ付けして電源を利用できます。 12Vとして赤い線を使用し、アースとして黒い線を使用します。
<図>リレーは、いつ水を汲み上げるかを制御する役割を果たします。
ステップ3:ヘリウムハブとAzureIoTハブをセットアップする
まず、すべてのサービスの下でIoT Hubを作成します。IoTHubをお気に入りに移動して、アクセスがはるかに簡単になるようにすることをお勧めします。無料トライアル$ 200トライアルクレジットでカバーできるため、標準ティアを使用できます。無料利用枠を使用することもできます。
<図>名前を選択したら、[サイズとスケール]に移動できます。
<図>作成後、共有アクセスポリシー-> RegistryReadWriteエントリ->接続文字列-主キーに移動する必要があります 、レジストリの読み取りとレジストリの書き込みがチェックされていることも確認してください。ただし、これらはデフォルトである必要があります
<図>接続をテストするためのプロトタイプ用の最初のデバイスを作成できます
<図>そのプライマリ接続文字列を取得したら、Heliumダッシュボードに移動してHelium接続を作成します。接続文字列を接続フィールドに貼り付けた後、他のすべてが自動的に入力されます。
<図>これを設定すると、HeliumHubですべてのMQTT文字列が自動的に生成されるようになります。これは、チャネルから簡単にアクセスできます。
<図>Azureではデバイスが固定MQTTトピックをパブリッシュおよびサブスクライブする必要があるため、これによりHelium Atomがそれを実行できるようになるだけでなく、IoTHubがメッセージをHeliumAtomにプッシュできるようになります。次の手順を実行して、Azureへの送信をテストできます。
git clone https://github.com/helium/helium-cli.gitcd helium-climake./helium -p / dev /
ヘリウムが正しく取り付けられているかどうかを確認します
./ helium -p / dev / serial0 channel create "Azure IoT App" ./ helium -p / dev / serial0 channel send 1 "Hello Azure"
これにより、AtomからAzureに直接情報が送信されます。これは、HeliumダッシュボードとAzure IoTHubの概要の両方で確認する必要があります
<図>以下のAzureIoT Hubでも、同じ結果が表示されるはずです
<図>デバイスはX509を介して認証され、Heliumプラットフォームがすべてを処理します。シンプルでクリーンなものにします。
手順5:AzureSQLデータベースをセットアップする
次に、IoTデバイスからのデータを保存できるようにする必要があります。 https://blogs.msdn.microsoft.com/sqlserverstorageengine/2018/01/23/working-with-azure-iot-data-in-azure-sql-database/に詳細に書かれた、これに関する優れたガイドがあります。この記事では、それがどのように行われるかをすばやく統合することに焦点を当てます。最初にSQLデータベースに移動して、下の画像のようなデータベースを作成します。アプリを起動するだけなので、基本階層を選択できます。無料トライアルクレジットでカバーできるはずです。これは最も安いオプションです プロトタイピングの場合、スケーリングするときに、Cosmosの最小額が25ドルであるため、将来的にAzureCosmosに移行することをお勧めします。
<図>その後、クエリエディタを使用して次のテーブルを作成できます。最初は、Smart PlantIoTの単純なデータ構造を使用して開始します
CREATE TABLE SmartPlant(id bigint IDENTITY(1,1)NOT NULL、Temperature int NOT NULL、Humidity int NOT NULL、Moisture int NOT NULL、UVLight int NOT NULL、DateCreated datetime default CURRENT_TIMESTAMP)
<図> これで、データを保存するテーブルができました。これをeventhubに接続して、データを保存できるようにする必要があります。[接続文字列]に移動し、次の手順のために接続文字列を取得します。
<図>
手順4:AzureFunctionアプリを作成する
関数に接続するために、EventHubを使用します。最初に、サーバーレス構造を可能にするAzure Functionアプリを作成する必要があります。これは、保守する必要がなくなったため、IoTアプリケーションに最適です。まず、computeの下に関数Appを作成する必要があります。
<図>これらの設定で関数を作成できます
<図>
数分ほどで、通知の下に表示されます。
<図>デプロイされた関数アプリ
関数ができたので、次にIoT Hub(イベントハブ)トリガーの下に関数を作成して、イベントハブを実行できるようにします。 [機能]-> [プラットフォーム機能]-> [アプリケーション設定]
に移動します <図>ここでは、前の手順で作成した接続文字列を追加します。作成後に保存
<図>次のステップは、イベントハブ関数を作成することです。この例では、C#を使用します。新しい接続をクリックすると、自動入力が行われます。
<図>関数を次のように変更します。これは、データをAzureSQLデータベースに直接挿入するためのものです。
using System.Configuration; using System.Data.SqlClient; using System.Threading.Tasks; public static async Task Run(string myIoTHubMessage、TraceWriter log){var map =myIoTHubMessage.Split( '&')。 Select(x => x.Split( '='))。ToDictionary(x => x [0]、x => x [1]);文字列Temperature =map ["Temperature"];文字列H文字列水分=map ["Moisture"]; String UVLight =map ["UVLight"]; var str =ConfigurationManager.ConnectionStrings ["sqldb_connection"]。ConnectionString; using(SqlConnection conn =new SqlConnection(str)){conn.Open(); var text ="INSERT INTOdbo。 SmartPlant(Temperature、using(SqlCommand cmd =new SqlCommand(text、conn)){//コマンドを実行し、影響を受けた#行をログに記録します。varrows=await cmd.ExecuteNonQueryAsync(); log.Info($ "{rows} rows更新されました ");}} log.Info($" C#IoT Hubトリガー関数がメッセージを処理しました:{myIoTHubMessage} ");}
成功すると、表示できるはずです
<図>この時点で、Azure IoTHubを介してHeliumからAzureSQLにエンドツーエンドのデータを送信できます。次に、データを取得する必要があります。データは、Azure FunctionAPIを介してHTTPトリガーを作成する必要があります。
<図>いくつかの値を変更し、ルーティングを/ dataに変更して、/ api / smartplantにアクセスできるようにし、認証レベルを匿名に、HTTPメソッドをGET専用に変更します
<図>コードについては、アドレスにアクセスしてテストできます
http://
これにより、結果がテストされ、「hellofoobar」が返されます。これが終了したら、次のコードを使用して実際のデータを返すことができます。次に、次のコードを使用してアプリ全体をテストできます。これは最も単純なクエリであり、より複雑なクエリを作成することで追加情報を収集できますが、プロトタイプの場合は、1つのレコードを取得することに焦点を当てます。
#r "System.Configuration" #r "System.Data" #r "Newtonsoft.Json" using System; using System.Net; using System.Configuration; using System.Data.SqlClient; usingSystem。 Threading.Tasks; using System.Text; using Newtonsoft.Json; public static async Task Run(HttpRequestMessage req、TraceWriter log){log.Info( "C#HTTPトリガー関数がリクエストを処理しました。"); var str =ConfigurationManager .ConnectionStrings ["sqldb_connection"]。ConnectionString; using(SqlConnection conn =new SqlConnection(str)){conn.Open(); var text ="SELECT Top 100 Temperature、Moisture、UVLight SmartPlant ret =new SmartPlant(); using( SqlCommand cmd =new SqlCommand(text、conn)){SqlDataReader reader =await cmd.ExecuteReaderAsync(); try {while(reader.Read()){ret.Temperature =(int)reader [0]; ret.Moisture =( int)reader [1]; ret.UVLight =(int)reader [2]; ret.Humidity =(int)リーダー[3]; }} finally {//読み取りが完了したら、常にCloseを呼び出します。 reader.Close(); } var json =JsonConvert.SerializeObject(ret、Formatting.Indented); return new HttpResponseMessage(HttpStatusCode.OK){Content =new StringContent(json、Encoding.UTF8、 "application / json")}; }}} public class SmartPlant {public float Temperature {get;セットする; } public float Moisture {get;セットする; } public float UVLight {get;セットする; } public float Humidity {get;セットする; }}
すべて完了すると、最新のレコードの結果が得られるはずです。
<図>
ステップ5:出力のUI
すべてがエンドツーエンドで接続されたので、プラントの全体的な状態をチェックできるシンプルなAndroidアプリケーションを構築できます。この場合、非常にシンプルなAndroidアプリを使用して、植物の周囲にある4つのセンサーを監視し、必要に応じて蠕動ポンプをトリガーして植物に水を供給します。以下のような情報を表示・更新する必要があります。データは60秒ごとに通過する必要があります(または設定したい場合)
<図>反対側では、Arduinoエンクロージャーを閉じることができるため、プラントの隣の景色がはるかに良くなります。
<図>独自のポンピングを簡単にシミュレートできます。
<図>
追加:Alexa統合
コード
- Azure関数のGETリクエスト
- IoTハブからのAzure関数データの挿入
- Azure関数のショートカット
- Arduinoコード
Azure関数のGETリクエスト C#
/ api / smartplant#r "System.Configuration" #r "System.Data" #r "Newtonsoft.Json" using System; using System.Net; using System.Configuration; usingSystem.Dataを呼び出してからの安らかな呼び出し。 SqlClient; using System.Threading.Tasks; using System.Text; using Newtonsoft.Json; public static async TaskRun(HttpRequestMessage req、TraceWriter log){log.Info( "C#HTTPトリガー関数がリクエストを処理しました。"); var str =ConfigurationManager.ConnectionStrings ["sqldb_connection"]。ConnectionString; using(SqlConnection conn =new SqlConnection(str)){conn.Open(); var text ="SELECT Top 100 Temperature、Moisture、UVLight from dbo.IoTData Order DateCreatedDESCによる "; EventData ret =new EventData(); using(SqlCommand cmd =new SqlCommand(text、conn)){SqlDataReader reader =await cmd.ExecuteReaderAsync(); try {while(reader.Read()){ret.Temperature =(int)リーダー[0]; ret.Moisture =(int)reader [1]; ret.UVLight =(int)reader [1]; }} finally {//読み取りが完了したら、常にCloseを呼び出します。 reader.Close(); } var json =JsonConvert.SerializeObject(ret、Formatting.Indented); return new HttpResponseMessage(HttpStatusCode.OK){Content =new StringContent(json、Encoding.UTF8、 "application / json")}; }}} public class SmartPlant {public float Temperature {get;セットする; } public float Moisture {get;セットする; } public float UVLight {get;セットする; }}
IoT Hub C#からのAzure関数データの挿入
Azure関数を介したデータの挿入using System.Configuration; using System.Data.SqlClient; using System.Threading.Tasks; public static async Task Run(string myIoTHubMessage、TraceWriter log){var map =myIoTHubMessage.Split( '&' ).Select(x => x.Split( '='))。ToDictionary(x => x [0]、x => x [1]);文字列タイプ=map ["Type"]; String Confidence =map ["Confidence"]; log.Info(Type); log.Info(Confidence); var str =ConfigurationManager.ConnectionStrings ["sqldb_connection"]。ConnectionString; using(SqlConnection conn =new SqlConnection(str)){conn.Open(); var text ="INSERT INTO dbo.IoTData(Type、Confidence)VALUES( '" + Type + "'、" + Confidence + ");"; using(SqlCommand cmd =new SqlCommand(text、conn)){//コマンドを実行し、影響を受けた#行をログに記録します。 var rows =await cmd.ExecuteNonQueryAsync(); log.Info($ "{rows}行が更新されました"); }} log.Info($ "C#IoT Hubトリガー関数がメッセージを処理しました:{myIoTHubMessage}");}
Azure関数のショートカット C#
AzureSQLに直接挿入#r "System.Configuration" #r "System.Data" using System; using System.Configuration; using System.Data.SqlClient; using System.Threading.Tasks; using System.Net; public static async TaskRun(HttpRequestMessage req、TraceWriter log){string Temperature =req.GetQueryNameValuePairs()。FirstOrDefault(q => string.Compare(q.Key、 "Temperature"、true)==0).Value; string Moisture =req.GetQueryNameValuePairs()。FirstOrDefault(q => string.Compare(q.Key、 "Moisture"、true)==0).Value; string UVLight =req.GetQueryNameValuePairs()。FirstOrDefault(q => string.Compare(q.Key、 "UVLight"、true)==0).Value; if(Temperature ==null || Moisture ==null || UVLight ==null){//リクエスト本文を取得return req.CreateResponse(HttpStatusCode.BadRequest、 "クエリ文字列またはリクエスト本文に名前を渡してください"); } var str =ConfigurationManager.ConnectionStrings ["sqldb_connection"]。ConnectionString; using(SqlConnection conn =new SqlConnection(str)){conn.Open(); var text ="INSERT INTO dbo.SmartPlant(Temperature、Moisture、UVLight)VALUES(" + Temperature + "、" + Moisture + "、" + UVLight + ");"; using(SqlCommand cmd =new SqlCommand(text、conn)){//コマンドを実行し、影響を受けた#行をログに記録します。 var rows =await cmd.ExecuteNonQueryAsync(); log.Info($ "{rows}行が更新されました"); }} return req.CreateResponse(HttpStatusCode.OK、 "Success");}
Arduinoコード Arduino
データをアップロードし、プラントに自動的に水をまくためのArduinoコード#include "Arduino.h" #include "Board.h" #include "Helium.h" #include "HeliumUtil.h" #include#include "Arduino.h" #include "Wire.h" #include #include #define CHANNEL_NAME "Azure IoT App" Helium helium(&atom_serial); Channel channel(&helium); int relay =5; void setDisplayToOriginalState(){SeeedGrayOled.init(SSD1327);} void setup(){//セットアップコードをここに配置して、1回実行します:Serial.begin(9600); pinMode(リレー、出力); delay(150); / * HP20x_devをリセットします* / TH02.begin(); delay(100); Serial.println( "TH02_devが利用可能です。\ n"); DBG_PRINTLN(F( "開始")); //ヘリウム原子との通信を開始します//ボーレートはサポートされているボードごとに異なります//Board.hで構成されますhelium.begin(HELIUM_BAUD_RATE); //アトムをヘリウムネットワークに接続しますhelium_connect(&helium); //チャネルとの通信を開始します。 //これは1回だけ実行する必要があります。 HeliumUtil関数は、チャネルが切断された場合にチャネルを再作成するための単純な再試行ロジックを//追加します。 channel_create(&channel、CHANNEL_NAME); Wire.begin();} void loop(){//騒音公害intmoisture =0; for(int i =0; i <32; i ++){湿気+ =analogRead(A0); } int uvlight =0; for(int i =0; i <32; i ++){uvlight + =analogRead(A1); } floattemper =TH02.ReadTemperature();フロート湿度=TH02.ReadHumidity(); String dataString ="Moisture =" + String(moisture)+ "&UVLight =" + String(uvlight)+ "&Temperature =" + String(temper)+ "&Humidity =" + String(humidity); char data [dataString.length()]; dataString.toCharArray(data、dataString.length()); channel_send(&channel、CHANNEL_NAME、data、strlen(data)); Serial.println(data); setDisplayToOriginalState(); SeeedGrayOled.clearDisplay(); //表示をクリアします。 SeeedGrayOled.setNormalDisplay(); //通常の表示モードを設定しますSeeedGrayOled.setVerticalMode(); //テキストを表示するために垂直モードに設定しますSeeedGrayOled.setTextXY(0、0); //カーソルを0行、0列目に設定しますStringmoisturestring ="Moisture:" + String(moisture); char moibuffer [moisturestring.length()];モイスチャーストリング.toCharArray(moibuffer、moisturestring.length()); SeeedGrayOled.putString(moibuffer); SeeedGrayOled.setTextXY(2、0); String uvstring ="UVLight:" + String(uvlight); char uvbuffer [uvstring.length()]; uvstring.toCharArray(uvbuffer、uvstring.length()); SeeedGrayOled.putString(uvbuffer); SeeedGrayOled.setTextXY(4、0);文字列temperaturestring =String(temper)+ "C"; char tempbuffer [temperaturestring.length()]; temperaturestring.toCharArray(tempbuffer、temperaturestring.length()); SeeedGrayOled.putString(tempbuffer); SeeedGrayOled.setTextXY(6、0);文字列humidstring ="Humid:" + String(humidity); charhumidbuffer [temperaturestring.length()];湿った文字列.toCharArray(humidbuffer、humidstring.length()); SeeedGrayOled.putString(humidbuffer); if(moisture <100){digitalWrite(relay、HIGH); delay(5000); digitalWrite(relay、LOW); } delay(60000);}
プロジェクトリポジトリ
netduinoスマートプラントのプロジェクトリポジトリhttps://github.com/Nyceane/smart-plant-iot 回路図
ヘリウムアーキテクチャは、IoTデバイスをAzure IoTHubに直接接続します 製造プロセス