ESP32(ESP-WROOM-32)でLチカ (WindowsでESP-IDF使用)

#はじめに

[ESP32の開発環境いろいろ](http://qiita.com/rukihena/items/efdf02bd728b01fd3330)の中でも触れた、[ESP-IDF](http://esp-idf.readthedocs.io/)について、環境構築方法とLチカサンプルプログラムを紹介します。

ESP-IDF は、make でビルドし、make flash でESP32の実機に書き込むような開発環境です。SDKと呼んでもいいような気がしますが、SDKだけじゃなくコンパイラなどなども提供してますよということで IDF という名前を付けているようです。

[Set up of Toolchain for Windows](http://esp-idf.readthedocs.io/en/latest/windows-setup.html) を元に書いています。

Windows 10 64bit で試しています。

#開発環境(ESP-IDF)インストール

make コマンドは UNIXの世界のコマンドですので、「UNIXっぽい環境」が必要となります。

「UNIXっぽい環境」を作るやり方はCygwinが有名だったりしますが、最近はMSYSが流行りのようです。

公式でもMSYSを使うことを前提にしています。

ここでは
　`C:\msys32` に MSYS
　`C:\esp-idf` に ESP-IDF
　`C:\Users\[Windowsのユーザー名]\OneDrive\esp32\` にプロジェクト（ソース）
を置く前提で話を進めます。

##Step1

Espressif が toolchain（ここではmakeのためのコンパイラやリンクのためのコマンド群という意味） と MSYS をまとめた ZIP を作ってくれているので、それをダウンロードし、Cドライブ直下に展開します。 C:\msys32 というフォルダが出来上がります。

現在の最新版は
~~https://dl.espressif.com/dl/esp32_win32_msys2_environment_and_toolchain-20170111.zip~~
https://dl.espressif.com/dl/esp32_win32_msys2_environment_and_toolchain-20170330.zip
です。

実際にダウンロードする場合は
http://esp-idf.readthedocs.io/en/latest/windows-setup.html
を見て最新版を拾ってくるようにしましょう。

ZIPが475MBytes、展開すると1.2GBytes ぐらいになります。この記事を読み終わる前にダウンロードを始めてしまいましょう。展開も10分以上かかります。

##Step1 （別の方法）

公式の文章では、Alternative （代替案）として、MSYSとtoolchainを別々にインストールする方法、Another Alternative（別の代替案）として、MSYSが既にインストールされている環境にtoolchainだけダウンロードする方法が紹介されています。場合によってはコチラの方法も検討してください。（自分は試していません）

##Step2

このステップでは ESP-IDF を github から取得します。

配置するディレクトリは、ここでは `C:\esp-idf` とします。公式の例では path/to/なんとか みたいな記述なので、どこでもいいと思います。

まず、Windows Explorerなどから `C:\msys32\mingw32.exe` を実行し、MSYSを開きます。初回は初期設定が走るらしく、ちょっと時間がかかります。起動できたら、bash の世界になります。

`cd /c` でカレントディレクトリをCドライブ直下に移動します。

`git clone --recursive https://github.com/espressif/esp-idf.git` で ESP-IDF を取得します。Cドライブ直下で実行すると、そこに esp-idf というフォルダだけが作成されます。（最初、C:\esp-idf で作業したら c:\esp-idf\esp-idf が出来上がっちゃいました。）

実行中、`': 有効な識別子ではありません ～` というメッセージが表示されますが、[既知の事象](https://github.com/espressif/esp-idf/issues/11)であり、問題ないそうです。

ここで、コマンドのgitを使わず、のGUI版のgitを使っても取得できます。（自分は試していません） その場合は、必ずサブモジュールを再帰的に取得するオプションを付けるのを忘れないでください。

##Step4-1

ステップの値が変ですが、公式の記述に数字を合わせつつ、書く順番を変えます。

ここでは、bash環境(MSYS環境)の環境変数の設定をします。設定するのは1つ。IDF_PATH に、ESP-IDFのパスを指定します。

具体的には、`C:\msys32\etc\profile.d` の下に、適当なファイル名、拡張子 .sh のファイルを作り、そのファイルに `export IDF_PATH="/c/esp-idf"` とだけ書きます。ファイル名は `add_IDF_PATH.sh` とでもしましょうか。この作業はWindows上のテキストエディタでやってもOKです。

一旦bashを抜けて(`exit` で抜けます)、また起動(`C:\msys32\mingw32.exe`を実行)しましょう。

##Step3

ここでは、プロジェクトのテンプレートを取得します。

あらかじめ、`C:\Users\[Windowsのユーザー名]\OneDrive\esp32\` を作っておきましょう。

MSYSのbash上で
`cd /c/Users/rukihena/OneDrive/esp32/` でプロジェクトを入れるディレクトリに移動します。
`git clone https://github.com/espressif/esp-idf-template.git` でプロジェクトのテンプレートを取得します。

このプロジェクトは、GPIO4 でLチカするものになっています。

ディレクトリ名がアレなので、 `mv esp-idf-template lchika` で lchika に変えてしまいましょう。

`cd lchika` で、lchika ディレクトリに入ります。

##ソース書き換え

lchika/main の中に、main.c があります。これがLチカのソースとなっています。

```c:main.c
#include "freertos/FreeRTOS.h"
#include "esp_wifi.h"
#include "esp_system.h"
#include "esp_event.h"
#include "esp_event_loop.h"
#include "nvs_flash.h"
#include "driver/gpio.h"

esp_err_t event_handler(void *ctx, system_event_t *event)
{
    return ESP_OK;
}

void app_main(void)
{
    nvs_flash_init();
    tcpip_adapter_init();
    ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) );
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
    ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) );
    ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
    wifi_config_t sta_config = {
        .sta = {
            .ssid = "access_point_name",
            .password = "password",
            .bssid_set = false
        }
    };
    ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &sta_config) );
    ESP_ERROR_CHECK( esp_wifi_start() );
    ESP_ERROR_CHECK( esp_wifi_connect() );

    gpio_set_direction(GPIO_NUM_4, GPIO_MODE_OUTPUT);
    int level = 0;
    while (true) {
        gpio_set_level(GPIO_NUM_4, level);
        level = !level;
        vTaskDelay(300 / portTICK_PERIOD_MS);
    }
}

```

`GPIO_NUM_4` （2か所）を、自分が配線したGPIOの番号に書き換えましょう。

そういえばハードウェアの解説がありませんが、[ESP32(ESP-WROOM-32)でLチカ](http://qiita.com/rukihena/items/6a904368700eb1c7d2a3)を参考にしてみてください（そっちも詳しくなくて参考にならないかもしれません。。。）


##Step4-2

ここでは、プロジェクトの設定、ビルド、書き込みをします。

`make menuconfig` で、プロジェクトの設定ができます。

![menuconfig.png](https://qiita-image-store.s3.amazonaws.com/0/104360/4dc598cd-8979-dad6-8be0-1165ca5882c2.png)


なにやら色々設定できるようです。最低限、設定が必要なのは、シリアルポート番号の指定です。

`Serial flasher config` の中の、一番上、`Default serial port` で指定します。 

デフォルトが `/dev/ttyUSB0` になっているので、この形式で指定しなきゃいけないのかなと思っちゃいますが、Windows では `COM3` みたいに指定します。

![comport.png](https://qiita-image-store.s3.amazonaws.com/0/104360/3b49bb16-2e9b-0fd3-fcf9-14543a5dd9d0.png)


次に、ビルドです。 これは `make` コマンド一発です。この「コマンド一発」のために、今まで苦労してきました。

最初のビルドは時間がかかります。

ビルドが終わったら、実機に書き込みしましょう。`make flash` を打ちます。開発ボードでは勝手に書き込みモードになってくれますが、そうでない場合は書き込みモードになるようリセットしましょう。IO0とENのボタンを同時押し、ENを先に離して、書き込みが始まったらIO0を離します。

```
$ make flash
Flashing binaries to serial port COM3 (app at offset 0x10000)...
esptool.py v2.0-beta1
Connecting....
Uploading stub...
Running stub...
Stub running...
Attaching SPI flash...
Configuring flash size...
Auto-detected Flash size: 4MB
Flash params set to 0x0220
Wrote 16384 bytes at 0x00001000 in 1.5 seconds (90.1 kbit/s)...
Hash of data verified.
Wrote 491520 bytes at 0x00010000 in 43.8 seconds (89.8 kbit/s)...
Hash of data verified.
Wrote 16384 bytes at 0x00008000 in 1.5 seconds (90.2 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting...
```

書き込みが終わったら、再度リセットしましょう。

うまくいけばLEDが点滅するはずです！

実際の開発では、ソース書き換え → make → make flash を繰り返すことになります。

#追記 - MSYS更新 20170330

esp32_win32_msys2_environment_and_toolchain が 20170111 から 20170330 にアップデートされております。

更新方法は、上書きでいいのか、削除してから展開がいいのかよく分かりませんが、削除してからの方が確実だとは思います。（細かいファイルが大量にあるので上書きだとすんごい時間かかりますし。必要な変更は`add_IDF_PATH.sh`だけですし。）

アップデート後、makeを実行すると `/bin/sh: python2: コマンドが見つかりません` というエラーが出てしまいます。MSYS の起動を `C:\msys32\msys2_shell.cmd` で行っている場合（更新前のドキュメントに従って行っている場合）に、この現象が出ます。

MSYS の起動を `C:\msys32\mingw32.exe` で行うと正常に実行できます。