ESP8266 > watchdog resetのESP-WROOM-02調査 > WiFi.begin()のままが問題なのかもしれない

関連 http://qiita.com/7of9/items/e8a01d43048199ad65d6

気圧計を作っている中で、watchdog resetがかかるようになったESP-WROOM-02(以下ESP8266)。
3枚あるうちの１枚だけwatchdog resetがかかるようだ。
該当のESP8266を使用中に気圧計のICを反対に挿したことがあり、ESP8266を壊したのだろうか。

[macsbugさんの記事](https://macsbug.wordpress.com/2016/06/20/esp8266-of-error-message/)を参考にGPIO15, GPIO0, GPIO2をAnalog Discovery 2にて計測してみた。

### reset時のGPIO15とGPIO0

- 黄色: GPIO15
- 青色: GPIO0

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/0c38fc57-d976-eab4-0ffd-c8705c4924c4.png)

watchdog resetがかかった時にGPIO0の電圧が下がることが分かった。

### reset時のGPIO2とGPIO0

- 黄色: GPIO2
- 青色: GPIO0

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/274a98f4-265b-daa0-c20a-923c29c6b1dc.png)

同じピンのキャプチャにて時間軸を詳細にしたもの

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/c7271e1b-7c38-006e-7bca-54b026993a77.png)

### 6月24日時点でわかっていること

- GPIO0の電圧が1.8V程度になる
- GPIO2が短時間にH/L切替になる

上記のトリガになるものはまだ追えていない。

### 2枚目もresetするようになった
(追記 2016/06/25)

1枚目のESP8266だけresetするかと思っていたが、2枚目もresetするようになった。

再現手順は以下

1. 気圧計のソフト(eps8266_160528_MPL115A2)を書込み
2. helloだけシリアル出力するソフトを書込み

気圧計のソフトでresetの原因となる何かがあるのかもしれない。

resetがかかるようになったESP8266は以下に記載した通りで復旧できた。
http://qiita.com/7of9/items/e8a01d43048199ad65d6#%E8%A7%A3%E6%B1%BA

1. udpEcho_151219を書込み
2. helloだけシリアル出力するソフトを書込み

### Clear the memory(Flash)推奨の情報

以下を見つけた。Flashに変なコードが残り、それがwatchdog resetを生じさせているのだろうか。

http://internetofhomethings.com/homethings/?tag=esp8266-unstable
> `2. Clear the memory
>
> Along with securing connections, flashing some of the original binaries back into the module has always worked for me to clear the reset problem, so far. 


## PWR ON時のGPIO 15とGPIO 0

[macsbugさんの記事](https://macsbug.wordpress.com/2016/06/20/esp8266-of-error-message/)
の以下を確認してみた。
> 起動時のGPIO状態：(以下画像を参照させてい頂きます)。
GPIO 0は 起動時に出力になり 起動40ms後にGPIO0ラインは
約100ms間 約350Hzの信号が出力される。

### watchdog resetしないESP8266のPWR ON時

- 黄色: GPIO15
- 青色: GPIO0

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/bee8492b-9e09-d461-0d89-ddf8625fea57.png)

0mから39msの間Hになり、その後H/Lの高速切替が発生している。

### watchdog resetするESP8266のPWR ON時

- 黄色: GPIO15
- 青色: GPIO0

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/d2ac68d8-dbbc-2dc4-03c1-fa0688102aa4.png)

watchdog resetしないESP8266と波形の違いは見られない。

## PWR ON時のGPIO 2とGPIO 0

[macsbugさんの記事](https://macsbug.wordpress.com/2016/06/20/esp8266-of-error-message/)に起動時のGPIO 2とGPIO 0の波形を掲載していただいた。同じものをこちらで波形観測してみた。

### watchdog resetしないESP8266のPWR ON時

- 黄色: GPIO 2
- 青色: GPIO 0

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/025f6d38-a21c-3340-b281-b418bc000268.png)


### watchdog resetするESP8266のPWR ON時

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/16d3d370-b47f-ac06-6d5b-b551b921b28d.png)


### 気になる点 GPIO 2の信号

上記２つの画像の差異は見られない。

~~一方で、macsbugさんの波形と違う点は以下の通り~~
~~- GPIO 2の波形(-4Vから-1Vの間の振動)がこちらの環境で見られない~~
~~こちらはReset端子に100nFを未実装、EN端子に100nFを未実装。~~

GPIO 2を測定するつもりがGPIO 12を見てしまっていた。波形を測定し直すと上記のようになった。
macsbugさんの波形と同じようにGPIO 2の信号が見える。

### Reset端子とEN端子にコンデンサ100nF

Reset端子に100nFを実装。EN端子に100nFを実装した。

watchdog resetはやはり発生している。


## 問題のプログラムの簡易版

### 気圧計のプログラムの簡易版 v0.1

気圧計のプログラムをロードした後に、別のソフト(helloWorld出力)をロードしてもwatchdog resetがかかっている。

気圧計のプログラムをコメントアウトしていき、簡易版にしたものが以下となる。

[v0.1 @ github](https://github.com/yasokada/esp8266_160625_watchdogReset/releases/tag/v0.1)

```c:eps8266_160625_watchdogReset
#include <ESP8266WiFi.h>
#include <WiFiUDP.h>

/*
 * This program may cause watchdog reset even after being overwritten by other EPS8266 program
 * 
 * Environment: Arduino 1.6.6
 * ESP-WROOM-02
 */

/*
 * v0.1 2016 Jun. 25
 *   - add WiFi_setup()
 */

static WiFiUDP wifiUdp;
static const int kPortUdp_logger = 7000;

static const char *kWifiSsid = "esp8266";
static const char *kWifiPass = "12345678";

static const char *kLoggerIP = "192.168.79.2";

void WiFi_setup()
{
  WiFi.begin(kWifiSsid, kWifiPass);
  while ( WiFi.status() != WL_CONNECTED) {
    delay(500); // msec  
  }
  wifiUdp.begin(kPortUdp_logger);
}

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

  WiFi_setup(); 
}

void loop() {

}
```

上記で気になるのは、setup()内でコールされるWiFi_setup()がAccessPointが有効でない時に延々とwhile()につかまってしまうこと。
こうするとloop()にたどり着かない。

こういう実装がまずいのかもしれない。

よくわからないのは、このプログラムを別のプログラムで上書きしても、このプログラムの影響によりwatchdog resetがかかっているようだということ。何かの情報がFlashに残ったままなのか、OSが管理する別ソフトとして残っているのか、そしてOSがそのソフトのハングを検知してwatchdog resetをかけているのだろうか。

### 気圧計のプログラムの簡易版 v0.2 > 問題の回避

問題を回避するコードにしてみた。

[v0.2 @ github](https://github.com/yasokada/esp8266_160625_watchdogReset/releases/tag/v0.2)

```c:esp8266_160625_watchdogReset.ino
#include <ESP8266WiFi.h>
#include <WiFiUDP.h>

/*
 * This program may cause watchdog reset even after being overwritten by other EPS8266 program
 * 
 * Environment: Arduino 1.6.6
 * ESP-WROOM-02
 */

/*
 * v0.2 2016 Jun. 25
 *   - disconnect WiFi when WiFi connection failed
 *   - modify WiFi_setup() to avoid endless while loop
 * v0.1 2016 Jun. 25
 *   - add WiFi_setup()
 */

static WiFiUDP wifiUdp;
static const int kPortUdp_logger = 7000;

static const char *kWifiSsid = "esp8266";
static const char *kWifiPass = "12345678";

static const char *kLoggerIP = "192.168.79.2";
static bool s_isWiFiConnected = false;

/*
 * in WiFi_setup(), changing "#if 1" to "#if 0" will cause watchdog reset
 */

void WiFi_setup()
{
  bool bfOk = false;
  WiFi.begin(kWifiSsid, kWifiPass);
#if 1
  for(int loop = 0; loop < 3; loop++) {
    if (WiFi.status() == WL_CONNECTED) {
      s_isWiFiConnected = true;
      break;
    }
    delay(500); // msec
  }
  if (s_isWiFiConnected) {
    wifiUdp.begin(kPortUdp_logger);  
  } else {
    WiFi.disconnect();
  }
#else
  while ( WiFi.status() != WL_CONNECTED) {
    delay(500); // msec  
  }
  wifiUdp.begin(kPortUdp_logger);
#endif  
}

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

  WiFi_setup(); 
}

void loop() {

}
```
<font color=red>(追記 2016/06/26) 上記ではconnectionのリトライを3としているが、10程度にする方がいいかもしれない。気圧計のソフトで試したところ3回ではconnectionを失敗する場合があった。</font>

上記において以下の変更をした

- while()での無限ループをやめて3回までのループにした
- s_isWiFiConnected を追加。
- s_isWiFiConnected == false時に WiFi.disconnect() を実行

以上によりwatchdog resetは発生しなくなったようだ。

http://qiita.com/exabugs/items/2f67ae363a1387c8967c#comment-50fe5d22ce84cc1c0fdd
に書かれている  7E000h のWiFi設定が書き込まれていることと関係があるのかもしれない。

http://qiita.com/Kaz_Macintosh/items/898e1f63d967a13e39d6
の以下も関係あるかもしれない。
> なぜか指定したSSIDではなく、リセット前に接続していたSSIDで接続をしているようでした。これは仕様なのでしょうか・・・。

以下は問題についての推測。
あるソフトでWiFi.begin()を実行し、アクセスポイントが無効の状態でWiFi.disconnect()をしないとする。7E000hにWiFi設定が書かれた状態になる。
別のソフトではWiFiについての記載がないとする。7E000h が使われてなんらかの現象によりwatchdog resetが発生する。

対策としては上記のようにWiFi.begin()失敗時にきちんとWiFi.disconnect()すること。

WiFiを使わないソフトの最初にWiFi.disconnect()を実行するのは有効だろうか。