« 2015年6月 | トップページ | 2015年8月 »

2015年7月

2015年7月24日 (金)

Arduino の ESP8266をwebサーバーにしてみよう

2017/03/02 追記

清水様より

'onRoot' was not declared in this scope
by Arduino 1.8.1 + http://arduino.esp8266.com/stable/package_esp8266com_index.json

とのご指摘が有りました。

確かに本記事の前半のコードでエラーがでます。
setup()の最後のほうに

  server.on("/",onRoot);

が記述してあり、onRoot()がありません。setu()内のserver.on("/",onRoot);を削除してください。

修正及び後半のコードが Arduino 1.8.1 + http://arduino.esp8266.com/stable/package_esp8266com_index.json
にてj動作することを確認しました。

以上、2017/03/02 追記 終わり

Arduino の ESP8266をwebサーバーにしてみよう

ESP8266で最低限のWebサーバーを構築してみる。

昨日の「ESP8266でアクセスポイントに接続してみる」に以下の追加します。

・インクルードファイルの追加(#include <ESP8266WiFi.h>の下に)2行追加

#include <WiFiClient.h>
#include <ESP8266WebServer.h>

・Webサーバーの生成。インクルードの下に追加。

ESP8266WebServer server(80);

・サーバーを起動する。setup()の最後に次の1行追加

server.begin();

・クライアントからの接続処理を呼び出を処理するため loop() の中身を次の1行のみにする。

server.handleClient();

以上4行の追加と loop() 内の入れ替えで完了。
全てのコードは以下のようになる。

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>

ESP8266WebServer server(80);

void setup() {
  Serial.begin(115200);
  delay(100);
  Serial.println("");

  pinMode(5, OUTPUT);  // オリジナルは13だがテスト環境の都合で5に変えてある。
  WiFi.mode(WIFI_STA);
  WiFi.begin("ssid","psddword");
  while(WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print(WiFi.localIP());

//  server.on("/",onRoot);
  server.begin();
}

void loop() {
  server.handleClient();
}

マイコンボードへの書き込みが完了したら、シリアルモニタを起動し

....
192.168.0.2

シリアルモニタに表示されたIPアドレス http://192.168.0.2/ にアクセスするとFireFoxでは

Not found: /

と表示される。ESP8266の電源OFFの状態ですタイムアウトまで数十秒かかる「ページ読み込みエラー」になる。ESP8266のWebサーバーが動いている状態ではすぐに「Not found:」が表示される。表示はブラウザによって異なると思います。

次に、プログラムで "Hello" と応答するコードを追加してみます

"Hello" を返す関数を setup() の上に追加。

void onRoot() {
  server.send(200,"text/plain","Hello");
}

onRoot() を登録するため server.begin() の上に追加

  server.on("/",onRoot);

全コードは以下の通り

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>

ESP8266WebServer server(80);

void onRoot() {
  server.send(200,"text/plain","Hello");
}
void setup() {
  Serial.begin(115200);
  delay(100);
  Serial.println("");

  pinMode(5, OUTPUT);  // オリジナルは13だがテスト環境の都合で5に変えてある。
  WiFi.mode(WIFI_STA);
  WiFi.begin("ssid","psddword");
  while(WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print(WiFi.localIP());

  server.on("/",onRoot);
  server.begin();
}

void loop() {
  server.handleClient();
}

以上で http://192.168.0.2/ にアクセスすると

Hello

と表示される。これでメッセージを返すWebサーバーになる。

テキストでなく HTML を返す Web サーバーにするには onRoot() を以下のように変えます。

void onRoot() {
  String msg = "<html><head><title>ESP8266WebSerber</title></head><body><h1>Hello</h1></body></html>";
  server.send(200,"text/html",msg);
}

これで大きな文字で "Hello" が表示されます。

2015年7月23日 (木)

ArduinoのESP8266でアクセスポイントに接続してみる

Arduino の ESP8266 でアクセスポイントに接続してみる

昨日作成のLED点滅スケッチでアクセスポイント(無線LANルータ)に接続してみる。

接続はsetup()の最後に次の5行を追加する。

  WiFi.begin("ssid","password");
  while(WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

"ssid"と"password"には接続するアクセスポイントのssidとパスワードに書き換える。

接続できたらアクセスポイントから指定されたIPアドレスを表示する

  Serial.print(WiFi.localIP());

マイコンボードへの書き込みが完了したらシリアルモニタを起動すると

....
192.168.0.7

と表示されたら接続完了している。
このプログラムでは接続するだけでデータを送ったり受けたりするコードはないため何もできません。

Serialのイニシャライズ等を含めてsetup()は以下のようになります。

void setup() {
  Serial.begin(115200);
  delay(100);
  Serial.println("");

  pinMode(5, OUTPUT);  // オリジナルは13だがテスト環境の都合で5に変えてある。

  WiFi.mode(WIFI_STA);
  WiFi.begin("ssid","password");
  while(WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print(WiFi.localIP());
}

2015年7月22日 (水)

ESP8266 でアクセスポイント機能を無効にする

ESP8266 でアクセスポイント機能を無効にする

7月5日に「ESP8266でアクセスポイント機能が勝手に有効になる」と言うエントリを書きました。
もちろんアクセスポイント機能はWiFI.mode()APIにより有効・無効が切り替え出来ます。

そこで次のような実験を行う
・WiFiAccessPointスケッチを実行しアクセスポイントを有効しアクセスポイントを確認する。
・WiFiとは関係ないBlinkを実行してアクセスポイントが有効な事を確認する。
・blinkにWiFi.mode()でアクセスポイントを無効(ステーションモードにする)にしてアクセスポイントを確認する。

WiFiAccessPointスケッチ実行
タブレットから「ESPap」というアクセスポイントが確認出来た。

Blinkスケッチ実行
タブレットから「ESPap」というアクセスポイントが確認出来た。
電源off/onしても「ESPap」は確認できた。

Blinkにアクセスポイント無効コードを追加して実行
次の2行をプログラムの先頭とsetup()内に追加

#include <ESP8266WiFi.h>
WiFi.mode(WIFI_STA);

「ESPap」アクセスポイントが消えた。

WiFi.mode(m)のmにはWIFI_AP, WIFI_STAとWIFI_AP_STAが指定できる。

解ったこと
・アクセスポイントの設定は電源Offでも記憶される
・アクセスポイント有効の状態でWiFiに関係ないプログラムを実行してもアクセスポイントは有効のまま。
・WiFiに関係ないプログラムでもWiFi.mode(WIFI_STA)を実行してアクセスポイント無効にする必要がある。

ステーションモードのみにした blink のコード

#include <ESP8266WiFi.h>

void setup() {
  pinMode(5, OUTPUT);  // オリジナルは13だがテスト環境の都合で5に変えてある。
  WiFi.mode(WIFI_STA);
}

void loop() {
  digitalWrite(5, HIGH);
  delay(1000);
  digitalWrite(5, LOW);
  delay(1000);
}

2015年7月20日 (月)

ESP8266のTOUTピンの入力電圧とADC値

昨日TOUTの電圧測定にArduinoスケッチから直接システムらしきファンクションを呼び出す方法を書いた。その方法で電圧測定すると誤差があるように感じたので.1ボルトステップで測定してみた。

入力電圧計算値DAC値誤差
0 0 0 0
0.1006 103 95 -8.44%
0.2007 205 203 -1.24%
0.3012 308 307 -0.46%
0.398 407 410 0.59%
0.502 514 517 0.57%
0.601 615 618 0.41%
0.701 717 724 0.85%
0.798 817 826 1.07%
0.902 923 935 1.21%
0.992 1015 1023 0.70%
0.994 1017 1024 0.60%
  1. 入力電圧はマルチメータによる値
  2. 計算値は1Vが1024として計算した値
  3. DAC値はsystem_get_vdd33()の戻り値
  4. 誤差は(計算値-DAC値)/計算値のパーセント(100倍)

ちょっと誤差が多すぎですね。Arduinoでサポートしていないのはこの辺もあるのかなあ?

 

2015年7月19日 (日)

ESP8266のTOUTピンの電圧をちゃんと測定する方法

ESP8266のTOUTピンの電圧をちゃんと測定する方法

ArduinoのESP8266 IED環境でanalogRead(A0)またはanalogRead(17)はTOUTピン解放時に3V3の電圧測定になるようです。
これは C:\Users\mtada\AppData\Roaming\Arduino15\packages\esp8266\hardware\esp8266\1.6.4-673-g8cd3697\cores\esp8266\core_esp8266_wiring_analog.c で readvdd33()の戻り値を>>2した値が返ります。

そこでいろいろ検索していると
http://qiita.com/azusa9/items/26e74e4e0d5773ce9c41
にsystem_adc_read()を呼び出す方法が書かれていました。

実際のTOUTピンの電圧と戻り値を確認すると 1/1000 すると電圧値になりました。

テスト スケッチは以下のようになります。

extern "C" {
#include "user_interface.h"
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
}

void loop() {
  // A0 の定義は17を確認
  Serial.println("A0: " + String(A0));

  // 17以外はいつも1023が返る
  int a = analogRead(0);
  Serial.println("analogRead(0): " + String(a));

  // TOUTピンをリード:4/1000倍すると3V3端子の電圧
  // TOUTピン解放のとき
  int b = analogRead(17);
  Serial.println("analogRead(17): " + String(b));
  float bv = (float)b * 4.0 / 1000.0;
  Serial.println("3V3: " + String(bv) + "V");

  int b2 = system_get_vdd33();
  Serial.println("system_get_vdd33(): " + String(b2));
  float bv2 = (float)b2 * 4.0 / 1000.0;

  //TOUTpinの読み出し(Cでincludeが必要)
  int c = system_adc_read();
  Serial.println("system_read_adc: " + String(c));
  float cv = (float)c / 1000.0;
  Serial.println("TOUTpin: " + String(cv) + "V");
  Serial.println("");
  Serial.println("");
  delay(1000);
}

TOUTピン解放での実行結果は以下の通り

A0: 17
analogRead(0): 1023
analogRead(17): 807
3V3: 3.23V
system_get_vdd33(): 65535
system_read_adc: 441
TOUTpin: 0.44V
VCC: 8.53V

TOUTピンが 0.258V のときの実行結果

A0: 17
analogRead(0): 1023
analogRead(17): 317
3V3: 1.27V
system_get_vdd33(): 65535
system_read_adc: 260
TOUTpin: 0.26V

解ったこと

  1. TOUTピン解放でanalogRead(17)は250で割ると3V3端子の電圧になる
  2. system_read_adc()を1000で割るとTOUTピンの電圧になる
  3. TOUTピンが解放でない場合は正しい3V3端子の電圧ではない
  4. user_interface.hに並んで定義してあるsystem_get_vdd33()は使えない

2015年7月18日 (土)

ESP8266WebServerが遅いわけ

ESP8266WebServerが遅いわけ

2015/9/1 現在 Arduino IDE と ESP8266 をインストールすると Arduion IDE 1.6.5 に ESP8266 の 1.6.5-947-g39819f0 がインストールされる。この ESPWebServer.cpp では

void ESP8266WebServer::sendContent(String content) は下記でコメントアウトしたコード部分が削除されている。

void ESP8266WebServer::send(int code, const char* content_type, const String& content) は sendHeader("Content-Length", len.c_str()); のみ対処している。

以上により以下の記述(2秒のタイムアウトの処理)は ESP8266 1.6.5-947-g39819f0 で対応済みと考えられる。

ESP8266のArduino IED用のSDWebServerスケッチの動作が極めて遅い。
SDカードのアクセスモードが古いの使っているからと遅いのかとずっと思っていました。
そこでSDカードのアクセス速度を計測してみるとぜんぜん遅くない。
Webサーバの応答が2秒以上かかっているのにSDカードのアクセスは40mSec以下処理していた。
そこでSDWebServerスケッチのloop()から時間のを計り始めた。
そしてスケッチの中のserver.send()の呼び出しで時間がかかっていた。
そしてC:\Users\xxxxx\AppData\Roaming\Arduino15\packages\esp8266\hardware\esp8266\1.6.4-673-g8cd3697\libraries\ESP8266WebServer\src\ESP8266WebServer.cppのsendContent()の赤字部分で2秒止まっている事を突き止めた。

void ESP8266WebServer::sendContent(String content) {
  size_t size_to_send = content.length();
  size_t size_sent = 0;
  while(size_to_send) {
    const size_t unit_size = HTTP_DOWNLOAD_UNIT_SIZE;
    size_t will_send = (size_to_send < unit_size) ? size_to_send : unit_size;
    size_t sent = _currentClient.write(content.c_str() + size_sent, will_send);
    size_to_send -= sent;
    size_sent += sent;
    if (sent == 0) {
      break;
    }
  }
  uint16_t maxWait = HTTP_MAX_CLOSE_WAIT;
  while(_currentClient.connected() && maxWait--) {
    delay(1);
  }

}

このコードはクライアントが接続が切れるか2秒待つで、いつもタイムアウトの2秒待っている感じです。
ここはsend()の最後に呼び出されている。でもスケッチからsend()を読んだ後にsendContentを呼び出すこともある。ここで2秒待つのはちょっとおかしいのでは?
ということでこの4行をコメントアウト

//  uint16_t maxWait = HTTP_MAX_CLOSE_WAIT;
//  while(_currentClient.connected() && maxWait--) {
//    delay(1);
//  }

以上で普通の速度(これまでに比べると高速)で動くWebServerになりました。

ESP8266WebServer.cppもう一か所、以下の3行をコメントアウトしてます。
本当は正しく書きなおさなければいけないのですがちょっと面倒なのでコメントアウトでごまかしています。

void ESP8266WebServer::send(int code, const char* content_type, String content) {
  String response = "HTTP/1.1 ";
  response += String(code);
  response += " ";
  response += _responseCodeToString(code);
  response += "\r\n";

  if (!content_type)
    content_type = "text/html";

  String len(content.length());
  sendHeader("Content-Type", content_type, true);
//  sendHeader("Content-Length", len.c_str());
//  sendHeader("Connection", "close");
//  sendHeader("Access-Control-Allow-Origin", "*");

  response += _responseHeaders;
  response += "\r\n";
  response += content;
  _responseHeaders = String();
  sendContent(response);
}

さぁてと、時間計測コードで汚した所を戻さなくては!

2015年7月17日 (金)

ESP8266のHelloServerちょろ変えでTOUTピンデータ表示

ESP8266のHelloServerちょろ変えでTOUTピンデータ表示

ESP8266 Arduino IDE のスケッチ例の HelloServer を最低限の修正でTOUTピンのデータを表示する。

スケッチのHandleRootを以下のように修正する(2行追加1行修正)。

void handleRoot() {
  digitalWrite(led, 1);
  int adc = analogRead(A0);   // input TOUT Pin
  String msg = "hello from esp8266!\r\nTOUT: " + String(adc);
  server.send(200, "text/plain", msg);
  digitalWrite(led, 0);
}

動作は
LED点灯後(元からあったまま)
TOUTピンのデータを読み出します
読み取ったTOUTピンの数値からStringに変換しつつ前後に文字追加
そのStringをWebブラウザに返す。

この後入力値から電圧を計算すると測定値がおかしいことが判りました。

調査すると C:\Users\<user>\AppData\Roaming\Arduino15\packages\esp8266\hardware\esp8266\1.6.4-673-g8cd3697\cores\esp8266\core_esp8266_wiring_analog.c で readvdd33() を呼び出しています。readvdd33() は libphy.a にありソースは無さそうです。
戻ってきた値を >>2 して1/4にしています。TOUTピン解放でanalogRead(A0)の戻り値を4/1000すると3V3への供給電圧になります。
analogRead(A0)またはanalogRead(17)以外ではdigitalRead(pin) * 1023の値で0または1023が返ります。

ということで上記サンプルはTOUTピン解放で3V3端子の電圧を読み取るプログラムということになりそうです。

2015年7月16日 (木)

ESP8266でAjax(SDWebServerで削除)

ESP8266でAjax(SDWebServerで削除)

スケッチの例にあるSDWebServerのeditで削除をテスト
ファイルまたはフォルダ(再帰的に削除されるよう)を削除するhtmを書いてみた。
先日のAjaxのテストコードでコマンド行のみ変更です(ボタンやメッセージも変えてはあります)。
重要なのは
  xmlhttp.open("GET","ajaxinfo.txt",true);

  xmlhttp.open("DELETE","edit?dir=/XXX.CSS",true);
に変えます。

dir=/XXX.CSSの=の右を変えることにより削除するファイル・フォルダを変えられます。

<html>
<head>

<script type="text/javascript">
function loadDoc() {
  if (window.XMLHttpRequest) {
    xmlhttp=new XMLHttpRequest();
  } else {
    xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
  xmlhttp.onreadystatechange=function() {
    if (xmlhttp.readyState==4 && xmlhttp.status==200) {
      document.getElementById("ajaxDiv").innerHTML=xmlhttp.responseText;
    }
  }
  xmlhttp.open("DELETE","edit?dir=/XXX.CSS",true);
  xmlhttp.send();
}
</script>

</head>
<body>

<p>
<div id="ajaxDiv"><h2>ここにajaxで実行した結果が表示されます</h2></div>
<button type="button" onclick="loadDoc()">ajaxで削除</button>
</p>

</body>
</html>

2015年7月14日 (火)

ESP8266でAjax つづき

ESP8266でAjax つづき

昨日に続きAjaxネタ

機能はアナログ入力ピン TOUT の値を取得した。
今日はスライダーの値で LED を点灯する。

16行目追加、17行目修正、27行目追加し以下のようにする。
(追加後の行数を示す)

<html>
<head>

<script type="text/javascript">
function loadDoc() {
  if (window.XMLHttpRequest) {
    xmlhttp=new XMLHttpRequest();
  } else {
    xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
  xmlhttp.onreadystatechange=function() {
    if (xmlhttp.readyState==4 && xmlhttp.status==200) {
      document.getElementById("ajaxDiv").innerHTML=xmlhttp.responseText;
    }
  }
  var val = document.getElementById("rang").value;
  xmlhttp.open("GET","led?value=" + val,true);
  xmlhttp.send();
}
</script>

</head>
<body>

<p>
<div id="ajaxDiv"><h2>ここにajaxで取得したの内容が表示されます</h2></div>
<input type="range" name="example1" id="rang">
<button type="button" onclick="loadDoc()">ajaxでデータ取得</button>
</p>

</body>
</html>

次に、スケッチのsetup()に以下追加

  server.on("/led", HTTP_GET, sliderAjax);

スケッチの適当な所に以下の関数追加

void sliderAjax() {
  String s = server.arg("value");
  int n = atoi(s.c_str());
  analogWrite(statusLED, n);
  server.send(200, "text/text", "");
  server.sendContent("LEDを明るさ" + s + "で点灯しました。");
}

2015年7月13日 (月)

ESP8266でAJAX

ESP8266でAJAX

ESP8266のTOUTピン(名称とは逆のアナログ入力ピン)の値をAJAXでブラウザで表示するテストをしてみました。

まずはAJAXの復習から。
次のようなHTMLを書き、ajax.htmとして保存。

<html>
<head>

<script type="text/javascript">
function loadDoc() {
  if (window.XMLHttpRequest) {
    xmlhttp=new XMLHttpRequest();
  } else {
    xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
  xmlhttp.onreadystatechange=function() {
    if (xmlhttp.readyState==4 && xmlhttp.status==200) {
      document.getElementById("ajaxDiv").innerHTML=xmlhttp.responseText;
    }
  }
  xmlhttp.open("GET","ajaxinfo.txt",true);
  xmlhttp.send();
}
</script>

</head>
<body>

<p>
<div id="ajaxDiv"><h2>ここにajaxで取得したの内容が表示されます</h2></div>
<button type="button" onclick="loadDoc()">ajaxでデータ取得</button>
</p>

</body>
</html>

ajaxinfo.txtとというファイルを作成する。中身はなんでも良い。
この2つのファイルをESP8266EXとSDカードにSDWebServer.inoで構成したSDカードのルートにコピーする。
Windowsなどからhttp://192.168.0.7/ajax.htmなどとしてアクセス。
(IPアドレスは実際に合わせて変更してください。)
表示されたボタンを押すとajaxinfo.txtファイルの中身が表示される。

これでajaxの復習と動くhtmlが準備できた。

つぎにSDWebServerスケッチにあるディレクトリの一覧を表示するprintDirectoryメソッドを動かしてみる。

16行目の"ajaxinfo.txt"を"list?dir=/"して以下のようにする

  xmlhttp.open("GET","list?dir=/",true);

に変えるだけ。
同じくWindowsなどからhttp://192.168.0.7/ajax.htmをアクセス。
表示されたボタンを押すとSDカードのルートのファイル名などが表示される。
もとからあるprintDirectory()はjsonのデータを返してくるので私はテキストで返すように変更してテストしました。変更しないでそのままでも一覧にはならないけど動作するはず。

最後にTOUTピンの情報の表示です。(3か所の変更・追加があります)

1.htmlの変更は16行目を"tout"変え次のようにします。

  xmlhttp.open("GET","tout",true);

2.さらにSDWebServer.inoのsetup()のserver.on()のあるかたまりに以下追加

  server.on("/tout", HTTP_GET, tout);

3.次のコードをSDWebServer.inoに追加

void tout() {
  Serial.println("ar");
  int ar = analogRead(A0);
  analogWrite(statusLED, ar);
  Serial.println(String(ar));
  String message = "<html><head><title>TOUT</title></head><body>";
  message += "TOUTピンの値=";
  message += String(ar);
  message += "<br /><body></html>";
  server.send(200, "text/html", message);
}

以上でTOUTピンの値(ADC変換された数値)が表示されます。
値を1/1000するとTOUTピンのおおよそ電圧になります。
TOUTピンに1Vのとき1023になるようですが1Vでは1023になりませんでした。また、1.023V前に1023になるので1.023Vで1023になるでも無いよう?そもそも測定したマルチメータの確度の問題もあるので測定では限界が。仕様を探しても明確に書いてある仕様書が見つかっていません。

補足
・2番目のてすとでSDカードのルートディレクトリの一覧で一覧を表示するまでに1分弱かかります。ディレクトリ・ファイルが24件あり1つひとつファイルを開いて調べているので時間がかかるのは解るのですがちょっと時間がかかりすぎですね。htmlを開くときも時間がかかります。
・ArduinoのSDカードはファイル名が8.3形式のみサポートです。なのでhtmlファイルもindex.htmなどとする必要があり、html内のファイル名などの記述も8.3に合わせなければなりません。小文字での記述はOKですが実際のファイル名は大文字となります。
またwindwsで長いファイル名で保存すると8.3形式のファイル名が自動的に生成されSAMPL~1.TXTなどの名前になります。コマンドプロンプトでDIR /Xとすると確認できますが、~1の部分は自動的に付けられるのでhtmlないのリンクに使うのは難しいですね。

2015年7月12日 (日)

ESP8266とArduino

ESP8266とArduino

ESP8266をArduinoから使う場合いくつかのパターンがあります。
その前にArduinoとは
・ATMEGA328をCPUとした基板:Arduino UNOなど
・Arduino UNOのプログラムを開発するArduio IDE
の2を片方だけや両方を含めてあらわしていると思います。
ここではArduinoはArduino IEDとArduino UNOを指すます。

Arduinoを使ってESP8266を使うといった場合
1.Arduino UNOにESP8266をATコマンド名で制御するプログラムを動かす
2.Arduino UNOにUSBシリアルとESP8266相互にやり取りするプログラムを動かし、PCのターミナルプログラムでESP8266を制御する。
3.Arduino UNOのUSBシリアルアダプタとESP8266をつなぎArduino UNOのUSBシリアルアダプタのみを使いう。
4.Arduino IEDからESP8266に直接つなぎ、Arduino IEDでESP8266のプログラムを作成し、ESP8266内にプログラムを転送し実行する。

このブログの最近のエントリでArduino・ESP8266の記事は最初の1つを除いてすべて4のパターンの事を書いています。
最初のエントリーは3、2のパターンで上手くいかず、PC->USBシリアル->ESP8266とつないでATコマンドで動いたという話です。
4のパターンはハード的にはPC->USBシリアル->ESP8266とつないでいます。

他の開発方法としてLuaという言語(?)で開発する方法もあるようです。

2015年7月11日 (土)

ESP8266のArduinoでvectorでエラーになる

ESP8266のArduinoでvectorでエラーになる

ボードをGeneric ESP8266 Moduleでvecterでエラーになる。
以下のようにarduino.hとvectorをincludeすると

#include <arduino.h>
#include <vector>

void setup() {
}

void loop() {
}

以下のエラーになる。

Arduino: 1.6.4 (Windows 7), ボード:"Generic ESP8266 Module, 80 MHz, 115200, 512K (64K SPIFFS)"

ビルドオプションが変更されました。全体をリビルドしています。

In file included from sketch_jul10c.ino:1:0:
c:\users\mtada\appdata\roaming\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9\xtensa-lx106-elf\include\c++\4.8.2\bits\stl_vector.h: In member function 'std::vector<_Tp, _Alloc>::size_type std::vector<_Tp, _Alloc>::_M_check_len(std::vector<_Tp, _Alloc>::size_type, const char*) const':
C:\Users\mtada\AppData\Roaming\Arduino15\packages\esp8266\hardware\esp8266\1.6.4-673-g8cd3697\cores\esp8266/arduino.h:217:18: error: expected unqualified-id before '(' token
#define max(a,b) ((a)>(b)?(a):(b))
                  ^
c:\users\mtada\appdata\roaming\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9\xtensa-lx106-elf\include\c++\4.8.2\bits\stl_bvector.h: In member function 'std::vector<bool, _Alloc>::size_type std::vector<bool, _Alloc>::_M_check_len(std::vector<bool, _Alloc>::size_type, const char*) const':
C:\Users\mtada\AppData\Roaming\Arduino15\packages\esp8266\hardware\esp8266\1.6.4-673-g8cd3697\cores\esp8266/arduino.h:217:18: error: expected unqualified-id before '(' token
#define max(a,b) ((a)>(b)?(a):(b))
                  ^
コンパイル時にエラーが発生しました。

  This report would have more information with
  "コンパイル中の詳細な出力を表示する"
  ファイル > 設定 で有効にする

ESP8266WebServer.cppのsend()でレスポンスヘッダーが重複する問題をvectorを使って解決しようとしてテストコードは出来てのですが、いざESP8266WebServer.cppに組み込むとエラー。
いろいろ調べると上記のようにincludeするだけでエラーになることが判明

ちなみにArduino NANOでvectorが無いとエラーになるので無いみたいです。

ESP8266WebServer.cppのあるフォルダにESP8266WebServer.cpp.origというファイルがある。
このvoid ESP8266WebServer::send(int code, const char* content_type, String content)は引数で渡されるcontent_typeのみレスポンスヘッダーに追加する。
これの方が良い。

2015年7月10日 (金)

ESP8266のArduinoのSDWebServerがうまく動かない訳

ESP8266XのArduinoのSDWebServerがうまく動かない訳

Arduino IDE にESP8266のIDEをインストールするとサンプルスケッチに"SDWeServer"が追加されている。
このスケッチのssidとpasswordとSSを変更・定義すると動作するわけですが、上手く動作しません。
WebサーバーはSDカードのルートをWebのルートとして動作する。
その時SDWebServerがHTTPヘッダーのContent-Length、Connection、Access-Control-Allow-Originを返すようセットしているのですが、ESPWebServerのsend()は、このヘッダーを送った後自分でも独自に作って送るため2重に送信してしまう。
こおためFireFoxとChrmeでは表示できない。IEは表示できる。
Windows10のMicrosft Edgeも表示する。ヘッダーが異常なのに表示するんだ!セキュリティ大丈夫かな?

SDWebServerでヘッダーを返さないと長さ0のヘッダーになるのでエラーなしでFireFoxとChrmeとIEは何も表示しない。Edgeはテストしてない。

ESPWebServer.cppの

void ESP8266WebServer::sendHeader(String name, String value, bool first) {
  String headerLine = name;
  headerLine += ": ";
  headerLine += value;
  headerLine += "\r\n";

  if (first) {
    _responseHeaders = headerLine + _responseHeaders;
  }
  else {
    _responseHeaders += headerLine;
  }
}

で_responseHeadersに追加するとき、すでにあるnameの行を削除してから追加すればよい。

他にも上手く動かないのがある、IEだと動くのかなあ。

上記記事は Arduion IDE 1.6.4 に ESP8266 の 1.6.4-673-g8cd3697 で記述。ESPWebServer.cpp は以下のフォルダにある。

C:\Users\xxxxx\AppData\Roaming\Arduino15\packages\esp8266\hardware\esp8266\1.6.4-673-g8cd3697\libraries\ESP8266WebServer\src\ESPWebServer.cpp

2015/9/1 現在 Arduino IDE と ESP8266 をインストールすると Arduion IDE 1.6.5 に ESP8266 の 1.6.5-947-g39819f0 がインストールされる。この ESPWebServer.cpp では send() が修正されているが動作確認はまだです。

C:\Users\xxxxx\AppData\Roaming\Arduino15\packages\esp8266\hardware\esp8266\1.6.5-947-g39819f0\libraries\ESP8266WebServer\src\ESPWebServer.cpp

確認できたら追記します。・・・ で確認しました。

void ESP8266WebServer::send(int code, const char* content_type, const String& content) は sendHeader("Content-Length", len.c_str()); のみ対処している。

でした。これによりFierFoxでは動作することを確認しました。

2015年7月 9日 (木)

ESP8266でI2Cを使ってみる

ESP8266でI2Cを使ってみる

ESP8266にはI2Cのインターフェースが付いている。 I2CはSDAとSCLの2つの信号でデータをやり取りすつ仕様となっている。

そこでリアルタイムクロックのDS1307をESP8266につなげてみた。

ESP8266
Pin
ESP8266
PinName
ESP8266
Function
DS1307
Pin
DS1307
Function
7 GPIO2 SDA 5 SDA
3 GPIO14 SCL 6 SCL

スケッチは以下のようになる

#include "Wire.h"
#define DS1307_ADDRESS 0x68

void setup(){
  Wire.begin(2, 14);
  Serial.begin(115200);
}

void loop(){
  char buf[100];
  Wire.beginTransmission(DS1307_ADDRESS);
  byte zero = 0x00;
  Wire.write(zero);
  Wire.endTransmission();
  Wire.requestFrom(DS1307_ADDRESS, 7);
  int second   = Wire.read();
  int minute   = Wire.read();
  int hour     = Wire.read() & 0b111111;
  int weekDay  = Wire.read();
  int monthDay = Wire.read();
  int month    = Wire.read();
  int year     = Wire.read();
  sprintf(buf,"20%x/%x/%x %x:%x:%x %x",year,month,monthDay,hour,minute,second,weekDay);
  Serial.println(buf);
  delay(100);
}

SDAとSCLの接続しているPinを知らせるため"Wire.begin(2, 14);"でイニシャライズする。
データはBCDで来るので16進で表示すると10進として表示される。

注:DS1307のVCCは5Vなので3.3VのESP8266やSDカードとは別に5Vの電源が必要になる。

以上で、アナログ入力、SDカード アクセス、リアルタイムクロック アクセスが確認できた。ATMEG328でデータロガーを作っていて、WiFi用にESP8266を追加しようとテストしてきたが、ESP8266単体でデータロガー出来る事が判った。
ATMEGA328いらないじゃん!

*ちゃんとレベル変換しないとSDカードの動作が不安定になります。SDカードの書き込みで不安定になるとSDカードのデータを壊します。しかし、I2Cの信号は双方向なのでレベル変換も双方向にしなければならない。なので今はDS1307を外してあり、別の3.3Vの物を物色中です。(7/17追記)

2015年7月 8日 (水)

ESP8266とmicroSDを接続してみる

ESP8266とmicroSDを接続してみる

ESP8266とmicroSDを次の表のように結線。


ESP8266 PinESP8266 Pin NamemicroSD Pin MicroSD Name
10 GPIO4 2 CD
5 MOSI 3 CMD
3 SCK 5 CLK
4 MISO 7 DATA0
4 VDD
6 VSS


CardInfo スケッチがすんなり動作

最初GPIO4をLEDでステータス表示に使用しているため、CDをGPIO5でテストしたらCardInfoスケッチがどうさせず。GPIO4でテストすると動作する。もちろんスケッチのコードは変更している。そこでHackしてみようとIncludeをたどりSd2Card.cppを見ると"chipSelectPin_"に設定していてちゃんと動作しそうなので、再度GPIO5でテストすると動作する。こんなことが多いESP8266・・・。
HACKで発見ですがSd2Card::initのsckRateIDは

#ifdef ESP8266
uint8_t Sd2Card::init(uint32_t sckRateID, uint8_t chipSelectPin) {
#else
uint8_t Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) {
#endif

とESP8266は32ビットになっている、初めて32ビットCPUを感じた。

以上、これでmicroSDが使用できる。


2015年7月 7日 (火)

ESP8266のArduino IDEのWebServerでGETコマンドの引数を取得する

ESP8266のArduino IDEのWebServerでGETコマンドの引数を取得する

WebServerでGETやPOSTの引数を取得できないと何もできない。
そこで引数を取得する方法を調べてテストしてみた。

最初適当にgrepで検索したけど上手く見つからない。
WebServerは受け取ったパケットのコマンドを解析しそのあとに引数を改正しているはず。
ということでHelloServerのloop()

void loop(void){
  server.handleClient();
}

のhandleClient()から調べると

C:\Users\hogehoge\AppData\Roaming\Arduino15\packages\esp8266\hardware\esp8266\1.6.4-673-g8cd3697\libraries\ESP8266WebServer\src
の181行あたりに

String ESP8266WebServer::arg(const char* name) {
  for (int i = 0; i < _currentArgCount; ++i) {
    if (_currentArgs[i].key == name)
      return _currentArgs[i].value;
  }
  return String();
}

というコードが有った、これで取得できそうだ
というこどで以下のコードを書いてテスト

サンプルのHelloServerのsetup()に以下のコード追加(場所は  server.on("/onoff", []() { の下あたり)

  pinMode(4, OUTPUT);
  analogWrite(4, 0);

  server.on("/onoff", []() {
    String s = server.arg("LED");
    if (s == "on") {
      analogWrite(4, 1024);
    } else {
      analogWrite(4, 0);
    }

    String message = "<html><head></head>";
    message += "<body>LED='";
    message += s;
    message += "'<br />";
    message += "<form method='get' action='./onoff'>";
    message += "<input type='radio' name='LED' value='on' checked='checked' />ON";
    message += "<input type='radio' name='LED' value='off' />OFF";
    message += "<input type='submit' value='送信'>";
    message += "</button>";
    message += "</form>";
    message += "</body></html>";
    server.send(200, "text/html", message);
  });

http://192.168.x.x/onoffに接続し送信ボタンを押すと"LED=on"と表示される。

2015年7月 6日 (月)

ESP8266のArduinoでADC_MODEが無い

ESP8266のArduinoでADC_MODEが無い

先日TOUTピンはADC_MODE(ADC_VCC)でVCCを読めるようだと書いた。
そこで動かしてみようと調べてみたがADC_MODE()がどこにもない。

getVcc()はEsp.cppのEspClssにあり、getVcc()はsystem_get_vdd33()を呼び出している。

いろいろ調べるとSDKの中にsystem_get_vdd33()があり
この辺のコードを見るとヒントがあるかもと思いSDKらしきものをダウンロードしたが中身がない。
GitHUBで一つ一つのファイルは見られるようだけど全部ダウンロードするのはどうしたらいいのかな
Gitを使えば良さそうだけどGitのインストールではまりそう。

で検索しているとsystem_get_vdd33()について質問しがあり、結局11日前にパッチが当てられたのかな(良く分からない)

system_get_vdd33からいつも65535が返ってくるって質問している
https://github.com/esp8266/Arduino/issues/225
pin A0 をGNDと3.3Vつないだ時の質問をしている
https://github.com/esp8266/Arduino/issues/338#issuecomment-113099775
で以下の変更するよとなっている(ADC_MODEが11日前に追加されているよう)
https://github.com/esp8266/Arduino/commit/5b00eba9d76e5ccd0a694da5b9a67f88f5caf3fc

結局のところテストできなかった。

2015年7月 5日 (日)

ESP8266でアクセスポイント機能が勝手に有効になる

ESP8266でアクセスポイント機能が勝手に有効になる
機能確認のために作成したWebアプリケーションで勝手にアクセスポイントが有効になる場合がある。
いろいろ調べてゆくとArduion IDEで選択するボードによりアクセスポイントが有効になることが判った。この場合のアクセスポイントはセキュリティ無しなので注意。
「ツール」「ボード:」で表示されるESP8266関係のボード

   
IDE選択表示AP動作
ESP8266 Module IDEでグレーアウトで選択できない
Generic ESP8266 Module APは無効
Olimex MOD-WIFI-ESP8266(-DEV) APが有効になり(192.168.4.1)HTTPで接続できる
NodeMCU(ESP8266 ESP-12 Module) APが有効になり(192.168.4.1)HTTPで接続できる

2015年7月 4日 (土)

ESP8266のanalogWriteのvalue値のMAXは?

ESP8266のanalogWriteのvalue値のMAXは?

Aruduino UNOのvalue値は0~255までです。
ESP8266をいろいろ調べているときanalogWriteは0~1023までと書いてあったような。
そして内蔵タイマーの都合で使用できるのは1ポートまでと。

で以下のようなArduinoスケッチを作成し実行。

const int port = 13;

void setup() {
  pinMode(port, OUTPUT);
}

void loop() {
  for (int i = 0; i < 4096; ++i) {
    analogWrite(port, i);
    delay(10);
  }
  analogWrite(port, 0);
  delay(3000);
}

すると4回ゆっくり明るくなりました。
そして、"const int port = 4;"で実行しても同じように動きます。
2つのポートで使えるじゃん!
と書いてる時同時に使える?と疑問になり次のように変更

const int port4 = 4;
const int port13 = 13;
void setup() {
  pinMode(port4, OUTPUT);
  pinMode(port13, OUTPUT);
}
void loop() {
  //  int adcin = analogRead(A0);
  for (int i = 0; i < 4096; ++i) {
    analogWrite(port4, i);
    analogWrite(port13, 4096-i);
    delay(10);
  }
  analogWrite(port4, 0);
  analogWrite(port13, 0);
  delay(3000);
}

明るくなって行くGPIO4と暗くなってゆくGPIO13が確認出来ました。

判ったこと
analogWrite(pin, value) のvalue値は0~1023
analogWrite(pin, value) はGPIO4とGPIO13同時に使える

2015年7月 3日 (金)

ESP8266のTOUTピンの機能調査とテスト

ESP8266のTOUTピンの機能調査とテスト。

名称が「TOUT」ですが機能は入力ピンです。

GitHubのesp8266 / Arduinoによると ESP.getVcc() により 電源電圧を測定するようです。これを使うには初期化時に ADC_MODE(ADC_VCC); を実行する。
ノートにデフォルトADCは、analogRead(A0)を使ってTOUTピンから読むために設定されて、ESP.getVCC()はavailablesではない。

とあったので analogRead(A0) を使ってみた。

Arduino IDEで以下のように入力し実行します。

void setup() {
  pinMode(13,OUTPUT);
}
void loop() {
  int adcin = analogRead(A0);
  analogWrite(13,adcin);
}

これでTOUTピンに0から1ボルトの電圧をかけるとLEDの明るさが変わります。

ESP8266をArduion IDEで開発するための接続・設定

ESP8266をArduion IDEで開発するための接続・設定

以下のようにESP8266EXとFT232を接続する。
FT232のVCCIOに3.3V接続すると出力が3.3Vになる。

PinResistorSerial Adapter
VCC VCC(3.3V)
GND GND
TX RX
RX TX
GPIO0 PullUp DTR
Reset PullUp RTS*
GPIO15 PullDown
CE PullUp

*RTSはFTDI232のUSBシリアル変換基板なのどの8Pinには出ていない(FT232RLの3番ピン)。

Arduinoにボードマネージャをインストールする。
1.Arduinoを起動する
2.「ファイル」「環境設定」「Additional Borards Manager URLs」に"http://arduino.esp8266.com/package_esp8266com_index.json"入力し「OK」
3.「ツール」「ボード」「Board Manager...」を開き「esp8266 by ESP8266 Community Version 1.6.4-673-g8cd3697」(の枠内)をクリックすると「Install」ボタンが出るのでクリック
4.「ツール」「ボード」「Generic ESP8266 Module"選択
5.「ツール」「CPU Frequency」「80MHz」選択(で良いと思う)
6.「ツール」「Upload Speed」「115200」選択
7.「ツール」「ボート」は接続されているポート「COM5」など

以上で設定完了。

GPIO13にLEDを接続し(8ピンタイプのでは付いているのかな?)
「ファイル」「スケッチの例」「01.Basics」「Blink」を開き
「ファイル」「マイコンボードに書き込む」とコンパイル・書き込み後LEDが点滅する。

このとき「シリアルモニタ」を起動してはいけない。
「シリアルモニタ」は「Reset-DTR]」と「GPIO0-DT」を切り離した(PullUp抵抗はESP8266に付けたまま)後に起動する。
これではまりました。

「ファイル」「スケッチの例」「ESP8266WebServer」「HelloServer」を開き
「ファイル」「マイコンボードに書き込む」
スケッチの6・7行目のssidとpasswordにWiFi接続(自宅のWiFiルータなど)のidとパスワードに変更する。

WebブラウザからESP8266のIPアドレスに接続するとブラウザに「Hello from esp8266!」と表示さえる。

ここでIPアドレスを確認するためにシリアルモニタを起動するとESP8266が止まってしまう。ResetとGPIO0を切り離してからシリアルモニタを起動すると初期化時にIPアドレスを表示する。すでに初期化が終わっていたらResetをGNDに接続しリセットする(ボタンを付けておくとよい)。

*最初上手く動作しなかったけどReset・GPIO0の切り離しを行うと上手くいく。途中で切り離してテストしたような気もするけど、またもや少し納得がいかない。

2015年7月 2日 (木)

ESP8266搭載 WiFi-UARTモジュール(技適取得済み)購入

Amazonの「マイクロテクニカで」ESP8266EX搭載 WiFi-UARTモジュール(技適取得済み)購入しました(やっと届いた)。日本国内で使用できる「技適取得済み」の物です。(技適取得済みじゃないnRF24L01+のことだとブログに書けないし)

表面実装用でピン間隔が1.5mmのためブレッドボードなとうまく乗りません。
0.55mmの銅線を2cmほどに切りはんだ付けし2.54mm間隔に広げてブレッドボードに刺してます。抜き刺しでチップに負担がかかりそうでちょっと怖い。

最初arduino NANOに接続してテストしましたが上手く動きません。
FTDI 232の自作変換基板に変えても最初上手く動きませんでしした。
なんとかATコマンドが動くようになったのですが動かなかった原因が解りません。
なので一応現状のピン接続状態をメモしておきます。

NO.PinName状態
1 3V3 3.3Vに接続
2 EN 3.3Vに接続
3 IO14 未接続
4 IO12 未接続
5 IO13 未接続
6 IO15 GNDに接続
7 IO2 3.3Vに接続
8 IO0 3.3Vに接続
9 GND GNDに接続
10 IO4 未接続
11 RXD FT232RL 1Pin(TXD)に抵抗分圧されて接続
12 TXD FT232RL 5Pin(RXD)に(直接)接続
13 GND GNDに接続
14 IO5 未接続
15 RST 未接続
16 TOUT 未接続
17 IO16 未接続
18 GND GNDに接続

モード設定

modeIO15IO0IO2
UART Download ModeLowLowHigh
Flash Boot ModeLowHighHigh

RSTがオープンなのが悪かったのかなあ?

あと、予約で買ったら926円今(7月2日)920円で予約の方が高かった!

« 2015年6月 | トップページ | 2015年8月 »