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

ハーブボックスエコシステム

コンポーネントと消耗品

>
Amazon Alexa Echo Dot
× 1
Arduino UNO
× 1
Espressif ESP8266 ESP-01
× 1
Arduinoプロトシールド
× 1
Arduino4リレーシールド
× 1
アクアポンプ
× 2
植物成長ランプ
× 1
220VDC電源アダプター
× 1
12VDC電源アダプター
× 1
USB電源プラグ+ケーブル
× 1
エアホース
× 1
ジャンパー線(汎用)
× 1

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

>
Arduino IDE
Amazon AlexaAlexaスキルキット
Amazon Web Services AWS Lambda
phpWebサーバー

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

私の植物は常に水が多すぎたり少なすぎたりすることがあり、皿にたくさんのハーブを入れるのが好きなので、カスタム灌漑システムを作成することにしました。私のハーブの箱は構成可能で、自動または手動で機能するはずです。したがって、セットアップを可能にし、湿度を素敵なチャートで表示するためのWebサイトへのインターフェイスが存在します。最後のステップは、音声制御を統合して、Amazon Alexaに湿度を要求し、植物成長ランプのオン/オフを切り替え、自動化が無効になっている場合は灌漑を開始することでした。結果を見つけるには、ここをクリックしてください。

私はプロジェクトの技術的な部分から始めて、Arduinoを購入しました。いくつかのチュートリアルの後、私はソフトウェアとArduinoの制御に固執しました。私はwifiコントローラー、いくつかの水分センサー、ポンプ、植物成長ランプ、および追加の必要なハードウェア(Arduinoからランプとポンプの回路を分離するためのリレーシールド、フレーム用のいくつかのワイヤーとブナ材)を注文しました。結果のArduinoコードは、プロジェクトでコンポーネントを使用する方法のいくつかの情報のほかに、このチュートリアルで提供されます。ウェブサイト/ APIコードは提供されていません(需要が非常に高い場合を除きます;))。

ステップ1:水分センサー

最初のマイルストーンは、Arduinoで湿度を読み取ることでした。水分センサーYL-69はArduinoと簡単に接続できました。 VCCピンをGPIOピン(私の例ではピン06)に接続し、アースをアースに接続し、A0をArduinoのアナログピン(私の例ではピンA1)に接続する必要があります。

チュートリアル:土壌湿度センサー

  byte vccPin =6; byte dataPin =A1; void setup(){pinMode(vccPin、OUTPUT); digitalWrite(vccPin、LOW); Serial.begin(9600); while(!Serial);} int readHumidity(){digitalWrite(vccPin、HIGH); delay(500); //測定前にプリパワーする時間をテストする必要がありますintvalue =analogRead(dataPin); digitalWrite(vccPin、LOW); return 1023 --value;} void loop(){Serial.print( "HumidityLevel(0-1023):"); Serial.println(readHumidity()); delay(10000);}  

ステップ2:ポンプとランプのリレー

次の目標は、ランプ、ポンプ、Arduinoの回路を分離するためのリレーシールド(4リレー)を設置することでした。 Arduinoは5Vで動作し、ポンプは12Vを使用し、植物成長ランプは230Vを使用します。シールドは、Arduinoの5Vピンとアースピンに接続する必要があります。各リレーには、オンとオフを切り替えるために選択したGPIOピンがさらに必要です。最後に、シールド上のVCC JCからVCCへのジャンパーを使用するか、予備のバッテリーを使用することができます(これが最善ですが、プロジェクト内にまだバッテリーがありません)。

私のシールドはピンの「LOW」で「On」に切り替わるということを理解することが重要です。ピンがOUTPUTとして定義されるとすぐに、自動的にアクティブに切り替わります。コードでは、リレーをオフにする場合は、常にINPUTとLOWに切り替える必要があります。デフォルトでは、ArduinoピンはINPUTとLOWです。

チュートリアル:リレーシールド

情報:なぜOUTPUT + LOW =アクティブをリレーするのですか?

  byte pump1 =11; byte pump2 =10; void setup(){Serial.begin(9600); while(!Serial); pinMode(pump1、OUTPUT); //バリアントlow / high digitalWrite(pump2、LOW); //バリアント入力/出力} void loop(){digitalWrite(pump1、HIGH); // pump1が非アクティブ化されたpinMode(pump2、INPUT); // pump2が非アクティブ化されたdelay(1000); digitalWrite(pump1、LOW); // pump1がアクティブ化されたpinMode(pump2、OUTPUT); // pump2がアクティブ化したdelay(1000);}  

ステップ3:ESP-01を使用したWiFi

espressif ESP8266ESP-01をArduinofor WiFiに接続することは、最も困難な部分でした。スクリプトでWi-Fiを実行するのに何時間もかかりました。

ESPは次の場所に接続されています:VCC =3.3V、GND =GND、CH_PD =3.3V、TX =ピン02、RX =ピン03。生産的な使用のためには、ピンに少なくとも5Vから3.3Vのレベルコンバータを使用する必要があります。 02とピン03も。私の場合、うまくいきました。

Arduinoと同様に、ESP-01は別のマイクロコントローラーです。両方のコントローラーが通信するようにする場合は、シリアル通信を使用する必要があります。 Arduino UNOは、デフォルトでRXとTXにピン01と02を使用します。ただし、これらはUSBデバッグにも使用されるため、SoftwareSerial.hを含め、カスタムピンを定義することをお勧めします。

  #include  SoftwareSerial espSerial(3,2); // RX、TXvoid setup(){Serial.begin(9600); espSerial.begin(115200); // AT + UART_DEF =9600,8,1,0,0の後に9600に切り替えますwhile(!Serial);} void loop(){if(espSerial.available()){Serial.write(espSerial.read()); } if(Serial.available()){espSerial.write(Serial.read()); }}  

上記のスクリプトを実行すると、シリアルモニターにATコマンドを入力して、結果を確認できます。シリアル通信が失敗する傾向があるため、ESPで使用される通信ボーレートを115200から9600に下げました。

チュートリアル:ESP8266 + Arduino |チュートリアル:一般的なESP8266(ドイツ語)

  • 便利なヘルパークラス(ただし、メモリの使用量が多すぎます):ライブラリ:WiFiEsp
  • メモリチェックツール:ライブラリ:MemoryFree
<図> <図>

HTTP 1.1ではバイトが応答の一部であるため、スクリプトはHTTP1.0を使用します。 AT + CIPSENDの後に送信されるコマンドの改行に注意することが重要です。それらが間違っていると、バイト送信エラーが発生します。

  #include  SoftwareSerial espSerial(3,2); // RX、TXconst char * ssid =""; const char * pass =""; void setup(){Serial.begin(9600); espSerial.begin(9600); while(!Serial); while(!connectToWiFi()); // Webサイトを要求し、結果を出力if(httpRequest( "my.server.com"、 "/site/subsite/index.php")){while(espSerial.available()){Serial.write(espSerial.read() ); }}} void loop(){//何度も実行if(espSerial.available()){Serial.write(espSerial.read()); } if(Serial.available()){espSerial.write(Serial.read()); }} bool connectToWiFi(){delay(2000;)espSerial.setTimeout(3000); while(espSerial.available())Serial.write(espSerial.read()); Serial.println(F( "[ESP] WiFiに接続しています")); espSerial.println(F( "AT + CIPSTATUS =2")); if(!espSerial.find( "OK")){espSerial.setTimeout(10000); Serial.println(F( "[ESP]リセットモジュール")); espSerial.println(F( "AT + RST")); if(!espSerial.find( "ready")){Serial.println(F( "[ESP]リセットに失敗しました")); falseを返します。 } Serial.println(F( "[ESP] Set CWMode")); espSerial.println(F( "AT + CWMODE =1")); if(!espSerial.find( "OK")){Serial.println(F( "[ESP]モードに失敗しました")); falseを返します。 } Serial.println(F( "[ESP]ルーターに接続")); espSerial.print(F( "AT + CWJAP =\" ")); espSerial.print(ssid); espSerial.print(F(" \ "、\" ")); espSerial.print(pass); espSerial.println ( "\" "); if(!espSerial.find( "OK")){Serial.println(F( "[ESP] WiFi接続に失敗しました")); falseを返します。 }} espSerial.setTimeout(3000); Serial.println(F( "[ESP] WiFiが接続されています")); trueを返します;} bool httpRequest(String server、String site){String cmd =""; cmd + ="GET" + site + "HTTP / 1.0 \ r \ n"; cmd + ="ホスト:" +サーバー+ "\ r \ n"; cmd + ="接続:閉じる"; int cmdLength =cmd.length()+ 4; // Serial.println(cmd); espSerial.print(F( "AT + CIPSTART =\" TCP \ "、\" ")); espSerial.print(server); espSerial.println(F(" \ "、80")); if(!espSerial.find( "OK")){Serial.println(F( "[ESP] TCP接続エラー")); falseを返します。 } espSerial.print(F( "AT + CIPSEND =")); espSerial.println(cmdLength); if(!espSerial.find(findGT)){Serial.println(F( "[ESP] Send State Error")); falseを返します。 } espSerial.print(F( "GET")); espSerial.print(site); espSerial.print(F( "HTTP / 1.0 \ r \ n")); espSerial.print(F( "ホスト:")); espSerial.print(server); espSerial.print(F( "\ r \ n")); espSerial.print(F( "接続:閉じる\ r \ n")); espSerial.println(); if(!espSerial.find( ":")){Serial.println(F( "Bytes not send")); espSerial.print(F( "AT + CIPCLOSE")); falseを返します。 } char status [32] ={0}; espSerial.readBytesUntil( '\ r'、status、sizeof(status)); if(strcmp(status、 "HTTP / 1.1 200 OK")!=0){Serial.print(F( "[ESP]予期しない応答:")); Serial.println(ステータス); falseを返します。 } if(!espSerial.find( "\ r \ n \ r \ n")){Serial.println(F( "[ESP]無効な応答")); falseを返します。 } // HTTPヘッダーをスキップします// if(!espSerial.find(\ r \ n)){Serial.println(F( "[ESP] Bytes not found"));戻る; } //バイトをスキップ(http 1.1の場合)return true; i}  

ステップ4:木箱

フレームは、スーパーマーケットからのすべての電子機器と3つのハーブポットを保管するように計画されていました。すべてのコンポーネントのサイズを測定し、位置を構成しました。 4つの水分センサー、2つのポンプ、Arduino +シールド、4xリレーシールド、USBプラグ、およびいくつかのワイヤーがボックスに収まる必要があります。ブナ材で作られており、釉薬を追加せずに丈夫で長持ちします。

<図>

自作のジグソーテーブルでジグソーで円を切り出しました。植物の台紙は、ホットグルーで円の内側に接着されています。ボックスの側面は木製の接着剤(耐水性のD3)で接着されています。電子機器以外に、下部パネルの固定の横にネジや釘は使用しませんでした。

<図> <図> <図>

私はすべての回路、ワイヤー、水管を箱の中に入れ、センサーと追加の水タンク用の管を引き出しました。箱を閉める前に、電子機器を保護するために箱の中に水が溺れるのを防ぐために受け皿を追加しました。

<図> <図>

ステップ5:ウェブサイトAPI

APIとWebサイトは、phpでコード化されたjQuery、Bootstrap、X-editable(インラインajaxフォーム用)およびChart.js(湿度チャート用)に基づいています。ウェブサイトでは、Arduinoの設定(センサーピン、湿度チェック間隔、プラントごとのポンプ、ポンプVCCピン、ライトVCCピンなど)を定義し、現在の湿度+チャートを見つけることができます。

<図>

構成は、ArduinoのJSONによって提供されます。開始後、頻繁に、ハーブボックスは新しい設定をチェックします。 ArduinoでJSONを解析するために、ライブラリArduinoJsonを使用しました。ポーリング間隔には、StensTimerを使用しました。

ライブラリ:ArduinoJson |ライブラリ:StensTimer

ステップ6:Alexaの統合

このウェブサイトは、Alexa通信用のAPIを提供しています。これは、AlexaによるリクエストJSONを受信するハブとして機能し、Arduinoで使用されるカスタムJSONに変換します(例:ランプオン、灌漑プラント1、...)。 Arduinoは新しいアクションをポーリングして実行します。

<図>

音声リクエストはオン/オフだけではないため、Alexaスキルを実装しました。Alexaスマートホームは実装していません。 AWS LampdaはリクエストJSONを私のAPIに転送し、APIはインテントを解析します。

  var https =require( 'https'); exports.handler =(event、context、callback)=> {var postData =JSON.stringify(event); var options ={host: ''、path: ''、port:443、method: 'POST'、headers:{'Content-Type': 'application / json' 、 'Content-Length':postData.length、}}; //リクエストを設定しますvarpostRequest =https.request(options、function(res){res.setEncoding( 'utf8'); res.on( 'data'、function(chunk){console.log( 'Response:' +チャンク); // console.log(chunk); callback(null、JSON.parse(chunk));});}); //データを投稿しますpostRequest.write(postData); postRequest.end();};  

自分のスキルで使用したインテントの抜粋:

  • ReadHumidityIntent私の植物はどうですか
  • ReadHumidityIntent私の{plantName}はどうですか
  • IrrigatePlantIntent私の植物を灌漑します
  • IrrigatePlantIntent {plantName}を{durationSeconds}秒間灌漑します
  • SwitchIntentランプを切り替えます{switchState}
  • ReadIrrigateIntentどの植物に水が必要か
  • ReadLastIrrigationIntent私の{plantName}の最後の灌漑はいつでしたか

最後になりましたが、ドイツ語と英語で使用するためのロケールサポートを追加しました。

結果

その結果、私はスーパーマーケットのハーブポットを入れ、土壌に水管と水分センサーを、外部の水タンクに水管を入れるための木製の箱を持っています。 Alexaの統合により、次の文章を言うことができます:

  • "アレクサ、ハーブボックスに私の植物はどうですか "-応答:"プラント1は正常、プラント2は乾燥しています... "
  • "アレクサ、ハーブボックスにバジルを5秒間灌漑するように伝えます "-応答:"バジルを5秒間灌漑する "
  • "アレクサ、どの植物に灌漑が必要かをハーブボックスに聞いてください "-応答:"プラント1は乾燥しており、プラント3は乾燥しています... "
  • "アレクサ、最後の灌漑はいつだったかハーブボックスに聞いてください 私のバジル "-応答:"バジルの最後の灌漑は36時間前でした "
  • "アレクサ、ハーブボックスにランプをオンにするように伝えます "-応答:"植物成長ランプをオンに切り替えました "
<図>

Alexaに私の植物の湿度を尋ね、その後灌漑します(ドイツ語):

Alexaに植物成長ランプをオンにするように依頼する:

ビデオなしの結果を示すGIF:

<図>

<図>

予定されている機能

次の機能はまだ実装されていませんが、将来的に計画されています。

  • Arduinoソースコードの省電力モード
  • 家の中の他の植物の水分測定用にワイヤレス通信(2,4 GHz)を備えた外部Arduino Nanosを追加します(ボックスはWiFiのハブです)-バッテリーのみを使用します
  • APIを、ハーブボックスの複数のインスタンス、友人(および、興味がある場合は誰でも)用に拡張します。
  • ウェブサイトやAlexaを使用せずに、ボックスのランプを灌漑して切り替えるためのボタンを追加します
  • Alexa画像(スキルレスポンスのカード)

2018年3月23日更新

2つの新しいインテントを追加しました。そのうちの1つは、湿度を記録するだけの外部AdruinoNanosの計画された機能にとって重要です。

  • どの植物が乾燥しているか
  • 最後の灌漑はいつでしたか

コード

  • EcoActionBuffer.h
  • EcoActionBuffer.cpp
  • Plant.cpp
  • Plant.h
  • WhiteWalnut.ino
  • WhiteWalnutApi.cpp
  • WhiteWalnutApi.h
EcoActionBuffer.h Arduino
 #ifndef ECOACTIONBUFFER_H#define ECOACTIONBUFFER_H#include "Arduino.h" #include "StensTimer.h" struct EcoActionBuffer:public IStensTimerListener {long entryNo; intアクション; intピン;長期間; void timerCallback(Timer * timer); void switchPin(int pin、bool value); void readStack(); void process(); void toSerial(); void reset();}; #endif 
EcoActionBuffer.cpp Arduino
 #include "EcoActionBuffer.h" #include "StensTimer.h" #include "WhiteWalnutApi.h" #define ACTION_ECOACTION_READ 1#define ACTION_ECOACTION_HIGH 2#define ACTION_ECOACTION_LOW 3void EcoActionBuffer ::readStack(){reset(); WhiteWalnutApi ::receiveActionFromStack(* this); if(entryNo!=0){process(); // WhiteWalnutApi ::updateActionOnStack(* this); //パフォーマンスのために非アクティブ化}} void EcoActionBuffer ::process(){toSerial(); pinMode(pin、OUTPUT); digitalWrite(pin、HIGH); switch(action){case ACTION_ECOACTION_HIGH:switchPin(pin、true);壊す;ケースACTION_ECOACTION_LOW:switchPin(pin、false);壊す; } if(duration!=0){StensTimer ::getInstance()-> setTimer(this、-pin、duration); }} void EcoActionBuffer ::timerCallback(Timer * timer){switch(timer-> getAction()){case ACTION_ECOACTION_READ:readStack();壊す; } if(timer-> getAction()<0){switchPin(abs(timer-> getAction())、false); }} void EcoActionBuffer ::switchPin(int pin、bool value){switch(value){case true:digitalWrite(pin、LOW);壊す; falseの場合:digitalWrite(pin、HIGH);壊す; } WhiteWalnutApi ::switchPin(pin、value);} void EcoActionBuffer ::reset(){entryNo =0;アクション=0;ピン=0; duration =0;} void EcoActionBuffer ::toSerial(){Serial.print(entryNo); Serial.print(F( "-アクション:")); Serial.print(アクション); Serial.print(F( "、ピン:")); Serial.print(pin); Serial.print(F( "、期間:")); Serial.print(duration); Serial.println();} 
Plant.cpp Arduino
 #include "Plant.h" #include "StensTimer.h" #include "WhiteWalnutApi.h" #define ACTION_PLANT_CHECKHUMIDITY 2#define PIN_HUMIDITY_VCC 12void Plant ::checkHumidity(){if(humidityDataPin!=0){Serial.print (コード); Serial.print(F( "-湿度をチェック...")); digitalWrite(PIN_HUMIDITY_VCC、HIGH); delay(200); // TODOint湿度=1023-analogRead(humidityDataPin); digitalWrite(PIN_HUMIDITY_VCC、LOW); Serial.println(湿度); WhiteWalnutApi ::sendHumidity(* this、湿度); if(humidityCheckInterval ==0)humidityCheckInterval =60000; StensTimer ::getInstance()-> setTimer(this、ACTION_PLANT_CHECKHUMIDITY、himidatureCheckInterval); } else StensTimer ::getInstance()-> setTimer(this、ACTION_PLANT_CHECKHUMIDITY、60000);} void Plant ::updateApi(){WhiteWalnutApi ::updatePlant(* this); // WhiteWalnutApi ::sendHeartbeat(* this); //パフォーマンスのために非アクティブ化pinMode(PIN_HUMIDITY_VCC、OUTPUT); toSerial();} void Plant ::timerCallback(Timer * timer){switch(timer-> getAction()){case ACTION_PLANT_CHECKHUMIDITY:checkHumidity();壊す; }} void Plant ::toSerial(){Serial.print(code); Serial.print(F( "-DataPin:")); Serial.print(humidityDataPin); Serial.print(F( "、Interval:")); Serial.print(humidityCheckInterval); Serial.println();} 
Plant.h Arduino
 #ifndef PLANT_H#define PLANT_H#include "Arduino.h" #include "StensTimer.h" struct Plant:public IStensTimerListener {const char * code; intHydriumDataPin;長いhumidityCheckInterval; void checkHumidity(); void timerCallback(Timer * timer); void toSerial(); void updateApi();}; #endif 
WhiteWalnut.ino Arduino
 #include "EcoActionBuffer.h" #include "Plant.h" #include "StensTimer.h" #include "WhiteWalnutApi.h" struct TimerHelper:public IStensTimerListener {public:void updateApi(); void timerCallback(Timer * timer);}; StensTimer * stensTimer; TimerHelper apiTimer; Plant leftPlant; Plant centerPlant; Plant rightPlant; Plant externalPlant; EcoActionBuffer actionBuffer; #define ACTION_PLANT_UPDATE 1#define ACTION_ECOACTION_READ 1void setup(){Serial.begin(9; while(!Serial); stensTimer =StensTimer ::getInstance(); leftPlant.code ="LEFT"; centerPlant.code ="CENTER"; rightPlant.code ="RIGHT"; externalPlant.code ="EXTERNAL"; while(!WhiteWalnutApi ::connectToWiFi())delay(2000); WhiteWalnutApi ::switchPin(0、false); apiTimer.updateApi(); leftPlant.checkHumidity(); centerPlant.checkHumidity(); rightPlant.checkHumidity(); externalPlant.checkHumidity(); actionBuffer.readStack(); StensTimer ::getInstance()-> setInterval(&apiTimer、ACTION_PLANT_UPDATE、60000); StensTimer ::getInstance()-> setInterval(&actionBuffer、ACTION_ECOACTION_READ、1000);} void loop(){stensTimer-> run();} void TimerHelper ::updateApi(){leftPlant.updateApi(); centerPlant.updateApi(); rightPlant.updateApi(); externalPlant.updateApi();} void TimerHelper ::timerCallback(Timer * timer){switch(timer-> getAction()){case ACTION_PLANT_UPDATE:updateApi();壊す; }} 
WhiteWalnutApi.cpp Arduino
WiFiとAPIの設定を追加する必要があります
 #include "Arduino.h" #include "ArduinoJson.h" #include "EcoActionBuffer.h" #include "MemoryFree.h" #include "Plant.h" #include " SoftwareSerial.h "#include" WhiteWalnutApi.h "SoftwareSerial espSerial(3、2); const char * ssid ="  "; const char * pass ="  "; const char * API_SERVER =""; const char * API_PLANT =""; const char * API_ACTION =""; char * findOK ="OK"; char * findRY ="ready"; char * findGT =">"; char * findDP =":"; char * findHD ="\ r \ n \ r \ n"; char * findBT ="\ r \ n"; bool WhiteWalnutApi ::connectToWiFi(){espSerial.begin(9600); espSerial.setTimeout(3000); while(espSerial.available())Serial.write(espSerial.read()); Serial.println(F( "[ESP] WiFiに接続しています")); espSerial.println(F( "AT + CIPSTATUS =2")); if(!espSerial.find(findOK)){espSerial.setTimeout(10000); Serial.println(F( "[ESP]リセットモジュール")); espSerial.println(F( "AT + RST")); if(!espSerial.find(findRY)){Serial.println(F( "[ESP]リセットに失敗しました")); falseを返します。 } Serial.println(F( "[ESP] Set CWMode")); espSerial.println(F( "AT + CWMODE =1")); if(!espSerial.find(findOK)){Serial.println(F( "[ESP]モードに失敗しました")); falseを返します。 } Serial.println(F( "[ESP]ルーターに接続")); espSerial.print(F( "AT + CWJAP =\" ")); espSerial.print(ssid); espSerial.print(F(" \ "、\" ")); espSerial.print(pass); espSerial.println ( "\" "); if(!espSerial.find(findOK)){Serial.println(F( "[ESP] WiFi接続に失敗しました")); falseを返します。 }} espSerial.setTimeout(3000); Serial.println(F( "[ESP] WiFiが接続されています")); return true;} void WhiteWalnutApi ::updatePlant(Plant&plant){String site =String(API_PLANT)+ "?action =get&code =" + String(plant.code); while(!httpRequest(site))connectToWiFi(); JsonObject&root =parseJson(); if(root.success()){plant.humidityDataPin =root ["dataPin"]。as (); plant.humidityCheckInterval =atol(root ["interval"]。as ()); }} void WhiteWalnutApi ::sendHumidity(Plant&plant、int hybrid){String site =String(API_PLANT)+ "?action =humidity&code =" + String(plant.code)+ "&humidity =" + String(humidity); while(!httpRequest(site))connectToWiFi(); // TODO:REMOVE RETURN} void WhiteWalnutApi ::sendHeartbeat(Plant&plant){String site =String(API_PLANT)+ "?action =heartbeat&code =" + String(plant.code); while(!httpRequest(site))connectToWiFi();} void WhiteWalnutApi ::receiveActionFromStack(EcoActionBuffer&actionBuffer){while(!httpRequest(String(API_ACTION)))connectToWiFi(); JsonObject&root =parseJson(); if(root.success()){actionBuffer.entryNo =atol(root ["entryNo"]。as ()); actionBuffer.action =root ["actionEnum"]。as (); actionBuffer.pin =root ["pin"]。as (); actionBuffer.duration =atol(root ["value"]。as ()); }} void WhiteWalnutApi ::updateActionOnStack(EcoActionBuffer&actionBuffer){String site =String(API_ACTION)+ "?action =processed&entryNo =" + String(actionBuffer.entryNo); while(!httpRequest(site))connectToWiFi();} void WhiteWalnutApi ::switchPin(int pin、bool value){String site =String(API_ACTION)+ "?action =switch&pin =" + String(pin)+ "&value ="+ String(value); while(!httpRequest(site))connectToWiFi();} bool WhiteWalnutApi ::httpRequest(String site){// char * cmd; // sprintf(cmd、 "GET%s HTTP / 1.0 \ r \ nHost:%s \ r \ nConnection:close"、site、API_SERVER); / *文字列cmd =""; cmd + ="GET" + site + "HTTP / 1.0 \ r \ n"; cmd + ="ホスト:" + String(API_SERVER)+ "\ r \ n"; cmd + ="接続:閉じる"; int cmdLength =cmd.length()+ 4; Serial.println(cmd); * / int cmdLength =44 + site.length()+ strlen(API_SERVER); // Serial.print(F( "[MEMORY]")); // Serial.print(freeMemory()); // Serial.print(F( "-")); // Serial.println(site); //->外部espSerial.print(F( "AT + CIPSTART =\" TCP \ "、\" ")); espSerial.print(API_SERVER); espSerial.println(F(" \ "、80")の場合は785 ); if(!espSerial.find(findOK)){Serial.println(F( "[ESP] TCP接続エラー")); falseを返します。 } espSerial.print(F( "AT + CIPSEND =")); espSerial.println(cmdLength); // espSerial.println(strlen(cmd)); if(!espSerial.find(findGT)){Serial.println(F( "[ESP] Send State Error")); falseを返します。 } espSerial.print(F( "GET")); espSerial.print(site); espSerial.print(F( "HTTP / 1.0 \ r \ n")); espSerial.print(F( "ホスト:")); espSerial.print(API_SERVER); espSerial.print(F( "\ r \ n")); espSerial.print(F( "接続:閉じる\ r \ n")); espSerial.println(); // while(espSerial.available())Serial.println(espSerial.readString());戻る; if(!espSerial.find(findDP)){Serial.println(F( "Bytes not send")); espSerial.print(F( "AT + CIPCLOSE")); falseを返します。 } char status [32] ={0}; espSerial.readBytesUntil( '\ r'、status、sizeof(status)); if(strcmp(status、 "HTTP / 1.1 200 OK")!=0){Serial.print(F( "[ESP]予期しない応答:")); Serial.println(ステータス); falseを返します。 } // HTTPステータスを確認するif(!espSerial.find(findHD)){Serial.println(F( "[ESP] Invalid response")); falseを返します。 } // HTTPヘッダーをスキップします//if(!espSerial.find(findBT)){Serial.println(F( "[ESP] Bytes not found"));戻る; } //バイトをスキップ(http 1.1の場合)return true;} JsonObject&WhiteWalnutApi ::parseJson(){const size_t capacity =JSON_OBJECT_SIZE(3)+ JSON_ARRAY_SIZE(2)+ 60; DynamicJsonBuffer jsonBuffer(capacity); JsonObject&root =jsonBuffer.parseObject(espSerial); if(!root.success())Serial.println(F( "解析に失敗しました!"));ルートを返す;} 
WhiteWalnutApi.h Arduino
 #ifndef WHITEWALNUTAPI_H#define WHITEWALNUTAPI_H#include "Arduino.h" #include "ArduinoJson.h" #include "EcoActionBuffer.h" #include "Plant.h" class WhiteWalnutApi {public:static bool connectToWiFi(); static void updatePlant(Plant&plant); static void sendHumidity(植物と植物、int湿度); static void sendHeartbeat(Plant&plant); static void receiveActionFromStack(EcoActionBuffer&actionBuffer); static void updateActionOnStack(EcoActionBuffer&actionBuffer); static void switchPin(int pin、bool value);プライベート:static bool httpRequest(String site); static JsonObject&parseJson();}; #endif 

回路図

通信とインターフェースに関するチャート 応答を含め、Alexaに問い合わせることができるすべての実装済みインテント。
(多言語) alexajson解析の開始ステップに関心がある場合。

製造プロセス

  1. Web操作のDMXコントローラー
  2. Arduino Spybot
  3. Arduino警報システム:SERENA
  4. Arduino + ESPウェザーボックス
  5. 地下室/クロールスペース換気システム
  6. ArduinoとGoogleスプレッドシートに基づく出席システム
  7. BLUE_P:ワイヤレスArduinoプログラミングシールド
  8. Arduinoベースの衝突検出警告システム
  9. ArduinoNano用TFTシールド-開始
  10. ArduinoシールドNCS314ニキシー管時計IN-14
  11. ArduinoGrowBoxコントローラー