7-2-1.Scratch3.0用ESP32-DevKitC環境構築 インターネットなし
ESP32-DevKitC環境構築
Scratch3.0用にESP32-DevKitC環境構築します。
本ページで利用するスケッチはESP32-DevKitCがインターネットに接続できない環境でも利用できます。
ArduinoIDE環境構築
「ESP32-DevKitC」へスケッチ(プログラム)を書き込みにはArduinoIDEを利用します。
環境が準備できていない方はこちらを参照し構築して下さい。
また、必要なライブラリはこちらになりますので構築できていない方がインストールして下さい。
回路と配線
電子回路と配線図は全センサーが利用できるよう5-4「全センサー実装」を利用します。
【ESP32-DevKitCの入出力端子はこちらを参照下さい】
スケッチ(制御ソフトウェア)
Scrachと接続するための制御ソフトウェアは以下の2つとなります。
(1)Scratch3Remocon.ino
(2)irRecvSend.ino
こちら[2019.7.27版]からダウンロードして下さい。
(1)Scratch3Remocon.ino
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
// IoT本格学習キット スマートリモコン // 7-2. Scratch3用プログラム(インターネット接続なし) // ①ライブラリを読み込み #include <WiFi.h> #include <DHT.h> #include <FS.h> #include <SPIFFS.h> #include <ESPAsyncWebServer.h> // ####################### ②Wi-Fi設定(環境設定) ####################### const char *ssid = "##### SSID #####"; const char *password = "### PASSWORD ###"; IPAddress ip(192, 168, 1, 123); // IPアドレス(本機が利用するIP) IPAddress gateway(192, 168, 1, 1); // デフォルトゲートウェイ IPAddress subnet(255, 255, 255, 0); // サブネットマスク // ################################################################### // ③ピン配置 const byte LED_PIN = 22; // LED緑 const byte IR_R_PIN = 36; // リモコン受信 const byte IR_S_PIN = 23; // リモコン送信 const byte LIGH_SNR = 39; // 照度センサ(A18) const byte TEMP_SNR = 21; // 温・湿度センサ // ④グローバル変数定義 AsyncWebServer server(80); // Port80番 unsigned short irData[1500]; bool ledFlag = true; // LED制御フラグ void setup(void) { // ⑤Serial設定 Serial.begin(115200); Serial.println ( ); // ⑤SPIFFS開始 SPIFFS.begin(); // ⑥LED設定 pinMode ( LED_PIN, OUTPUT ); pinMode ( IR_R_PIN, INPUT ); pinMode ( IR_S_PIN, OUTPUT ); pinMode ( LIGH_SNR, INPUT ); // ⑦無線Wi-Fi接続 WiFi.config( ip, gateway, subnet ); WiFi.begin ( ssid, password ); // ⑧Wi-Fi接続処理(接続するまで無限ループ) while ( WiFi.status() != WL_CONNECTED ) { // ⑨LEDを1秒毎に点滅する ledFlag = !ledFlag; digitalWrite(LED_PIN, ledFlag); // ⑩1秒間Wait delay ( 1000 ); Serial.print ( "." ); } // ⑪Wi-Fi接続できたのでシリアルモニターにIPアドレス表示 Serial.print ( "Wi-Fi Connected! IP address: " ); Serial.println ( WiFi.localIP() ); // ⑫LED点灯(Wi-Fi接続状態) digitalWrite ( LED_PIN, true ); // ⑬WebServerアクセス処理[LED制御] server.on("/led", HTTP_GET, [](AsyncWebServerRequest *request){ Serial.println ( "webServer led" ); String setLedVal = request->getParam("o")->value(); if (setLedVal == "ON") { digitalWrite ( LED_PIN, true ); } else { digitalWrite ( LED_PIN, false ); } // 応答処理 request->send(200, "text/plain", "OK"); }); // ⑭WebServerアクセス処理[センサー情報更新] server.on("/update", HTTP_GET, [](AsyncWebServerRequest *request){ Serial.println ( "webServer update" ); // リモコン送信 String sendMsg = updateSensor(); // 応答処理 request->send(200, "application/json", sendMsg); }); // ⑮WebServerアクセス処理[リモコン送信] server.on("/send", HTTP_GET, [](AsyncWebServerRequest *request){ Serial.println ( "webServer send:" + request->getParam("n")->value() ); // リモコン送信 String replyResult = "NG"; if ( contRemocon(request->getParam("n")->value()) ){ replyResult = "OK"; } // 応答処理 request->send(200, "text/plain", replyResult); }); // ⑯WebServerアクセス処理[リモコン受信] server.on("/recv", HTTP_GET, [](AsyncWebServerRequest *request){ Serial.println ( "webServer recv:" + request->getParam("n")->value() ); // リモコン受信設定 String replyResult = "NG"; if ( setRemocon(request->getParam("n")->value()) ){ replyResult = "OK"; } // 応答処理 Serial.println ( "send recv response." ); request->send(200, "text/plain", replyResult); }); // ⑰WebServerヘッダ設定及び起動 DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", "*"); server.begin(); Serial.println ( "Web server started" ); } void loop(void){ } // ⑱センサー情報を更新し送信データ作成 String updateSensor(){ DHT dht(TEMP_SNR, DHT11); float g_temperature = dht.readTemperature(); float g_humidity = dht.readHumidity(); unsigned short g_light = analogRead(LIGH_SNR) * 100 / 4095; String messageS = "{\"t\":" + String(int(g_temperature)) + ",\"h\":" + String(int(g_humidity)) + ",\"l\":" + String(g_light) + "}"; return messageS; } |
(2)irRecvSend.ino
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
// ①赤外線受信(信号受信 or 30秒間を処理) bool setRemocon (String setNumStr) { // ②利用する変数を宣言 unsigned short irCount = 0; // HIGH,LOWの信号数 uint32_t lastt = 0; // 1つ前の経過時間を保持 uint32_t deltt = 0; // 1つ前の経過時間を保持 uint32_t sMilli; // 本処理の開始時間 uint32_t wMilli; // 赤外線の待ち開始時間 uint32_t sMicro; // 処理の開始時間 uint32_t cMicro; // 現在時間 bool rState = 0; // 赤外線受信モジュールの状態 0:LOW,1:HIGH // ③現在の時間をミリ秒で取得 sMilli = millis(); // ④特定条件(信号受信 or 30秒経過)するまで無限ループ while(1) { // ⑤Ir受信を待つ開始時間を取得 wMilli = millis(); // ⑥反転信号の受信待ち while (digitalRead(IR_R_PIN) == rState) { // ⑦待ち始めて0.5秒以上経過したら if (millis() - wMilli > 500) { // ⑧待ち始めて0.5秒以上経過したら if ( irCount > 10 ) { Serial.println(""); Serial.println("recvOK!"); delay(1); // ⑨ボタン名をEEPROMへ、リモコンデータをファイルへ保存 if (saveIr( (irCount - 1), setNumStr )) { // ⑩正常に終了 Serial.println("setRemocon OK"); return true; // ⑪正常に完了 } else { // ⑫信号受信に失敗 Serial.println("setRemocon NG"); return false; // 失敗終了 } } // ⑬0,1信号が10個以上ない場合は雑音のため再度ゼロから受信 irCount = 0; } // ⑭処理が15秒以上経過したらタイムアウト if ( millis() - sMilli > 15000 ) { Serial.println("setRemocon T.O."); return false; // ⑮15秒経過で失敗終了(受信なし) } } // ⑯信号受信開始時の現在の時間や経過時間を取得 if ( irCount == 0 ) { sMicro = micros(); lastt = 0; irCount++; Serial.print("ir:"); // ⑰信号受信処理開始後の処理(irCountが1以上) } else { // ⑱赤外線受信部の状態変化が最後に変化した時間からの経過時間を計算 cMicro = micros(); deltt = ( (cMicro - sMicro)/ 10 ) - lastt; irData[(irCount - 1 )] = deltt; // ⑲次回経過時間計算のため最後に変化した経過時間を保存 lastt = lastt + deltt; irCount++; Serial.print( deltt ); Serial.print(","); } // ⑳次回While内で状態変化を検知する値を変更 rState = !rState; } } // ㉑ボタン名をEEPROMへ、リモコンデータをファイルへ保存 bool saveIr(unsigned short irLength, String setNumStr){ // ㉒ボタン番号チェック if (setNumStr == "") { return false; } // ㉓リモコン信号を保存するためファイル名を作成(ファイル名はボタン番号) String t_file = "/" + setNumStr; Serial.println( "recvFile:" + t_file); // ㉔ファイルを書き込みモードで開く File fw = SPIFFS.open(t_file.c_str(), "w"); // ㉕リモコン信号の長さを最初に書き込み(最初の行) fw.println( String( irLength, HEX ) ); // ㉖リモコン信号の0,1の時間長さを書き込み(2行目以降) for (int i = 0; i < irLength; i++) { fw.println( String( irData[i], HEX ) ); } // ㉗書き込みが完了したのでファイルを閉じる fw.close(); // ㉘正常に処理が完了したのでtrueを返す return true; } // ㉙赤外線送信処理 bool contRemocon (String setNumStr) { // 送信番号保存 // ㉚変数宣言 unsigned short irCount = 0; // HIGH,LOWの信号数 unsigned long l_now = 0; // 送信開始時間を保持 unsigned long sndt = 0; // 送信開始からの経過時間 // ㉛リモコン信号をファイルから取得(ファイル名はボタン番号) String t_file = "/" + setNumStr; Serial.println( "sendFile:" + t_file); // ㉜ファイルを開く File fr = SPIFFS.open(t_file.c_str(), "r"); // ㉝ファイルを開く if(!fr || fr.isDirectory()){ Serial.println("FileOpen NG"); return false; } // ㉞最初の1行のみ読み出し信号長さ(0,1の数)を取得 String snum = fr.readStringUntil('\n'); // ㉟1行目の文字列を数値型に変換 irCount = strtol(snum.c_str(), NULL, 16); Serial.print( "sendData:" + String(irCount)); // ㊱一旦ファイルから変数irDataに読み出し保存 for (int i = 0; i < irCount; i++) { snum = fr.readStringUntil('\n'); irData[i] = strtol(snum.c_str(), NULL, 16); } fr.close(); // ㊲送信開始時間を取得 l_now = micros(); // ㊳0,1の信号回数分をFor文でループ for (int i = 0; i < irCount; i++) { // ㊴送信開始からの信号終了時間を計算 sndt += irData[i]; do { // ㊵iが偶数なら赤外線ON、奇数ならOFFのまま // キャリア周波数38kHz(約26μSec周期の半分)でON時間で送信 digitalWrite(IR_S_PIN, !(i&1)); microWait(13); // ㊶キャリア周波数38kHz(約26μSec周期の半分)でOFF時間で送信 digitalWrite(IR_S_PIN, 0); microWait(13); // ㊷送信開始からの信号終了時間が超えるまでループ } while (long(l_now + (sndt * 10) - micros()) > 0); } // ㊸正常に終了したので、trueを返答 Serial.println(":End"); return true; } // ㊹マイクロ秒単位で待つ void microWait(signed long waitTime) { unsigned long waitStartMicros = micros(); while (micros() - waitStartMicros < waitTime) {}; } |
環境設定
Scratch3Remocon.inoファイル内には以下の設定を実施しESP32-DevKitCにスケッチを書き込みして下さい。
(1)SSIDとパスワードの設定
以下の行を書き換えて自宅の接続するSSIDとパスワードを設定して下さい。
1 2 |
const char *ssid = "##### SSID #####"; const char *password = "### PASSWORD ###"; |
(2)工作キットのIPアドレス
以下の行を書き換えて工作キットのIPアドレスを設定して下さい。
1 2 3 |
IPAddress ip(192, 168, 1, 123); // IPアドレス(本機が利用するIP) IPAddress gateway(192, 168, 1, 1); // デフォルトゲートウェイ IPAddress subnet(255, 255, 255, 0); // サブネットマスク |
【本IPアドレスをScratch3.0で設定する必要があります。】
《IPアドレス設定時の注意事項》
(1)IPアドレスはインターネット上の住所となるため、他キットと重複しないように値を付与してください。
(123を他の端末やキットで利用している場合は124など他の番号をつけてください)
(2)「192.168.1.」の部分は接続するネットワークアドレスと同じ値に設定してください。
(同じネットワークに接続されている端末が192.168.0.xの場合は192.168.0.123など「192.168.0.」の部分は同じものにしてください)