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

UNO、ESP-01、ThingSpeak、MIT AppInventorでIoTを簡単に

コンポーネントと消耗品

>
Arduino UNO
× 1
Espressif ESP8266 ESP-01
× 1
DHT22温度センサー
× 1
DS18B201-Wireデジタル温度センサーを土壌で使用
× 1
LDR-光依存抵抗器
× 1
2チャンネルDC5Vリレーモジュール
× 1

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

>
Arduino IDE
ThingSpeak API
MIT App Inventor

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

私たちの目標は、基本的にローカルユニットから情報を収集してインターネットに送信することです。この情報を見ている地球上のどこのユーザーも、このローカルユニットにあるアクチュエーターにリモートコマンドを送信することによって決定を下します。任意のセンサーまたはアクチュエーターを使用できます。

<図>

IoT分野での私の仕事の大部分は、NodeMCUと、最近ではESP32を使用していました。しかし、数年前にArduinoUNOと古くて優れたESP8266-01を使用してIoTを学び始めた初期のステップを忘れないでください。

そこで、ここでその時代に戻り(もう少し経験を積んで)、ThingSpeak.com Webサービスを使用して、これらの優れたデバイスをクラウドに接続し、もう一度探索することにしました。また、MIT AppInventorを使用して開発されたAndroidアプリを使用して、物事をリモートで制御する方法についても説明します。

<図>

「私たちのIoTプロジェクトの中心」はThingSpeak.comになります。ローカルユニット(UNO / ESP-01)は、センサーとアクチュエーターのステータスからデータをキャプチャし、送信します。 それらをインターネットに送信し、特定の ThingSpeak.com に「書き込み」ます ステータスチャネル 。ローカルユニットも 受信します インターネットからのデータ、特定の ThingSpeak Actuator Channels からのデータの「読み取り」 。

Androidアプリも 読書されます ThingSpeak.comステータスチャネルからのデータ そしてそれらをユーザーに表示します。同様に、ユーザーはそのステータス情報に基づいて、アクチュエータにコマンドを送信し、書き込みを行うことができます。 それらはThingSpeakアクチュエータチャネルにあります(データの流れをよりよく理解するには、上のブロック図を参照してください)。

それで、私たちは何をしますか?次のステップに示すブロック図は、最終的なプロジェクトの概要を示しています。

ステップ1:はじめに

<図>

私たちのプロジェクトでは、一般的なセンサーを使用していくつかのデータをキャプチャし、それらをクラウドに送信します。クラウドでは、インターネットを通じて誰もがそれらを見ることができます。これらのデータを処理するために、ThingSpeak.comが提供するサービスを使用します。これは、これらのデータの収集、分析、および操作を可能にするオープンIoTプラットフォームです。

センサーによって収集されるデータ なります:

  • 気温と相対湿度
  • 土壌の温度と湿度
  • 光度

プロジェクトには2人のアクチュエータが含まれます :

  • 電動ポンプ
  • 電灯

これらのアクチュエータのステータス(「オン/オフ」)もクラウドに送信する必要があります。

そのため、プランテーションなどのセンサーからこれらのデータをキャプチャしてクラウドに送信するというアイデアがあります。これらのデータに基づいて、ユーザーはこれらのステートメントに基づいて決定を下す必要があります。

  • 土壌の湿度が低すぎる場合は、ポンプをオンにします
  • 土壌温度が低すぎる場合は、ランプをオンにします

アクチュエータをリモートでコマンドするには、Androidアプリを使用します。

ステップ2:BoM-部品表

ここにリストされている最も重要なコンポーネントのいくつかには、リンクと米ドルでの表示価格が関連付けられています。これらのリンクは情報提供のみを目的としています。

  • Arduino UNO(マイクロコントローラー)-$ 10.00
  • ESP8266-01(通信モジュール)-$ 3.50
  • DHT22(空気および相対湿度センサー)-9.00ドル
  • DS18B20(土壌で使用するための1-Wireデジタル温度センサー)-6.00ドル
  • YL-69 + LM393(土壌湿度センサー)-$ 2.00
  • LDR(Luminosity Sensor)-$ 0.20
  • 2 x LED(赤と緑)
  • フォトカプラ低レベルトリガー付き1x2チャンネルDC5Vリレーモジュール-$ 7.00
  • 5VDCポンプ-3.00ドル
  • 220Vランプ
  • 2 x 330オーム抵抗(LEDで使用)
  • 2 x 10Kオーム抵抗器(DHT22およびLDRで使用)
  • 1 x 4K7オーム抵抗(DS18B20で使用)
  • プロトボード
  • ジャンパー
  • リレー用の外部5VDC電源

ステップ3:ハードウェア

<図>

プロジェクトHWを組み立てましょう。理想は、プロジェクトをパーツごとにインストールしてテストすることです。提案として、次の手順に従うことができます:

  • すべてのセンサーをローカルにインストールしてテストします
  • ESP-01(BareMinimum)をインストールして構成します
  • ESP-01のインストールを最終構成に変更し、テストします
  • ThingsPeakステータスチャネルを構成する
  • ArduinoにThingsPeakコードをインストールし、クラウド上のセンサーのステータスを確認します
  • ステータスとメッセージを表示するAndroidアプリの最初のバージョンを開発する
  • アクチュエータ(LEDとリレー)を取り付けます
  • ThingSpeakアクチュエータチャネルを構成する
  • アクチュエータを使用してArduinoコードをインストールしてテストする
  • Androidアプリの最終バージョンを開発する

ステップ4:センサーを接続する

<図>

センサーを正しく読み取るには、IDEにいくつかのライブラリをインストールする必要があります。すべてのライブラリがインストールされているかどうかを確認してください。初期構成は次のようになります。

  // DS18B20#include  #include  #define ONE_WIRE_BUS 5 //ピンD5上のDS18B20OneWire oneWire(ONE_WIRE_BUS); DallasTemperature DS18B20(&oneWire); int soleTemp =0; // DHT#include "DHT.h" #include  int pinoDHT =11; int tipoDHT =DHT22; DHT dht(pinoDHT、tipoDHT); int airTemp =0; int airHum =0; // LDR(Light)#define ldrPIN 1int light =0; //土壌湿度#definesoilHumPIN 0int soleHum =0;  

セットアップとループで、次のように記述しましょう:

  void setup(){Serial.begin(9600); DS18B20.begin(); dht.begin();} void loop(){readSensors(); displaySensors();遅延(10000);}  

最後に、2つの特定の関数を記述しましょう。1つはセンサーを読み取るためのもので、もう1つはシリアルモニターに値を表示するためのものです。

  / *********センサー値の読み取り************* / void readSensors(void){airTemp =dht.readTemperature(); airHum =dht.readHumidity(); DS18B20.requestTemperatures(); soleTemp =DS18B20.getTempCByIndex(0); //センサー0は摂氏の土壌温度をキャプチャしますsoilHum =map(analogRead(soilHumPIN)、1023、0、0、100);ライト=map(analogRead(ldrPIN)、1023、0、0、100); // LDRDark:0 ==> light 100%} / *********センサーの値を表示************* / void displaySensors(void){Serial.print( " airTemp(oC): "); Serial.println(airTemp); Serial.print( "airHum(%):"); Serial.println(airHum); Serial.print( "soilTemp(oC):"); Serial.println(soilTemp); Serial.print( "soilHum(%):"); Serial.println(soilHum); Serial.print( "ライト(%):"); Serial.println(ライト); Serial.println( "");}  

下のシリアルモニターの写真は、センサーの値を示しています。

<図>

コードは私のGITHUBからダウンロードできます:Sens ors_Test.ino

ステップ5:ESP8266-01初期構成

<図>

ESP-01はシリアルブリッジとして使用されます。つまり、「ATコマンド」を使用してプログラムします。まず、ESP-01が正しいボーレート通信速度になっていることを確認します。私たちの場合、9,600ボーです。通常、ESP-01は工場から115,200ボーでプログラムされており、9,600ボーに変更する必要があります。

まず、上記のようにESP-01を接続する必要があります。

次に、Arduinoをコンピューターに接続し、IDEを開いて、[ファイル]> [例]> [01.Basics]> [BareMinimum]にある例をロードします。これは空のコードであり、ArduinoとESPの間で通信の競合が発生しないようにします。

Arduinoがシリアル通信(TXおよびRX)を使用しないように、ESP-01Sに接続する前にこのコードをArduinoに転送しました。これは、ESPが適切に通信できるようにするために重要です。

IDEシリアルモニターを開き、速度を115,200ボーに変更します。IDEシリアルモニターで「AT」コマンドの送信を開始します。 ESP-01は「OK」を返すはずです

次に、速度を変更しましょう。そのためには、次のコマンドを使用できます:

  AT + CIOBAUD =9600  

ESP-01が工場出荷時のプログラミングに戻る可能性があることに注意してください(これがFWバージョンによるものかどうかはわかりません)。少なくとも私の場合、BaudRateを明確に変更するには別のコマンドを使用する必要がありました:

  AT + UART_DEF =  

例:9600ボー/ 8データビット/ 1ストップビット、パリティおよびフロー制御なし:

  AT + UART_DEF =9600,8,1,0,0  

シリアルモニターの下部にある選択ボックスで、速度を「9600ボー」に変更します。通信をテストします。ウィンドウの上部にATと入力し、「OK」と答えます。次に、モジュールを ステーションモードで構成する必要があります クライアントとして機能する あなたのWi-Fiネットワークの。次のコマンドを使用します:

  AT + CWMODE =1  

次に、モジュールをWi-Fiネットワークに接続する必要があります。

これを行うには、以下のコマンドを使用して、「network_name」をWi-Fiネットワークの名前に置き換え、「network_name」をパスワードに置き換えます。引用符を保持します。

  AT + CWJAP ="network_name"、 "network_name"  

以下の回答が表示された場合、接続は正しく確立されています:

  WIFI CONNECTED WIFI GOT IP  

IPを見つけるには、次のコマンドを実行します。

  AT + CIFSR  

また、シリアルモニターに表示されるIPアドレスをメモします。将来必要になるかもしれません。

ステップ6:ESP-01のテスト

<図>

ESP-01を構成したら、最終回路にインストールする必要があります。そのためには、前に行った配線を変更し、以下のようにESP-01をUNOに接続する必要があります。

  • ESP-01 RX(黄色)からUNOピンD7
  • ESP-01 TX(オレンジ)からUNOピンD6
  • ESP-01 Ch-Pd(ブラウン)からVcc(3.3V)
  • ESP-01リセット(青)をUNOピンD8に
  • ESP-01 Vcc(赤)から3.3V
  • ESP-01 Gnd(黒)からUNO GND

簡単なテストを行って、ESP-01が正しくインストールおよびテストされているかどうかを確認しましょう。以下のコードを入力してください:

  #include  SoftwareSerial esp8266(6,7); // Rx ==>ピン6; TX ==> Pin7 #define speed8266 9600 void setup(){esp8266.begin(speed8266); Serial.begin(speed8266); Serial.println( "ESP8266セットアップテスト-ATクーマンドを使用");} void loop(){while(esp8266.available()){Serial.write(esp8266.read()); } while(Serial.available()){esp8266.write(Serial.read()); }}  

次に、いくつかのATコマンドを試して、シリアルモニターで結果を確認します。

<図>
  * AT =====> ESP8266はOKを返します* AT + RST =====> ESP8266は再起動してOKを返します* AT + GMR =====> ESP8266はATバージョンを返します。 SDKバージョン; id; OK * AT + CWMODE? => ESP8266はモードタイプを返します* AT + CWLAP ===> ESP8266はクローズアクセスポイントを返します* AT + CIFSR ===> ESP8266は指定されたIPを返します 

コードは私のGITHUBからダウンロードできます:ESP_AT_Config.ino

リセットが発生するたびに(またはArduinoがオフ/オンになるたびに)WiFiネットワークに接続して資格情報を入力する場合は、 connectWiFi()への呼び出しを追加します。 セットアップ()関数の最後の関数:

  setup(){... connectWiFi(); }  

connectWiFi() 関数はメインコードの最後にある必要があります。ino:

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

上記の関数は別の sendData(data)を呼び出すことに注意してください 関数。これもコードに含める必要があります:

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

ステップ7:センサーとESP-01を接続する

<図>

すべてのセンサーをインストールしてテストし、ESP-01が正常に機能するようになったら、すべてを一緒に見て、インターネットにデータを送信する準備をしましょう。

ステップ8:ThingSpeak

<図>

私たちのプロジェクトの最も重要な部分の1つは、収集されたデータの収集、分析、および操作を可能にするオープンIoTプラットフォームであるThingSpeakです。まだお持ちでない場合は、ThingSpeakにアクセスして、アカウントを作成してください。

次に、2つのアクチュエータ、5つのセンサー、および予備のフィールドステータスを持つ新しいチャネルを作成します。

  • フィールド1:アクチュエータ1
  • フィールド2:アクチュエータ2
  • フィールド3:気温(oC)
  • ファイル4:空気の相対湿度(%)
  • フィールド5:土壌温度(oC)
  • フィールド6:土壌湿度(%)
  • フィールド7:光度(%)
  • フィールド8:スペア

フィールド8は、将来の拡張またはデバッグ目的で使用するためのスペアとして残されます。たとえば、ThingSpeak.comとのArduino / ESP-01ハンドシェイク中に発生する各通信エラーの「カウンター」として使用します。

チャンネル(この場合はステータスチャンネル)を作成したら、以下に示すように、キーをメモしておくことが重要です。

<図>

ステップ9:ステータスをクラウドに送信する

<図>

この時点で、クラウドサービスが利用可能になり、センサーがローカルでデータをキャプチャします。それらの値を取得してThingSpeak.comに送信しましょう。 ThingSpeakチャネルに書き込みます。そのために、GET文字列を送信する必要があります。 3つのパートで行います:

「Startcmd」を送信します:

  AT + CIPSTART ="TCP"、 "184.106.153.149"、80  

コマンドの「長さ」に従う:

  AT + CIPSEND =116  

そして、ステータスチャネルの適切なフィールドに書き込むGET文字列自体:

  GET / update?api_key =YOUR_WRITE_KEY_HERE&field1 =pump&fieldlamp =0&field3 =airTemp&field4 =airHum&field5 =soapTemp&field6 =soapHum&field7 =light&field8 =spare 

以下のコードは私たちのために作業を行い、上記のPrintScreenはシリアルモニターに結果を表示します:

  // Thingspeak String statusChWriteKey ="6SRPQQKIE6AJVQE6"; //ステータスチャネルID:385184#include  SoftwareSerial EspSerial(6、7); // Rx、Tx#define HARDWARE_RESET 8 // DS18B20#include  #include  #define ONE_WIRE_BUS 5 //ピンD5上のDS18B20OneWire oneWire(ONE_WIRE_BUS); DallasTemperature DS18B20(&oneWire); intooilTemp =0; // DHT#include "DHT.h" #include  int pinoDHT =11; int tipoDHT =DHT22; DHT dht(pinoDHT、tipoDHT); int airTemp =0; int airHum =0; // LDR(Light)#define ldrPIN 1int light =0; //土壌湿度#definesoilHumPIN 0int soleHum =0; //タイマーで使用される変数longwriteTimingSeconds =17; // ==>データを送信するサンプル時間を秒単位で定義しますlongstartWriteTiming =0; longlapsedWriteTime =0; // Actuatorsbooleanポンプで使用される変数=0;ブールランプ=0; intスペア=0;ブールエラー; void setup(){Serial.begin(9600); pinMode(HARDWARE_RESET、OUTPUT); digitalWrite(HARDWARE_RESET、HIGH); DS18B20.begin(); dht.begin(); EspSerial.begin(9600); // Comunicacao com Modulo WiFi EspHardwareReset(); // ModuloWiFiをリセットしますstartWriteTiming =millis(); //「プログラムクロック」を開始します} void loop(){start:// label error =0;経過書き込み時間=ミリ秒()-startWriteTiming; if(elapsedWriteTime>(writeTimingSeconds * 1000)){readSensors(); writeThingSpeak(); startWriteTiming =millis(); } if(error ==1)//送信が完了していない場合は再送信{Serial.println( "<<<>>>");遅延(2000); goto start; //ラベル「start」に移動}} / *********センサー値の読み取り************* / void readSensors(void){airTemp =dht.readTemperature(); airHum =dht.readHumidity(); DS18B20.requestTemperatures(); soleTemp =DS18B20.getTempCByIndex(0); //センサー0は摂氏ライトで土壌温度をキャプチャします=map(analogRead(ldrPIN)、1023、0、0、100); // LDRDark:0 ==>ライト100%soilHum =map(analogRead(soilHumPIN)、1023、0、0、100); } / ********* Conexao com TCP com Thingspeak ******* / void writeThingSpeak(void){startThingSpeakCmd(); // preparacao da string GET String getStr ="GET / update?api_key ="; getStr + =statusChWriteKey; getStr + ="&field1 ="; getStr + =String(pump); getStr + ="&field2 ="; getStr + =String(lamp); getStr + ="&field3 ="; getStr + =String(airTemp); getStr + ="&field4 ="; getStr + =String(airHum); getStr + ="&field5 ="; getStr + =String(soilTemp); getStr + ="&field6 ="; getStr + =String(soilHum); getStr + ="&field7 ="; getStr + =String(light); getStr + ="&field8 ="; getStr + =String(spare); getStr + ="\ r \ n \ r \ n"; sendThingSpeakGetCmd(getStr); } / ********* ESPのリセット************* / void EspHardwareReset(void){Serial.println( "Reseting ......."); digitalWrite(HARDWARE_RESET、LOW); delay(500); digitalWrite(HARDWARE_RESET、HIGH); delay(8000); //TemponecessárioparacomeçaralerSerial.println( "RESET"); } / ********* ThingSpeakとの通信を開始します************* / void startThingSpeakCmd(void){EspSerial.flush(); // limpaobufferantesdecomeçara gravar String cmd ="AT + CIPSTART =\" TCP \ "、\" "; cmd + =" 184.106.153.149 "; // Endereco IP de api.thingspeak.com cmd + =" \ "、80"; EspSerial.println(cmd); Serial.print( "enviado ==>コマンドの開始:"); Serial.println(cmd); if(EspSerial.find( "Error")){Serial.println( "AT + CIPSTARTエラー");戻る; }} / ********* GETコマンドをThingSpeakに送信します************* / String sendThingSpeakGetCmd(String getStr){String cmd ="AT + CIPSEND ="; cmd + =String(getStr.length()); EspSerial.println(cmd); Serial.print( "enviado ==> lenght cmd:"); Serial.println(cmd); if(EspSerial.find((char *) ">")){EspSerial.print(getStr); Serial.print( "enviado ==> getStr:"); Serial.println(getStr); delay(500); // tempo para processar o GET、sem este delayapresentabosynopróximocomandoStringmessageBody=""; while(EspSerial.available()){文字列行=EspSerial.readStringUntil( '\ n'); if(line.length()==1){//実際のコンテンツは空の行(長さ1)の後に始まりますmessageBody =EspSerial.readStringUntil( '\ n'); }} Serial.print( "MessageBody receive:"); Serial.println(messageBody); messageBodyを返します。 } else {EspSerial.println( "AT + CIPCLOSE"); //ユーザーに警告Serial.println( "ESP8266 CIPSEND ERROR:RESENDING"); //再送...スペア=スペア+1;エラー=1; 「エラー」を返します。 }}  

コードは私のGITHUBからダウンロードできます:SendingStatusTS_EXT.ino

ステップ10:Androidアプリの最初の部分-ステータスの監視

<図>

Androidアプリの最初の部分を作成しましょう。

まず、ユーザーインターフェイスを設計します。上記のPrintScreenは、主な表示要素と非表示要素を示しています。その後、ブロックを設計する必要があります(以下の番号は上記の図に対応しています):

2秒ごと(Clock1で定義)に、「readArduino」という名前のプロシージャを呼び出します。

<図> <図> <図>
  • このようなプロシージャの戻り値は、画面に表示されるステータス変数のそれぞれの値になります。
  • 理解を深めるために、アクチュエータのステータスから「0」と「1」の値を「OFF」と「ON」に「変換」することに注意してください。
  • これらの値(「ステータス」)は、対応する「ラベル」に表示されます
  • ステータス変数はグローバルとして宣言する必要があります。
  • プロシージャ「readArduino」は、実際、ThingSpeakのステータスチャネルを読み取ります。したがって、Thingspeakに送信するURLを定義する必要があります。そのためには、TSに送信するURLを作成するために、3つのグローバル変数を宣言して結合する必要があります。 GETは「ArduFarmBotStatusCh」という名前のWebコンポーネントに送信する必要があります
  • 前のコマンドから取得したテキストは、JSon形式で届きます。このテキストは、対応するグローバル変数で読み取られて保存される各フィールドを使用して処理する必要があります。
  • 最後に行うことは、2つの土壌センサーのステータスを分析する「アラーム」手順を呼び出すことです。温度が低すぎる場合(この場合は10oC)、メッセージを表示する必要があります。 60%未満の場合、湿度についても同じです。 1秒ごとに起動するようにプログラムされた別のタイマー(Clock2)を定義していることに注意してください。これは、メッセージテキストの色(白から赤)を「切り替える」ためだけのものです。これにより、メッセージが「点滅」します。

上の最後の写真は、最終的なアプリの動作を示しています。

<図>

アプリコードは私のGITHUBからダウンロードできます:ArduFarmBot_Status_App_EXT.aia

ステップ11:アクチュエータ(LEDとリレー)の取り付け

<図>

HWを完成させましょう。

そのためには、アクチュエータを設置する必要があります。ご存知のように、ポンプとランプのオンとオフを切り替えるコマンドをリモートで受信します。 Arduino出力は、これらのアクションを取得するためにリレー(およびLED)をアクティブにします。

オプトカプラー低レベルトリガーを備えたリレーモジュールを使用します。また、別のピンを介して5Vを供給するため、入力ピンに必要な電流を供給する必要はありません。モジュールは私たちのためにそれを行います。

上の図は、アクチュエータの接続方法を示しています。 RealyGNDはArduinoGNDに接続されていないことに注意してください。これは、リレーが動作するときにノイズを導入しないようにするのに役立ちます。

簡単にするために、図からセンサーを取り出しました。ただし、すでにインストールしてテストしたセンサーを取り外さなくても、アクチュエータ回路をプロジェクトに追加できます。

ステップ12:ThingSpeakアクチュエータチャネルの構成

<図>

ステータスの場合と同じ方法で、アクチュエータごとに1つずつ2つの新しいチャネルを作成します。それらのそれぞれから、チャネルID、読み取りおよび書き込みキーをメモします。 フィールド1にのみ書きます それらのチャネルのそれぞれの。したがって、私の場合、たとえば:

チャネルID375598 ==> LED赤(ポンプ)

  • Field1 =0 ==>ポンプオフ
  • Field1 =1 ==>ポンプオン

チャネルID375599 ==> LED緑色(ランプ)

  • フィールド1 =0 ==>ランプオフ
  • フィールド1 =1 ==>ランプがオン

ステップ13:アクチュエータを使用したArduinoコードのインストールとテスト

<図>

データをWebに送信するとき、私たちが行ったことは、ThingSpeakチャネル(チャネルステータス)に書き込み、データを「送信」(アップロード)することでした。次に、ThingSpeakチャネル(アクチュエータチャネル)から読み取り、データを「受信」(ダウンロード)する必要があります。

ThingSpeakチャネルから読み取り、そのためにGET文字列を送信する必要があります。 3つのパートで行います:

「Startcmd」を送信します:

  AT + CIPSTART ="TCP"、 "184.106.153.149"、80  

コマンドの「長さ」に従う:

  AT + CIPSEND =36  

そして、アクチュエータチャネルのそれぞれのフィールド1から読み取られるGET文字列自体:

  GET / channels / 375598 / fields / 1 / last  

ThingSpeakチャネルから10秒間隔で読み取ります。上記のGETコマンドを送信すると、「フィールド1に保存された最後の値」が呼び出され、ThingSpeakから、回答の特定の位置で「1」または「0」の回答が返されます。それと異なる場合は、到着しました。無視する必要があります。

コードのこの部分と(ステータスデータを送信するための)前の部分との主な違いは、次の機能です。

  readThingSpeak(String channelID) 

以下のコードは私たちのために作業を行い、上記のPrintScreenはシリアルモニターに結果を表示します:

  // Thingspeak String canalID1 ="375598"; // Actuator1String canalID2 ="375599"; // Actuator2#include  SoftwareSerial EspSerial(6、7); // Rx、Tx#define HARDWARE_RESET 8 // timerslongで使用される変数readTimingSeconds =10; // ==>データを受信するためのサンプル時間を秒単位で定義longstartReadTiming =0; longlapsedReadTime =0; // Relays#define ACTUATOR1 10 // RED LED ==> Pump#define ACTUATOR2 12 // GREEN LED ==>ランプブールポンプ=0;ブールランプ=0; intスペア=0;ブールエラー; void setup(){Serial.begin(9600); pinMode(ACTUATOR1、OUTPUT); pinMode(ACTUATOR2、OUTPUT); pinMode(HARDWARE_RESET、OUTPUT); digitalWrite(ACTUATOR1、HIGH); //omódulorelééativoemLOWdigitalWrite(ACTUATOR2、HIGH); //omódulorelééativoemLOWdigitalWrite(HARDWARE_RESET、HIGH); EspSerial.begin(9600); // Comunicacao com Modulo WiFi EspHardwareReset(); // ModuloWiFiをリセットしますstartReadTiming =millis(); //「プログラムクロック」を開始します} void loop(){start:// label error =0;経過読み取り時間=ミリ秒()-startReadTiming; if(elapsedReadTime>(readTimingSeconds * 1000)){int command =readThingSpeak(canalID1); if(command!=9)pump =command;遅延(5000);コマンド=readThingSpeak(canalID2); if(command!=9)lamp =command; takeActions(); startReadTiming =millis(); } if(error ==1)//送信が完了していない場合は再送信{Serial.println( "<<<>>>");遅延(2000); goto start; //ラベル「start」に移動}} / ********* ThingSpeakコマンドに基づいてアクションを実行します************* / void takeActions(void){Serial.print( "ポンプ:"); Serial.println(ポンプ); Serial.print( "ランプ:"); Serial.println(ランプ); if(pump ==1)digitalWrite(ACTUATOR1、LOW);それ以外の場合、digitalWrite(ACTUATOR1、HIGH); if(lamp ==1)digitalWrite(ACTUATOR2、LOW); else digitalWrite(ACTUATOR2、HIGH);} / ********* ThingSpeakからアクチュエータコマンドを読み取る************* / int readThingSpeak(String channelID){startThingSpeakCmd(); intコマンド; // preparacao da string GET String getStr ="GET / channels /"; getStr + =channelID; getStr + ="/ fields / 1 / last"; getStr + ="\ r \ n";文字列messageDown =sendThingSpeakGetCmd(getStr); if(messageDown [5] ==49){コマンド=messageDown [7] -48; Serial.print( "コマンドを受信しました:"); Serial.println(コマンド); } else command =9; return command;} / ********* ESPをリセット************* / void EspHardwareReset(void){Serial.println( "Reseting ......." ); digitalWrite(HARDWARE_RESET、LOW); delay(500); digitalWrite(HARDWARE_RESET、HIGH); delay(8000); //TemponecessárioparacomeçaralerSerial.println( "RESET"); } / ********* ThingSpeakとの通信を開始します************* / void startThingSpeakCmd(void){EspSerial.flush(); // limpaobufferantesdecomeçara gravar String cmd ="AT + CIPSTART =\" TCP \ "、\" "; cmd + =" 184.106.153.149 "; // Endereco IP de api.thingspeak.com cmd + =" \ "、80"; EspSerial.println(cmd); Serial.print( "enviado ==>コマンドの開始:"); Serial.println(cmd); if(EspSerial.find( "Error")){Serial.println( "AT + CIPSTARTエラー");戻る; }} / ********* GETコマンドをThingSpeakに送信します************* / String sendThingSpeakGetCmd(String getStr){String cmd ="AT + CIPSEND ="; cmd + =String(getStr.length()); EspSerial.println(cmd); Serial.print( "enviado ==> lenght cmd:"); Serial.println(cmd); if(EspSerial.find((char *) ">")){EspSerial.print(getStr); Serial.print( "enviado ==> getStr:"); Serial.println(getStr); delay(500);//tempo para processar o GET, sem este delay apresenta busy no próximo comando String messageBody =""; while (EspSerial.available()) { String line =EspSerial.readStringUntil('\n'); if (line.length() ==1) { //actual content starts after empty line (that has length 1) messageBody =EspSerial.readStringUntil('\n'); } } Serial.print("MessageBody received:"); Serial.println(messageBody); return messageBody; } else { EspSerial.println("AT+CIPCLOSE"); // alert user Serial.println("ESP8266 CIPSEND ERROR:RESENDING"); //Resend... spare =spare + 1; error=1; return "error"; }}  

The code can be downloaded from my GITHUB:ReadingCommandTS_EXT.ino

Step 14:Sending Commands to Actuators

<図>

At this point, we have the actuators channels configured on ThingSpeak and changing the value of Field 1 on each channel, we must see the actuators changing accordingly. On our final project we will do this task, using the Android App, but for testing proposes we can also do it using a normal browser. Let's do it.

The commands are:

Turn ON Pump (RED LED):

https://api.thingspeak.com/update?api_key=ACT1_WRITE_KEY&field1=1 

Turn OFF Pump (RED LED):

https://api.thingspeak.com/update?api_key=ACT1_WRITE_KEY&field1=0 

Turn ON Lamp (GREEN LED):

https://api.thingspeak.com/update?api_key=ACT2_WRITE_KEY&field1=1 

Turn OFF Lamp (GREEN LED):

https://api.thingspeak.com/update?api_key=ACT2_WRITE_KEY&field1=0 

Above you can see a print screen of a command to TurnOn the Pump sent from a browser and how it will appear at Serial Monitor. Obviously, the LED Red and relay will be also be turned on.

Step 15:Completing the Android APP

<図>

Let's complete the APP. Previously we have developed a simple App that gets the status from ThingSpeak (READ from Staus Channel). Now we must WRITE on Actuator channels, so those commands could be read by Arduino and act on Pump and Lamp accordingly.

For a user to pass the commands to the App, we will use "buttons". A pair of buttons (ON and OFF) for each one of the Actuators.

When a button is pressed, the color of its text changes.

  • If ON ==> Blue
  • if OFF ==> Red
<図> <図>

Above you can see the set of blocks for each one of the pairs of buttons.

Test the App, sending commands to turn ON and OFF the actuators. Check on Serial Monitor, the messages exchanged between ESP-01 and ThingSpeak.

<図>

The complete App code can be downloaded from my GITHUB:ArduFarmBot_V1_EXT.aia

Step 16:Putting All Together

<図>

完全! At this point, you have a full Android APP, a complete HW but you still do not have a code that will continuously read and write on ThingSpeak. Let's combine all that we have developed previously.

On the final code, you will find additional portions to verify for example if the ESP-01 is not freezing. We will do it, sending an AT command to it before any read or write. As we saw at the very beginning of this tutorial, sending an AT command should return from ESP-01 an OK. If this does not happen, we will proceed with an HW reset, commanded by SW (as we do once during setup phase).

The complete code for our project can be downloaded from my GITHUB:ArduFarmBot_Light_EXT.ino

Step 17:Conclusion

<図>

There is a lot to be explored in IoT arena with those great little devices, the Arduino Uno, and the ESP8266-01. We will return soon with new tutorials! Keep following MJRoBot tutorials!

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

Please visit my GitHub for updated files:ArduFarmBot_Light

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

Saludos from the south of the world!

See you at my next tutorial!

Thank you,

Marcelo

コード

  • コードスニペット#1
  • コードスニペット#2
  • コードスニペット#3
  • コードスニペット#11
  • コードスニペット#12
  • Code snippet #16
  • Code snippet #20
コードスニペット#1 プレーンテキスト
// DS18B20#include #include #define ONE_WIRE_BUS 5 // DS18B20 on pin D5 OneWire oneWire(ONE_WIRE_BUS);DallasTemperature DS18B20(&oneWire);int soilTemp =0;//DHT#include "DHT.h"#include int pinoDHT =11;int tipoDHT =DHT22;DHT dht(pinoDHT, tipoDHT); int airTemp =0;int airHum =0;// LDR (Light)#define ldrPIN 1int light =0;// Soil humidity#define soilHumPIN 0int soilHum =0;
コードスニペット#2 プレーンテキスト
void setup(){ Serial.begin(9600); DS18B20.begin(); dht.begin();}void loop(){ readSensors(); displaySensors(); delay (10000);}
コードスニペット#3 プレーンテキスト
/********* Read Sensors value *************/void readSensors(void){ airTemp =dht.readTemperature(); airHum =dht.readHumidity(); DS18B20.requestTemperatures(); soilTemp =DS18B20.getTempCByIndex(0); // Sensor 0 will capture Soil Temp in Celcius soilHum =map(analogRead(soilHumPIN), 1023, 0, 0, 100); light =map(analogRead(ldrPIN), 1023, 0, 0, 100); //LDRDark:0 ==> light 100% }/********* Display Sensors value *************/void displaySensors(void){ Serial.print ("airTemp (oC):"); Serial.println (airTemp); Serial.print ("airHum (%):"); Serial.println (airHum); Serial.print ("soilTemp (oC):"); Serial.println (soilTemp); Serial.print ("soilHum (%):"); Serial.println (soilHum); Serial.print ("light (%):"); Serial.println (light); Serial.println ("");}
コードスニペット#11 プレーンテキスト
#include  SoftwareSerial esp8266(6,7); //Rx ==> Pin 6; TX ==> Pin7 #define speed8266 9600 void setup() { esp8266.begin (speed8266); Serial.begin(speed8266); Serial.println("ESP8266 Setup test - use AT coomands");}void loop() { while(esp8266.available()) { Serial.write(esp8266.read()); } while(Serial.available()) { esp8266.write(Serial.read()); }} 
コードスニペット#12 プレーンテキスト
* AT =====> ESP8266 returns OK* AT+RST =====> ESP8266 restart and returns OK* AT+GMR =====> ESP8266 returns AT Version; SDK version; id; OK* AT+CWMODE? => ESP8266 returns mode type* AT+CWLAP ===> ESP8266 returs close access points* AT+CIFSR ===> ESP8266 returs designided IP
Code snippet #16Plain text
// Thingspeak String statusChWriteKey ="6SRPQQKIE6AJVQE6"; // Status Channel id:385184#include SoftwareSerial EspSerial(6, 7); // Rx, Tx#define HARDWARE_RESET 8// DS18B20#include #include #define ONE_WIRE_BUS 5 // DS18B20 on pin D5 OneWire oneWire(ONE_WIRE_BUS);DallasTemperature DS18B20(&oneWire);int soilTemp =0;//DHT#include "DHT.h"#include int pinoDHT =11;int tipoDHT =DHT22;DHT dht(pinoDHT, tipoDHT); int airTemp =0;int airHum =0;// LDR (Light)#define ldrPIN 1int light =0;// Soil humidity#define soilHumPIN 0int soilHum =0;// Variables to be used with timerslong writeTimingSeconds =17; // ==> Define Sample time in seconds to send datalong startWriteTiming =0;long elapsedWriteTime =0;// Variables to be used with Actuatorsboolean pump =0; boolean lamp =0; int spare =0;boolean error;void setup(){ Serial.begin(9600); pinMode(HARDWARE_RESET,OUTPUT); digitalWrite(HARDWARE_RESET, HIGH); DS18B20.begin(); dht.begin(); EspSerial.begin(9600); // Comunicacao com Modulo WiFi EspHardwareReset(); //Reset do Modulo WiFi startWriteTiming =millis(); // starting the "program clock"}void loop(){ start://label error=0; elapsedWriteTime =millis()-startWriteTiming; if (elapsedWriteTime> (writeTimingSeconds*1000)) { readSensors(); writeThingSpeak(); startWriteTiming =millis(); } if (error==1) //Resend if transmission is not completed { Serial.println(" <<<>>>"); delay (2000); goto start; //go to label "start" }}/********* Read Sensors value *************/void readSensors(void){ airTemp =dht.readTemperature(); airHum =dht.readHumidity(); DS18B20.requestTemperatures(); soilTemp =DS18B20.getTempCByIndex(0); // Sensor 0 will capture Soil Temp in Celcius light =map(analogRead(ldrPIN), 1023, 0, 0, 100); //LDRDark:0 ==> light 100% soilHum =map(analogRead(soilHumPIN), 1023, 0, 0, 100); }/********* Conexao com TCP com Thingspeak *******/void writeThingSpeak(void){ startThingSpeakCmd(); // preparacao da string GET String getStr ="GET /update?api_key="; getStr +=statusChWriteKey; getStr +="&field1="; getStr +=String(pump); getStr +="&field2="; getStr +=String(lamp); getStr +="&field3="; getStr +=String(airTemp); getStr +="&field4="; getStr +=String(airHum); getStr +="&field5="; getStr +=String(soilTemp); getStr +="&field6="; getStr +=String(soilHum); getStr +="&field7="; getStr +=String(light); getStr +="&field8="; getStr +=String(spare); getStr +="\r\n\r\n"; sendThingSpeakGetCmd(getStr); }/********* Reset ESP *************/void EspHardwareReset(void){ Serial.println("Reseting......."); digitalWrite(HARDWARE_RESET, LOW); delay(500); digitalWrite(HARDWARE_RESET, HIGH); delay(8000);//Tempo necessário para começar a ler Serial.println("RESET"); }/********* Start communication with ThingSpeak*************/void startThingSpeakCmd(void){ EspSerial.flush();//limpa o buffer antes de começar a gravar String cmd ="AT+CIPSTART=\"TCP\",\""; cmd +="184.106.153.149"; // Endereco IP de api.thingspeak.com cmd +="\",80"; EspSerial.println(cmd); Serial.print("enviado ==> Start cmd:"); Serial.println(cmd); if(EspSerial.find("Error")) { Serial.println("AT+CIPSTART error");戻る; }}/********* send a GET cmd to ThingSpeak *************/String sendThingSpeakGetCmd(String getStr){ String cmd ="AT+CIPSEND="; cmd +=String(getStr.length()); EspSerial.println(cmd); Serial.print("enviado ==> lenght cmd:"); Serial.println(cmd); if(EspSerial.find((char *)">")) { EspSerial.print(getStr); Serial.print("enviado ==> getStr:"); Serial.println(getStr); delay(500);//tempo para processar o GET, sem este delay apresenta busy no próximo comando String messageBody =""; while (EspSerial.available()) { String line =EspSerial.readStringUntil('\n'); if (line.length() ==1) { //actual content starts after empty line (that has length 1) messageBody =EspSerial.readStringUntil('\n'); } } Serial.print("MessageBody received:"); Serial.println(messageBody); return messageBody; } else { EspSerial.println("AT+CIPCLOSE"); // alert user Serial.println("ESP8266 CIPSEND ERROR:RESENDING"); //Resend... spare =spare + 1; error=1; return "error"; }} 
Code snippet #20Plain text
// Thingspeak String canalID1 ="375598"; //Actuator1String canalID2 ="375599"; //Actuator2#include SoftwareSerial EspSerial(6, 7); // Rx, Tx#define HARDWARE_RESET 8// Variables to be used with timerslong readTimingSeconds =10; // ==> Define Sample time in seconds to receive datalong startReadTiming =0;long elapsedReadTime =0;//Relays#define ACTUATOR1 10 // RED LED ==> Pump#define ACTUATOR2 12 // GREEN LED ==> Lampboolean pump =0; boolean lamp =0; int spare =0;boolean error;void setup(){ Serial.begin(9600); pinMode(ACTUATOR1,OUTPUT); pinMode(ACTUATOR2,OUTPUT); pinMode(HARDWARE_RESET,OUTPUT); digitalWrite(ACTUATOR1, HIGH); //o módulo relé é ativo em LOW digitalWrite(ACTUATOR2, HIGH); //o módulo relé é ativo em LOW digitalWrite(HARDWARE_RESET, HIGH); EspSerial.begin(9600); // Comunicacao com Modulo WiFi EspHardwareReset(); //Reset do Modulo WiFi startReadTiming =millis(); // starting the "program clock"}void loop(){ start://label error=0; elapsedReadTime =millis()-startReadTiming; if (elapsedReadTime> (readTimingSeconds*1000)) { int command =readThingSpeak(canalID1); if (command !=9) pump =command; delay (5000); command =readThingSpeak(canalID2); if (command !=9) lamp =command; takeActions(); startReadTiming =millis(); } if (error==1) //Resend if transmission is not completed { Serial.println(" <<<>>>"); delay (2000); goto start; //go to label "start" }}/********* Take actions based on ThingSpeak Commands *************/void takeActions(void){ Serial.print("Pump:"); Serial.println(pump); Serial.print("Lamp:"); Serial.println(lamp); if (pump ==1) digitalWrite(ACTUATOR1, LOW); else digitalWrite(ACTUATOR1, HIGH); if (lamp ==1) digitalWrite(ACTUATOR2, LOW); else digitalWrite(ACTUATOR2, HIGH);}/********* Read Actuators command from ThingSpeak *************/int readThingSpeak(String channelID){ startThingSpeakCmd(); int command; // preparacao da string GET String getStr ="GET /channels/"; getStr +=channelID; getStr +="/fields/1/last"; getStr +="\r\n"; String messageDown =sendThingSpeakGetCmd(getStr); if (messageDown[5] ==49) { command =messageDown[7]-48; Serial.print("Command received:"); Serial.println(command); } else command =9; return command;}/********* Reset ESP *************/void EspHardwareReset(void){ Serial.println("Reseting......."); digitalWrite(HARDWARE_RESET, LOW); delay(500); digitalWrite(HARDWARE_RESET, HIGH); delay(8000);//Tempo necessário para começar a ler Serial.println("RESET"); }/********* Start communication with ThingSpeak*************/void startThingSpeakCmd(void){ EspSerial.flush();//limpa o buffer antes de começar a gravar String cmd ="AT+CIPSTART=\"TCP\",\""; cmd +="184.106.153.149"; // Endereco IP de api.thingspeak.com cmd +="\",80"; EspSerial.println(cmd); Serial.print("enviado ==> Start cmd:"); Serial.println(cmd); if(EspSerial.find("Error")) { Serial.println("AT+CIPSTART error");戻る; }}/********* send a GET cmd to ThingSpeak *************/String sendThingSpeakGetCmd(String getStr){ String cmd ="AT+CIPSEND="; cmd +=String(getStr.length()); EspSerial.println(cmd); Serial.print("enviado ==> lenght cmd:"); Serial.println(cmd); if(EspSerial.find((char *)">")) { EspSerial.print(getStr); Serial.print("enviado ==> getStr:"); Serial.println(getStr); delay(500);//tempo para processar o GET, sem este delay apresenta busy no próximo comando String messageBody =""; while (EspSerial.available()) { String line =EspSerial.readStringUntil('\n'); if (line.length() ==1) { //actual content starts after empty line (that has length 1) messageBody =EspSerial.readStringUntil('\n'); } } Serial.print("MessageBody received:"); Serial.println(messageBody); return messageBody; } else { EspSerial.println("AT+CIPCLOSE"); // alert user Serial.println("ESP8266 CIPSEND ERROR:RESENDING"); //Resend... spare =spare + 1; error=1; return "error"; }} 
Github
https://github.com/Mjrovai/ArduFarmBot_Light

回路図

Electrical diagram
https://github.com/Mjrovai/ArduFarmBot_Light/blob/master/ArduFarmBot_Light/ArduFarmBot%20Light.fzz

製造プロセス

  1. Raspberry Pi 4B + IoTボードでの並列コンピューティングが容易に
  2. IoTを使用した心拍数モニター
  3. Arduino UnoWiFiを使用したWebServerBlink
  4. シンプルなUNO計算機
  5. 視覚の持続性
  6. 無接触温度監視ゲート
  7. Arduino-シリアル経由でWebに温度を送信
  8. ThingSpeak Arduino Weather Station
  9. 学校向けのSMART温度監視
  10. サーミスタの使い方は簡単ですか?!
  11. AzureIoTスイミングプール