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

ArduFarmBot-パート2:リモートステーションとIoTの実装

コンポーネントと消耗品

>
Arduino Nano R3
× 1
Espressif ESP8266 ESP-01
× 1
DHT22温度センサー
× 1
ky18
× 1
比重計
× 1
リレー(汎用)
× 2
lcd 4X20
× 1
SparkFunプッシュボタンスイッチ12mm
× 3
LED(汎用)
× 3

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

>
ThingSpeak API

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

<図> <図> <図>

このチュートリアルは、ArduFarmBotの続きです:ArduinoとIoTを使用したトマトホームファームの制御

最初の部分では、ローカルコントロールステーションを作成し、トマト農園から温度、相対湿度、光度、土壌湿度などの情報を取得します。これらのデータに基づいて、ArduFarmBotは、プランテーションが熱と水を受け取る適切な量(および時期)を自動的に決定しました。パート1で開発されたローカルステーションでは、ウォーターポンプと電球を制御するためにオペレーターが手動で介入することもできました。このパート2では、この「手動介入」がインターネットを介してリモートでも可能である場合に、IoTアプローチを実装します。ブロック図は、これをどのように行うかを示しています。

キャプチャされたデータは「クラウドストレージサービス」(この場合はThinkspeak.com)に送信されることに注意してください。また、専用のウェブサイトである「リモートコントロールページ」は、これらのデータをほぼリアルタイムで監視および表示します。このウェブページでは、ポンプとランプのリモートアクティベーションも許可されます。

ステップ1:部品表

  • Arduino Nano-($ 7.50)
  • 温度および湿度センサーDHT22またはDHT11-($ 3.66)
  • 輝度センサー-AD-018フォトレジスタモジュール。または同等のもの-($ 0.71)
  • 2X土壌水分センサー-($ 1.99)(オプション、DIY可能)
  • LCD I2C 20X4($ 13.99)
  • LED(1X)($ 0.20)
  • Esp8266シリアルWifiワイヤレストランシーバモジュールEsp-01-($ 5.96)
  • アクティブブザー-Ky-12または同等品($ 0.60)
  • 2 X 5vリレーモジュール($ 11.60)
  • ジャンパー線(S1.00)
  • 10KOhms抵抗器-($ 0.03)
  • 2.2Kオーム抵抗-($ 0.03)
  • 1.0Kオーム抵抗-($ 0.03)
  • 220オーム抵抗-($ 0.03)
  • Arduino Nano Shield( "Funduino")-($ 7.28)
  • メンブレンキーボード(4キー)-($ 6.65)
  • プラスチックボックス

ステップ2:ハードウェアの完成

<図> <図> <図> <図> <図> <図> <図>

パート1で開発されたローカルステーションから始めて、必要な追加のHWはESP8266だけです。上のブロック図は、すべてのArduinoと主要コンポーネントのPIN接続を示しています。あなたがしなければならない唯一の注意は、電圧レベルに関連しています。 ESP8266は3.3Vで動作するため、RxピンをNano Txピン(D3)に直接接続しないでください。電圧レベルを使用する必要があります。この例では、電圧レベルコンバータとして使用する分圧器を構築します。上記の図は、ESP8266を接続する方法をより詳細に示しています。 ESP8266について詳しく知りたい場合は、私のチュートリアルをご覧ください:

  • ESP8266パート3-ArduinoLEDをリモートでトリガーする
  • ESP8266パート1-Arduino用のシリアルWIFIモジュール
  • ESP8266パート2-ArduinoWebサーバー

ライブラリSoftSerialを使用して、Nanoピン2(Tx)およびピン3(Rx)に接続されたESP8266を使用していることに注意してください。これらのデジタルピンを「解放」する場合は、Nanoシリアルピン0と1を交互に使用できます。コードをNanoにアップロードするときは、これらを切断する必要があることに注意してください。

注:ブザーを接続する場合は、ピンD17(ピンA3と同じ)で接続する必要があります。通信エラーが発生したときに音を出すのは良いことです。私はテスト段階でそれを使用し、最終プロジェクトでは除外しました(ハードウェアですが、コードはそのために準備されています)。それを持っているかどうかはあなた次第です。

以下のコードを使用して、ESP8266のテストやセットアップを行うことができます:

FC9DBPKIT682FY7.ino

ステップ3:ESP8266接続

<図>

ArduFarmBotをインターネットに接続するには、IoTプロジェクト用のシンプルで安価でプログラミングが簡単なモジュールであるESP8266を使用します。モジュールがインストールされたら、最初に行うことは、CH-PDピンに「リセット」を適用することです。

  / ******************************************* *********通信を受け入れるために機能をリセットします************************************ **************** / void reset8266(void){pinMode(CH_PD、OUTPUT); digitalWrite(CH_PD、LOW); delay(300); digitalWrite(CH_PD、HIGH); Serial.print( "8266リセットOK"); lcd.clear(); lcd.println( "8266 reset OK");}  

リセット後、資格情報を使用してローカルネットワークに接続し(コードで、USERNAMEとPASSWORDを変更)、モジュールを「STA:ステーションモード」(CWMODE =1)として開始します。

  / ******************************************* *********接続WiFi *************************************** ************* / void connectWiFi(void){sendData( "AT + RST \ r \ n"、2000、DEBUG); // sendData( "AT + CWJAP =\" USERNAME \ "、\" PASSWORD \ "\ r \ n"、2000、DEBUG);をリセットします//ネットワーク遅延を接続します(3000); sendData( "AT + CWMODE =1 \ r \ n"、1000、DEBUG); sendData( "AT + CIFSR \ r \ n"、1000、DEBUG); // IPアドレスを表示lcd.clear(); lcd.print( "8266接続済み"); Serial.println( "8266 Connected");}  

ESP8266にデータを送信するには、関数 sendData() 使用された:

  / ******************************************* ********* ATコマンドをモジュールに送信します************************************ **************** / String sendData(String command、const int timeout、boolean debug){String response =""; esp8266.print(コマンド); long int time =millis(); while((time + timeout)> millis()){while(esp8266.available()){// espにはデータがあるため、出力をシリアルウィンドウに表示しますchar c =esp8266.read(); //次の文字を読み取ります。応答+ =c; }} if(debug){Serial.print(response); } return response;}  

上記の関数は、コードの「セットアップフェーズ」中に呼び出されます。すべてが正しく行われた場合は、シリアルモニターに上記と同様のメッセージが表示されます。

ステップ4:クラウドストレージデータ:ThinkSpeak.com

<図>

ArduFarmBotによってキャプチャされたすべてのデータは、「ThinkSpeak.com」の無料サービスを使用してクラウドにアップロードされます。

「Loop()」関数で( readSensors()でデータをキャプチャした後 )、キャプチャされたデータをアップロードするために特定の関数を呼び出します。 updateDataThingSpeak();

  / ******************************************* ********* thingspeak.comにデータを送信します************************************ ***************** / void updateDataThingSpeak(void){startThingSpeakCmd(); cmd =msg; cmd + ="&field1 ="; // DHT温度のフィールド1cmd + =tempDHT; cmd + ="&field2 ="; // DHT湿度のフィールド2cmd + =humDHT; cmd + ="&field3 ="; // LDR光度のフィールド3cmd + =ルーメン; cmd + ="&field4 ="; //土壌水分データのフィールド4cmd + =SoilMoist; cmd + ="&field5 ="; // PUMPステータスのフィールド5cmd + =pumpStatus; cmd + ="&field6 ="; // LAMPステータスのフィールド6cmd + =lampStatus; cmd + ="\ r \ n"; sendThingSpeakCmd();}  

これらのデータを送信するために最初に行うことは、ThingSpeakとの通信を開始することです。これは、機能を使用して行います: startThingSpeakCmd();

  / ******************************************* ********* ThingSpeak.comとの通信を開始します*********************************** ***************** / void startThingSpeakCmd(void){cmd ="AT + CIPSTART =\" TCP \ "、\" "; cmd + =IP; cmd + =" \ "、80"; esp8266.println(cmd); delay(2000); if(esp8266.find( "Error")){Serial.println( "ESP8266 START ERROR");戻る; } Serial.println( "Thinkspeak Comm Started"); cmd ="";}  

チャネルがThingSpeakで開かれ、「cmd」文字列がデータでアセンブルされたら、次の関数を使用して、ThingSpeakの対応するチャネルにすべてをアップロードします。 sendThingSpeakCmd();

  / ******************************************* *********チャネルThingSpeak.comを更新します************************************ **************** / String sendThingSpeakCmd(void){esp8266.print( "AT + CIPSEND ="); esp8266.println(cmd.length()); if(esp8266.find( ">")){esp8266.print(cmd); Serial.println( ""); Serial.println( ""); Serial.println(cmd); delay(500);文字列messageBody =""; while(esp8266.available()){文字列行=esp8266.readStringUntil( '\ n'); if(line.length()==1){//実際のコンテンツは空の行(長さ1)の後に始まりますmessageBody =esp8266.readStringUntil( '\ n'); Serial.print( "受信したメッセージ:"); Serial.println(messageBody); }} return messageBody; } else {esp8266.println( "AT + CIPCLOSE"); Serial.println( "ESP8266 CIPSEND ERROR:RESENDING"); //再送... error =1; 「エラー」を返します。 }}  

上記の関数は、MichalisVasilakisによって開発された非常に詳細なチュートリアルに基づいています。詳細については、彼のチュートリアル:Arduino IOT:温度と湿度(ESP8266 WiFiを使用)を参照してください。

写真はThingSpeak.comのArduFarmBotチャンネルを示しています。

ステップ5:ウェブからアクチュエータを操作する

<図> <図>

現在、収集したすべてのデータをアップロードしてクラウドに保存しています。これはリモートモニタリングに非常に役立ち、便利ですが、これらのデータに基づいて、ローカルの自動プログラムとは関係なく、ポンプまたはランプもオンにしたい場合はどうなりますか?そのためには、クラウドからデータを「ダウンロード」し、それらのコマンドに基づいて動作するようにコントローラーに命令する必要もあります。

ThinkSpeakチャネルに特定のフィールドを作成して、アクチュエータに命令します。

フィールド7:

  • データ=1 ==>ポンプをオンにする必要があります
  • データ=0 ==>ポンプをオフにする必要があります

フィールド8:

  • データ=1 ==> LAMPをオンにする必要があります
  • データ=0 ==> LAMPをオフにする必要があります

OKですが、ThingSpeakでこれらのフィールドを直接設定するにはどうすればよいですか?たとえば、ThinksPeakで直接「プラグイン」を作成するか、外部のWebサイトを使用して作成することができます(これが私たちの選択になります)。とにかく、どちらの場合も、次のようなコマンドを使用する必要があります:

  api.thingspeak.com/update?key=YOUR_WRITE_KEY&field7=1  

上記のコマンドを使用すると、たとえば(そして、チャネルの書き込みキーを使用して)、フィールド7に「1」と書き込みます。これは、PUMPをオンにする必要があることを意味します。あなたはそれを簡単にテストすることができます、あなたのブラウザで上記のコマンドラインを書くと、あなたのチャンネルの対応するフィールドが変更されます。見返りとして、ブラウザの左上隅に、チャネルのシーケンシャルデータエントリに対応する単一の番号が付いた白いページが表示されます。

作業の50%が完了したので、ローカルのArduFarmBotステーションでこの「コマンド」(フィールドのデータ)を読む必要があります。

これを行うためのコマンドを以下に示します。特定のフィールドに書き込まれた最後のデータを取得します(この場合は「コマンド」になります。

  api.thingspeak.com/channels/CHANNEL_ID/fields/7/last  

以前と同じように、Webブラウザを使用してコマンドラインをテストできます。この場合、ブラウザはその特定のフィールドのデータを表示します。上の写真を参照してください。

「地球」に戻り、この「最後のフィールド」を読み取る関数を書いてみましょう:

  / ******************************************* ********* thingspeak.comのfield7からデータを読み取ります********************************* ******************* / int readLastDataField7(){startThingSpeakCmd(); // "GET / channels / CHANNEL_ID / fields / 7 / last"; cmd =msgReadLastDataField7; cmd + ="\ r \ n";文字列messageDown =sendThingSpeakCmd(); Serial.print( "コマンドを受信しました:"); Serial.println(messageDown [7]); intコマンド=messageDown [7] -48;戻りコマンド;}  

上記の関数は、フィールド7( "1"または "0")のデータを返します。フィールド8についても同様の関数を作成する必要があります。

両方のフィールドの内容を取得したら、「手動コマンド関数」で行ったのと同じように、アクチュエータにコマンドを送信する関数でそれらを使用する必要があります。

  / ******************************************* ********* thingSpeak.comからコマンドを受信します*********************************** ***************** / void receiveCommands(){field7Data =readLastDataField7(); if(field7Data ==1){digitalWrite(PUMP_PIN、HIGH); pumpStatus =1; showDataLCD(); } if(field7Data ==0){digitalWrite(PUMP_PIN、LOW); pumpStatus =0; showDataLCD(); }遅延(500); field8Data =readLastDataField8(); if(field8Data ==1){digitalWrite(LAMP_PIN、HIGH); lampStatus =1; showDataLCD(); } if(field8Data ==0){digitalWrite(LAMP_PIN、LOW); lampStatus =0; showDataLCD(); }遅延(500); }  

したがって、これからは、ブラウザのコマンドラインを使用して、ポンプとランプをリモートでオン/オフにすることができます。上の写真は、受信したコマンドがシリアルモニターにどのように表示されるかを示しています。

もう1つの重要な考慮事項は、ローカルコマンドとリモートコマンド間の「調整」です。 readLocalCmd()関数を変更する必要があります また、Thinkspeakフィールド7と8をそれぞれポンプとランプのステータスで更新します(対応する「IFステートメント」で。このチュートリアルの最後にある完全なコードを参照してください):

  field7Data =pumpStatus; field8Data =lampStatus;  

これで、「filed7Data」と「field8Data」はWebページのコマンドと同期し、ボタンを押したときのローカルコマンドのアクションとも同期します。それでは、 aplyCmd()を更新しましょう。 機能、それはアクチュエータをオン/オフする責任があります:

  / ******************************************* *********コマンドを受信し、アクチュエータに作用します************************************ ***************** / void aplyCmd(){if(field7Data ==1)digitalWrite(PUMP_PIN、HIGH); if(field7Data ==0)digitalWrite(PUMP_PIN、LOW); if(field8Data ==1)digitalWrite(LAMP_PIN、HIGH); if(field8Data ==0)digitalWrite(LAMP_PIN、LOW);}  

テストを開始すると、ローカルまたはWeb経由で手動で実行するコマンドは、関数 autoControlPlantation()によって定義された自動アクションによって克服されることがわかります。 ;この時点で、最後の言葉を持って、誰が「ボス」になるかを検討する必要があります。ここでは、以下を定義します。

  • ループサイクルごとに、ほぼ「常に」、ボタンが押されているかどうかを確認します
  • 毎分、ThingSpeakで「プーリング」を実行し、そこから注文を受け取ったかどうかを確認する必要があります。
  • 約10分ごとに、センサーを読み取り、ThingSpeakのデータを更新し、さらに重要なことに自動アクションを実行します。これらのアクションは、手動で選択されたものとは関係なく実行され、保持されます。

あなたはそれをあなたが望む方法で変えることができます。それは、物事を制御するためにプログラム可能なプロセッサを使用することの良いところです!

したがって、2つのタイマーが使用されます。1つはリモートコマンドのプール用で、もう1つはセンサーの読み取り用です(以前に使用したものと同じです:

  long sampleTimingSeconds =75; // ==> ********センサーを読み取るためのサンプル時間を秒単位で定義********* int reverseElapsedTimeSeconds =0; long startTiming =0; longlapsedTime =0; long poolingRemoteCmdSeconds =20; // ==> ********新しいThingSpeakコマンドのプーリング時間を秒単位で定義します********* long startRemoteCmdTiming =0;長い経過したRemoteCmdTime =0;  

したがって、 loop() 関数は次のように書き直す必要があります:

  void loop(){elapsedRemoteCmdTime =millis()-startRemoteCmdTiming; //リモートコマンドをプールするためのタイマーを開始しますelapsedTime =millis()-startTiming; //測定のタイマーを開始しますreverseElapsedTimeSeconds =round(sampleTimingSeconds-経過時間/ 1000); readLocalCmd(); //ローカルボタンのステータスを読み取りますshowDataLCD(); if(elapsedRemoteCmdTime>(poolingRemoteCmdSeconds * 1000)){receiveCommands(); updateDataThingSpeak(); startRemoteCmdTiming =millis(); } if(elapsedTime>(sampleTimingSeconds * 1000)){readSensors(); autoControlPlantation(); updateDataThingSpeak(); startTiming =millis(); }}  

ステップ6:専用のWebページを実装する

<図>

この時点で、ArduFarmBotは動作可能であり、Webから制御できます。 Thinkspeakサイトでデータを監視し、ブラウザを使用してコマンドを送信することもできますが、もちろん、この「Webソリューション」は「エレガントな」ソリューションとは見なされません。完全なIoTソリューションを実装する最良の方法は、すべてのデータを表示する完全なWebページを開発することです。また、アクチュエーターをアクティブにするためのボタンもあります。

私はあなたのページを扱うのがとても簡単で簡単な無料のウェブホストであるByethostを選びます。また、このプロジェクトに応募する機会を利用しました。これは、Coursera /ミシガン大学の素晴らしいオンライン専門分野で学んだことです。ウェブサイトのデザインと作成を学ぶ(HTML5、CSS3、JavaScriptを使用してレスポンシブでアクセス可能なウェブポートフォリオを構築する) 。

このチュートリアルの中心的な目的ではないため、このようなページの開発方法については詳しく説明しませんが、ここではHTML、CSS、およびJavaScriptのソースコードを含めます。そして、誰かが私がどのように結果を得たかに興味を持ったら、プロジェクトの最後にコメントボードを使用してそれについて話し合うことができます。

このページはArduFarmBotローカルコントロールステーションと直接連携しないことを強調することが重要です。それが実際に行っているのは、以下のようにThinkSpeakチャネルと対話することです。

  • フィールド1、2、3、4のセンサーデータの読み取り
  • フィールド5および6のアクチュエータステータスの読み取り
  • フィールド7と8にデータを書き込む
  • Yahooサービスからの地域の気象データの読み取り

上記の項目4は、プロジェクトにとってそれほど重要ではありませんが、トマトのプランテーションでローカルで行われていることとは関係なく、リモートアクションを実行したい場合に備えて、常に追加のデータを利用できます。他の考慮事項は、たとえば、それらのデータを別のThingSpeakチャネルに保存し、Arduinoにダウンロードして、ローカルLCDディスプレイに気象データを表示できることです(これは、うまく機能した別のクールなプロジェクトで開発しました!ここに提案として残しておきますあなた)。

FQOK9ENIT653YX5.zip

ステップ7:脳に戻ります。センサー-アクチュエーターマトリックスアプローチ:

<図> <図> <図>

このプロジェクトの最初の部分では、センサーの読み取り値に応じてアクチュエーターがどのように動作するかについて、いくつかの予備的な考慮事項を定義しました。単純な選択しかしませんでしたが、もっと複雑な状況になるとどうなりますか?いくつかの異なる条件?私たちが開発するのは、「センサー-アクチュエーターマトリックスアプローチ」です。

マトリックスでは、センサーごとに、その状態とアクチュエーターの出力をどのように設定するかが定義されています。結果は、以下に含まれているExcelスプレッドシートで確認できます。 Excelファイルには2つのスプレッドシートがあります。フィルタとバージョンのある表では、複数のセンサー条件を選択し、この選択によってアクチュエータがどのように機能するかを確認できます。

マトリックスを定義したら、それをコードに変換する必要があります。 Sensor-Actuator Matrixの条件を「コピー」するために、18行10列の配列が作成されました。

  // + --- SOIL ---- + -LIGHT- + --- TEMP --- + --- ACTUAT ---- + // SL SM SH LL LH TL TMTHポンプランプブールSDf [18] [10] ={{1、0、0、0、1、0、0、1、1、0}、{1、0、0、0、1、0、1、0、1 、0}、{1、0、0、0、1、1、0、0、1、1}、{1、0、0、1、0、0、0、1、1、0}、{1 、0、0、1、0、0、1、0、1、0}、{1、0、0、1、0、1、0、0、0、1}、{0、1、0、0 、1、0、0、1、0、0}、{0、1、0、0、1、0、1、0、0、0}、{0、1、0、0、1、1、0 、0、0、1}、{0、1、0、1、0、0、0、1、0、0}、{0、1、0、1、0、0、1、0、0、1 }、{0、1、0、1、 0、1、0、0、0、1}、{0、0、1、0、1、0、0、1、0、0}、{0、0、1、0、1、0、1、 0、0、0}、{0、0、1、0、1、1、0、0、0、1}、{0、0、1、1、0、0、0、1、0、0} 、{0、0、1、1、0、0、1、0、0、1}、{0、0、1、1、0、1、0、0、0、1}、}; > 

マトリックスを操作するために、関数 defSensorStatus()を作成します。 。この関数は、最初の8列の条件がTRUEであるかどうかを各行でテストします。はいの場合、最後の2列の条件が実行されます。

例:

  if(1と0と0と0と1と0と0と1){pumpStatus =1; lampStatus =0} else if(1と0と0と0と1と0と1と0){pumpStatus =1; lampStatus =0}  

など。

上記の関数内で、各センサーの読み取り値のステータスを使用して別の配列が作成されます。

  boolean snsSts [8] ={0、0、0、0、0、0、0、0}; // SL、SM、SH、LL、LH、TL、TM、TH  

この変数配列は、LOGレジスタにも使用されます。

F2HWXBYITA8WIN1.xlsx

ステップ8:コードの最適化

<図> <図>

ArduFarmBotの開発プロセス中に、元の仕様にいくつかの変更を加える必要があることに気付きました。

表示:

LCDディスプレイはデフォルトでオフになっているはずであり、センサーの読み取りが必要なときはいつでも手動で「オン」にすることができます。この条件はコードに実装されており、いつでもLCDをオン/オフするには、「トグル」モードと同様に「センサー読み取り」ボタンを使用する必要があります。ディスプレイをオンまたはオフにすると、センサーの読み取り値が更新されて表示されますが、ArduFarmBotの通常の機能では使用されません。

初期設定:

ArduFarmBotをオン(またはリセット)にすると、LCDに「初期設定」と表示されます。プログラムの実行を開始するには、「センサー」ボタンを押す必要があります。表示される初期情報(上の写真を参照)は次のとおりです。

  • 低温(つまり12oC)
  • 乾燥した土壌湿度(つまり30%)
  • 湿った土壌湿度(つまり60%)
  • ダークライト(つまり40%)
  • P_ONポンプ時間がオンになっている(つまり、10秒)
  • センサーを読み取るためのスキャン時間(600秒など)
  • SW_Vertion(つまり、4.1)

ログレコード:

監査の目的で、ArduFarmBotの読み取り値と作動を使用してログを作成しました。読み取りサイクルごとに、関数: storeDataLogEEPROM() 実行されます。

  / ******************************************* ********* ArduinoEEPROMでのログデータの保存********************************** ****************** / void storeDataLogEEPROM(void){for(int i =0; i <8; i ++){logData =logData +(snsSts [i])<<1; } EEPROM.write(memoAddr、logData); memoAddr ++; logData =0; logData =logData + pumpStatus; logData =logData <<1; logData =logData + lampStatus; EEPROM.write(memoAddr、logData); EEPROM.write(0、memoAddr + 1); logData =0; if((memoAddr + 1)==1023)memoAddr =1; else memoAddr ++;}  

最後のステップでコメントしたように、Arduino EEPROMに保存されるのはコンテンツであり、配列のビット snsSts [] プラスポンプとランプのステータス。上にシリアルモニターのログが表示されます。

すべてのArduFarmBotコードは、理解しやすいように異なるファイルに分割されています。この2番目の部分に2つの新しいファイルが追加されたことに注意してください:

  • communication.ino (ThingSpeakおよびESP8266固有の機能)
  • stationCredentials.h (ThingSpeakチャネルIDとチャネルに書き込むための特定のキー)

最後になりましたが、コードが適切なサイズで終了したら、SRAMではなくフラッシュ(プログラム)メモリに定数データを格納することにしました。そのために、変数修飾子であるPROGMEMキーワードを使用します。たとえば、次を使用する代わりに:

  #define DHTPIN 5  

使用したもの:

  constPROGMEMバイトDHTPIN =5;  

キーワードPROGMENは、コンパイラに、通常の場所であるSRAMではなく、「この情報をフラッシュメモリに入れる」ように指示します。また、コードのメインファイルにライブラリavr /pgmspace.hを含める必要があります。

SRAMの使用を減らすためのもう1つの良い手順は、開発中にデバッグに使用したすべてのSerial.Print()行をコメント化(または削除)することです。たとえば、シリアルモニターでログを表示するために使用されるコードは、以下のファイルにコメント化されていることがわかります。

以下に、完全なArduFarmBotArduinoコードを見つけることができます。チャンネルIDと書き込みキーを使用してcredentials.hのダミーデータを変更することを忘れないでください。また、communication.inoで、実際のユーザー名とパスワードを使用して、インターネットでESP8266に接続します。

FTUT5VIIT67U8ME.ino FWMIPSSIT67U8MG.ino FJPGZNKIT67U8MK.ino FQH3X9VIT67U8NA.ino F15MY4YIT67U8NB.ino FVU64X1IT67U8NC.h FZ057E3IT67U8P5.h

ステップ9:MJRovaiホームファーム

以下の写真は、私の最初のトマト農園を管理しているArduFarmBotの連続写真を示しています。

<図> <図> <図> <図> <図> <図> <図> <図> <図> <図> <図>

下の写真のシーケンスは、種子のプランテーションから最高の植物を選択するまでの2番目のプランテーションの進化(約45日)と最高の6つの植物の移植を示しています。

<図> <図>

Step 10:Conclusion

<図> <図>

That's all folks! ...For now!

As always, I hope this project can help others find their way in the exciting world of electronics, IoT and Robotics!

Soon we probably will publish the third and last part of our project that I hope will be a very good recipe of a organic tomato sauce pasta.

By the way, on the above photo you can see the first sighs of life on Mauricio's plantation! And before you go, please give a look and the new ArduFarmBot, the book!, where I pack all project on a more friendly format:

ArduFarmBot, the Book!

<図>

"ArduFarmBot, the book" is also at Amazon.com! You can get it, by clicking hereThe book uses the electronic controller ArduFarmBot as a basis for teaching how to work in both HW and SW, with:

  • LCD and OLED type displays;
  • LEDs and buttons;
  • Activation of pumps and lamps via relays and
  • Sensors such as:DHT22 (temperature and relative air humidity), DS18B20 (soil temperature), YL69 (soil moisture) and LDR (luminosity).
<図>

All key stages of the project are documented in detail through explanatory texts, block diagrams, high-resolution color photos, electrical diagrams using Fritzing application, complete codes stored in GitHub and YouTube videos.

<図>

Two versions of the electronic controller ArduFarmBot are developed in detail in the book. From capture of data coming from a garden, such as air and soil temperature, relative humidity, soil moisture and luminosity, the ArduFarmBot helps to control when a crop should receive heat and water. Control will happen automatically, locally and remotely via internet. The book is divided into 3 parts. In the first part, the Arduino Nano is the starting point for development of a local version of ArduFarmBot , that can be controlled both, manually and automatically.

<図>

In the second part, the book dives into automation design, introducing remote operation through the creation of a webpage. The ESP8266-01 is used for Wi-Fi connection, sending data to an important web service in the field of IoT, the ThingSpeak.com

<図>

In the third part, a second version of ArduFarmBot is developed, introducing the NodeMCU ESP8266-12E , a powerful and versatile IoT device, which replaces both the Arduino Nano and the ESP8266-01 , used in the earlier parts of the book.

<図>

In this last part of the book, a new service platform of the IoT universe, the Blynk , is also explored.

<図>

Download the book, give it a review and please use the message board here to give us any comment, suggestion or critic!

For more projects, please visit my blog:MJRoBot.org

Saludos from the south of the world!

See you at my next project!

Thank you

マルセロ

コード

  • コードスニペット#1
  • コードスニペット#2
  • Code snippet #3
  • Code snippet #4
  • Code snippet #5
  • Code snippet #6
  • Code snippet #9
  • Code snippet #10
  • Code snippet #11
  • Code snippet #12
  • Code snippet #13
  • Code snippet #14
  • Code snippet #15
コードスニペット#1 プレーンテキスト
/**************************************************** Reset funtion to accept communication****************************************************/void reset8266(void){ pinMode(CH_PD, OUTPUT); digitalWrite(CH_PD, LOW); delay(300); digitalWrite(CH_PD, HIGH); Serial.print("8266 reset OK"); lcd.clear(); lcd.println("8266 reset OK ");}
コードスニペット#2 プレーンテキスト
/**************************************************** Connect WiFi****************************************************/void connectWiFi(void){ sendData("AT+RST\r\n", 2000, DEBUG); // reset sendData("AT+CWJAP=\"USERNAME\",\"PASSWORD\"\r\n", 2000, DEBUG); //Connect network delay(3000); sendData("AT+CWMODE=1\r\n", 1000, DEBUG); sendData("AT+CIFSR\r\n", 1000, DEBUG); // Show IP Adress lcd.clear(); lcd.print("8266 Connected"); Serial.println("8266 Connected");}
Code snippet #3Plain text
/**************************************************** Send AT commands to module****************************************************/String sendData(String command, const int timeout, boolean debug){ String response =""; esp8266.print(command); long int time =millis(); while ( (time + timeout)> millis()) { while (esp8266.available()) { // The esp has data so display its output to the serial window char c =esp8266.read(); // read the next character. response +=c; } } if (debug) { Serial.print(response); } return response;}
Code snippet #4Plain text
/**************************************************** Transmit data to thingspeak.com****************************************************/void updateDataThingSpeak(void){ startThingSpeakCmd (); cmd =msg; cmd +="&field1="; //field 1 for DHT temperature cmd +=tempDHT; cmd +="&field2="; //field 2 for DHT humidity cmd +=humDHT; cmd +="&field3="; //field 3 for LDR luminosity cmd +=lumen; cmd +="&field4="; //field 4 for Soil Moisture data cmd +=soilMoist; cmd +="&field5="; //field 5 for PUMP Status cmd +=pumpStatus; cmd +="&field6="; //field 6 for LAMP Status cmd +=lampStatus; cmd +="\r\n"; sendThingSpeakCmd();}
Code snippet #5Plain text
/**************************************************** Start communication with ThingSpeak.com****************************************************/void startThingSpeakCmd(void){ cmd ="AT+CIPSTART=\"TCP\",\""; cmd +=IP; cmd +="\",80"; esp8266.println(cmd); delay(2000); if(esp8266.find("Error")) { Serial.println("ESP8266 START ERROR");戻る; } Serial.println("Thinkspeak Comm Started"); cmd ="";}
Code snippet #6Plain text
/*************************************************** * Update channel ThingSpeak.com****************************************************/String sendThingSpeakCmd(void){ esp8266.print("AT+CIPSEND="); esp8266.println(cmd.length()); if(esp8266.find(">")){ esp8266.print(cmd); Serial.println( ""); Serial.println( ""); Serial.println(cmd); delay(500); String messageBody =""; while (esp8266.available()) { String line =esp8266.readStringUntil('\n'); if (line.length() ==1) { //actual content starts after empty line (that has length 1) messageBody =esp8266.readStringUntil('\n'); Serial.print("Message received:"); Serial.println(messageBody); } } return messageBody; } else{ esp8266.println("AT+CIPCLOSE"); Serial.println("ESP8266 CIPSEND ERROR:RESENDING"); //Resend... error=1; return "error"; }} 
Code snippet #9Plain text
/**************************************************** Read data from field7 of thingspeak.com****************************************************/int readLastDataField7(){ startThingSpeakCmd (); // "GET /channels/CHANNEL_ID/fields/7/last"; cmd =msgReadLastDataField7; cmd +="\r\n"; String messageDown =sendThingSpeakCmd(); Serial.print("Command received:"); Serial.println(messageDown[7]); int command =messageDown[7]-48; return command;}
Code snippet #10Plain text
/**************************************************** Receive Commands from thingSpeak.com****************************************************/void receiveCommands(){ field7Data =readLastDataField7(); if (field7Data ==1) { digitalWrite(PUMP_PIN, HIGH); pumpStatus =1; showDataLCD(); } if (field7Data ==0) { digitalWrite(PUMP_PIN, LOW); pumpStatus =0; showDataLCD(); } delay (500); field8Data =readLastDataField8(); if (field8Data ==1) { digitalWrite(LAMP_PIN, HIGH); lampStatus =1; showDataLCD(); } if (field8Data ==0) { digitalWrite(LAMP_PIN, LOW); lampStatus =0; showDataLCD(); } delay (500); } 
Code snippet #11Plain text
/**************************************************** Receive Commands and act on actuators****************************************************/void aplyCmd(){ if (field7Data ==1) digitalWrite(PUMP_PIN, HIGH); if (field7Data ==0) digitalWrite(PUMP_PIN, LOW); if (field8Data ==1) digitalWrite(LAMP_PIN, HIGH); if (field8Data ==0) digitalWrite(LAMP_PIN, LOW);}
Code snippet #12Plain text
long sampleTimingSeconds =75; // ==> ******** Define Sample time in seconds to read sensores *********int reverseElapsedTimeSeconds =0;long startTiming =0;long elapsedTime =0;long poolingRemoteCmdSeconds =20; // ==> ******** Define Pooling time in seconds for new ThingSpeak commands *********long startRemoteCmdTiming =0; long elapsedRemoteCmdTime =0;
Code snippet #13Plain text
void loop() { elapsedRemoteCmdTime =millis()-startRemoteCmdTiming; // Start timer for pooling remote commands elapsedTime =millis()-startTiming; // Start timer for measurements reverseElapsedTimeSeconds =round (sampleTimingSeconds - elapsedTime/1000); readLocalCmd(); //Read local button status showDataLCD(); if (elapsedRemoteCmdTime> (poolingRemoteCmdSeconds*1000)) { receiveCommands(); updateDataThingSpeak(); startRemoteCmdTiming =millis(); } if (elapsedTime> (sampleTimingSeconds*1000)) { readSensors(); autoControlPlantation(); updateDataThingSpeak(); startTiming =millis(); }} 
Code snippet #14Plain text
 // +---SOIL----+-LIGHT-+---TEMP---+---ACTUAT----+ // SL SM SH LL LH TL TM TH Pump Lampboolean SDf [18] [10] ={{ 1, 0, 0, 0, 1, 0, 0, 1, 1, 0 }, { 1, 0, 0, 0, 1, 0, 1, 0, 1, 0 }, { 1, 0, 0, 0, 1, 1, 0, 0, 1, 1 }, { 1, 0, 0, 1, 0, 0, 0, 1, 1, 0 }, { 1, 0, 0, 1, 0, 0, 1, 0, 1, 0 }, { 1, 0, 0, 1, 0, 1, 0, 0, 0, 1 }, { 0, 1, 0, 0, 1, 0, 0, 1, 0, 0 }, { 0, 1, 0, 0, 1, 0, 1, 0, 0, 0 }, { 0, 1, 0, 0, 1, 1, 0, 0, 0, 1 }, { 0, 1, 0, 1, 0, 0, 0, 1, 0, 0 }, { 0, 1, 0, 1, 0, 0, 1, 0, 0, 1 }, { 0, 1, 0, 1, 0, 1, 0, 0, 0, 1 }, { 0, 0, 1, 0, 1, 0, 0, 1, 0, 0 }, { 0, 0, 1, 0, 1, 0, 1, 0, 0, 0 }, { 0, 0, 1, 0, 1, 1, 0, 0, 0, 1 }, { 0, 0, 1, 1, 0, 0, 0, 1, 0, 0 }, { 0, 0, 1, 1, 0, 0, 1, 0, 0, 1 }, { 0, 0, 1, 1, 0, 1, 0, 0, 0, 1 }, };
Code snippet #15Plain text
/**************************************************** Storage of Log data at Arduino EEPROM****************************************************/void storeDataLogEEPROM(void){ for (int i =0; i<8; i++) { logData =logData + (snsSts[i])<<1; } EEPROM.write (memoAddr, logData); memoAddr++; logData =0; logData =logData + pumpStatus; logData =logData <<1; logData =logData + lampStatus; EEPROM.write (memoAddr, logData); EEPROM.write (0, memoAddr+1); logData =0; if ((memoAddr+1) ==1023) memoAddr=1; else memoAddr++;} 
ArduFarmBot GitHub
https://github.com/Mjrovai/ArduFarmBot

回路図

ardufarmbot_qpNcBDX6Jr.fzz

製造プロセス

  1. IoTの実装動向
  2. 6-シューター:Arduinoドリンクミキシングステーション
  3. マルチ温度センサー
  4. MotionSense
  5. 3Dプリンターの火災安全
  6. Arduino、Yaler、IFTTTを使用したIoTゲージ
  7. Arduinoの反発電磁浮上
  8. リモコングリッパーボット
  9. Arduino Powered Weather Balloon Datalogger
  10. $ 10ポータブルArduinoウェザーステーション(AWS)
  11. CoroFence-熱検出器🖖