2019年10月6日日曜日

ArduinoとESP-WROOM-02のWiFi WebサーバーでLEDを操作してみた

前回は、ArduinoからUARTでESP-WROOM-02をコントロールしてWebサーバーを起動させて、ブラウザでのアクセス成功まで。

今回は、更にブラウザからArduinoのLEDを制御してみたいと思います。

まずは、どの様にデータを受け渡しするかを考えます。
手始めに考えてみたのは、アドレスに要素を付加する方法。
簡単に書くと以下の様にアドレスを指定する。

  • http://XXX.XXX.XXX.XXX:80/0 // 消灯
  • http://XXX.XXX.XXX.XXX:80/1 // 点灯
一方、サーバー側で判断するのは、
+IPD,0,XXX:GET / HTTP/1.1
Host: XXX.XXX.XXX.XXX
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_XX_X) AppleWebKit/XXX.XX (KHTML, like Gecko) Chrome/XX.X.XXXX.XXX Safari/XXX.XX
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate
Accept-Language: ja,en;q=0.9,und;q=0.8
の赤枠で囲んだ赤太字の箇所。
アドレスの指定によって下記の様に変化する。

  • +IPD,0,XXX:GET /0 HTTP/1.1 // 消灯
  • +IPD,0,XXX:GET /1 HTTP/1.1 // 点灯
以上から得られるのは、":GET /"の位置情報を取得して、7文字目の値を参照すれば良いのでは?って事。 で、該当箇所のみスケッチを書いてみる。
 if (mySerial.available()) {
  String ret = mySerial.readString();
  if ( ret.indexOf("IPD") > 0 ) {
   int pos = ret.indexOf(":GET /") + 6;
   int led = ret.charAt(pos);

   ~ ここに"led"による条件分岐処理を記述 ~

  }
 }
変数"led"に格納された値が取得値。

点灯させるためのスケッチも確認しておく。
まぁ、Blinkのスケッチ例のパクリなんだけど。
void setup() {
	pinMode(LED_BUILTIN, OUTPUT);					// LED(GPIO13)の設定
}

void loop() {
	digitalWrite(LED_BUILTIN, led);
}
"LED_BUILTIN"は、Arduinoの各機種でオンボードのLEDに割り当てられているGPIOを指します。

と、まぁ色々考えたものの、点/消灯だけであれば"digitalRead(LED_BUILTIN)"を参照するだけでも問題なさそうなので、前回最後のスクリプトに以下の箇所を追加、修正するだけに留めています。
#include <SoftwareSerial.h>

String ret, ip_add;

SoftwareSerial mySerial(10, 11);   // RX, TX

void setup() {

	Serial.begin(9600);			// ハードウェアシリアルポートのデータレートを設定する
	mySerial.begin(9600);		// ソフトウェアシリアルポートのデータレートを設定する

	pinMode(LED_BUILTIN, OUTPUT);					// LED(GPIO13)の設定

	mySerial.write("AT+CIPMUX=1\r\n");				// サーバーを複数接続に設定
	ret = mySerial.readString();
	ret.replace("\r\n\r\n", "\r\n");
	Serial.println(ret);
	mySerial.write("AT+CIPSERVERMAXCONN=1\r\n");	// 複数接続の最大数を設定
	ret = mySerial.readString();
	ret.replace("\r\n\r\n", "\r\n");
	Serial.println(ret);
	mySerial.write("AT+CIPSERVER=1,80\r\n");		// サーバを起動
	ret = mySerial.readString();
	ret.replace("\r\n\r\n", "\r\n");
	Serial.println(ret);

	mySerial.write("AT+CIFSR\r\n");	// ESP-WROOM-02のIPアドレス取得
	ret = mySerial.readString();
	int first = ret.indexOf('"')+1;
	int last  = ret.indexOf('"', first+1);
	ip_add = "http://"+ret.substring(first, last)+":80";
	Serial.println(ip_add);
}

void loop() {
	if (mySerial.available()) {
		ret = mySerial.readString();
		if ( ret.indexOf("IPD") > 0 ) {
			String btn = "ON";
			boolean led = !digitalRead(LED_BUILTIN);
			digitalWrite(LED_BUILTIN, led);
			if ( led ) {
				btn = "OFF";
			}
			String html_code = "<button type=\"button\" ";
			html_code += "onClick=\"location.href=\'";
			html_code += ip_add+"\'\"><H1>"+btn+"</H1></button>";

			mySerial.write("AT+CIPSEND=0,");		// 指定された長さのデータを送信
			mySerial.println(html_code.length());
			ret = mySerial.readString();
			ret.replace("\r\n\r\n", "\r\n");
			Serial.println(ret);
			mySerial.println(html_code);			// HTML書式のデータを指定
			ret = mySerial.readString();
			ret.replace("\r\n\r\n", "\r\n");
			Serial.println(ret);
			mySerial.write("AT+CIPCLOSE=0\r\n");	// 接続を閉じる
			ret = mySerial.readString();
			ret.replace("\r\n\r\n", "\r\n");
			Serial.println(ret);
		}
	}
}
実行させると、ブラウザには下の様に"ON"ボタンが表示される。
ボタンを押すとArduinoのLEDが点灯し、
ブラウザのボタン表記が"OFF"へと変化する。
この後"OFF"ボタンを押せばLEDは消灯し、ブラウザのボタン表記が"ON"に戻る。
以降は、ボタンを押すたびに点灯、消灯が繰り返される。

以上で、ArduinoからESP-WROOM-02のWiFi機能を使用してみる検証は終了。
例として揚げているスケッチは、Stringを多用しているのでメモリを無駄使いしているし、文字列操作を行うためにString変換も行なっているので処理全般重くなっていると思います。
実際に使用する場合は、その辺りを踏まえて記述しないと使い物にならないでしょう。

あえて80MHzで動かせるESP-WROOM-02を16MhzのArduinoからWiFIの機能だけ使用してみるのも案外勉強になりました。

0 件のコメント:

コメントを投稿