BLE対応のESP32用MicroPythonのビルドと書き込み - Ubuntu (Windows Subsystem for Linux)

# ESP32用のMicroPython

ESP32用のMicroPythonもBluetooth Low Energy（BLE）をサポートしています。
Windows10 上の Ubuntu でビルドから動作確認までを行うことができます。

https://micropython-docs-ja.readthedocs.io/ja/latest/library/ubluetooth.html

# Windows10でUbuntuをインストール

## Ubuntuインストールの準備とインストール

Windows PowerShell を「管理者として実行する」で起動し、次のコマンドで Windows Subsystem for Linux オプション機能を有効にします。

```
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
```

Windows10 の Microsoft Store で、Ubuntuを検索し、Ubuntuをインストールします。

**参照：**https://aka.ms/wslinstall

## Ubuntuの初期化
インストール後、Ubuntuを起動し、Linuxユーザーアカウントの設定を行います。
設定後、ログインするので、ディストリビューションのパッケージの更新とアップグレードを行います。

```
sudo apt update && sudo apt upgrade
```

**参照：** https://docs.microsoft.com/ja-jp/windows/wsl/initialize-distro

# 必要なツールのインストール

```
sudo apt update
sudo apt install \
gcc git wget make libncurses-dev flex bison gperf \
libffi-dev libssl-dev
```

- `python` `python-pip` `python-setuptools` `python-serial` `python-cryptography` `python-future` `python-pyparsing` については、ここではインストールしません。ESP-IDFの依存モジュールとして、後でインストールします。

# フォルダ構成
最終的に次のようなフォルダ構成とします。

```
~/esp32
 + /micropython
 + /esp-idf
 + /xtensa-esp32-elf
```

# セットアップ（インストール）

## MicroPythonの取得（gitクローン）

`~/esp32/micropython`ディレクトリにMicroPythonのソースコードを取得します。

```
cd
mkdir esp32
cd esp32
git clone https://github.com/micropython/micropython
```

## ESP-IDFの取得（gitクローンとリビジョン）

`~/esp32/esp-idf`ディレクトリにESP-IDFのソースコードを取得（gitクローン）します。
ただし、MicroPythonは特定のESP-IDFのリビジョンに依存しますので、そのリビジョンをチェックアウトします。

`make ESPIDF=`を実行すると依存するリビジョンが表示されますので、そのリビジョンを`git checkout`のパラメーターに与えます。
※ 2020/04/28 現在、`Supported git hash (v3.3): 9e70825d1e1cbf7988cf36981774300066580ea7`と表示されました。

```
cd ~/esp32/micropython/ports/esp32
make ESPIDF=

export ESPIDF=~/esp32/esp-idf
mkdir -p $ESPIDF
cd $ESPIDF
git clone https://github.com/espressif/esp-idf.git $ESPIDF

git checkout 9e70825d1e1cbf7988cf36981774300066580ea7
git submodule update --init --recursive
```

## Python仮想環境とESP-IDFの依存モジュールのインストール

Pythonを仮想環境で実行できるようにし、ESP-IDFの依存モジュールをインストールします。

```
sudo apt install python3-venv

cd ~/esp32/micropython/ports/esp32
python3 -m venv build-venv
source build-venv/bin/activate

pip install --upgrade pip
pip install -r ~/esp32/esp-idf/requirements.txt
```

## クロスコンパイラ(Toolchain)のインストール
`~/esp32/xtensa-esp32-elf`ディレクトリにクロスコンパイラ(Toolchain)をインストールします。

次のページを参照して、64bit版もしくは32bit版の最新バージョンをインストールします。
https://docs.espressif.com/projects/esp-idf/en/v3.3.2/get-started/linux-setup.html

* 今回、`xtensa-esp32-elf-gcc8_2_0-esp32-2019r1-linux-amd64.tar.gz`をインストールしました。

```
mkdir -p ~/Downloads
cd ~/Downloads
wget https://dl.espressif.com/dl/xtensa-esp32-elf-gcc8_2_0-esp32-2019r1-linux-amd64.tar.gz
cd ~/esp32
tar -xzf ~/Downloads/xtensa-esp32-elf-gcc8_2_0-esp32-2019r1-linux-amd64.tar.gz
```
クロスコンパイラ(Toolchain) が `~/esp32/xtensa-esp32-elf`ディレクトリに展開されます。

## ESPIDF環境変数とPATH環境変数の設定

`ESPIDF`環境変数とクロスコンパイラ(Toolchain)の`PATH`環境変数に関する記述を `~/.profile`ファイルに追加します。

```~/.profile
# set ESPIDF esp-idf Repository
export ESPIDF="$HOME/esp32/esp-idf"
# set PATH xtensa-esp32-elf/bin
export PATH="$HOME/esp32/xtensa-esp32-elf/bin:$PATH"
alias get_esp32='export PATH="$HOME/esp32/xtensa-esp32-elf/bin:$PATH"'
```

`~/.profile`ファイルを保存したら、一旦、Ubuntuを終了し(`exit`)、再度、起動します。
次のコマンドで、`PATH`が設定されていることを確認できます。

```
printenv PATH
```

# ビルド

## Python仮想環境の有効化（再）

次のコマンドで、構築したPython仮想環境を再度、有効化します。

```
source ~/esp32/micropython/ports/esp32/build-venv/bin/activate
```

## 組み込みスクリプトのプリコンパイル
MicroPythonの組み込みスクリプトの一部をバイトコードにプリコンパイルします。

```
cd ~/esp32/micropython/mpy-cross
make mpy-cross
```

## berkeley-db-1.xxモジュールのアップデート
`berkeley-db-1.xx`モジュールをアックデートします。

```
cd ~/esp32/micropython/
git submodule init lib/berkeley-db-1.xx
git submodule update
```

## ESP32用のMicroPythonのビルド
ESP32用のMicroPythonのファームウェアをビルドします。
ファームウェアのイメージファイルは、`build`ディレクトリに作成されます。
（`bootloader.bin`, `partitions.bin`, `application.bin` の3つ）

```
cd ~/esp32/micropython/ports/esp32
make submodules
make PYTHON2=python
```
※ python2が見つからないというエラーが出てしまうので、`make`に`PYTHON2=python`パラメーターを渡しています。

# ファームウェアの書き込み

## USBシリアルポートの設定
ESP32とは、USBシリアルポートで通信しますが、例えば、 /dev/ttyS1 (COM1)にアクセスしようとするとエラーが発生することがあります。
次のように、ユーザーを dialout グループに追加しておく必要があります。

```
sudo usermod -a -G dialout $USER
```

## ESP32の接続
ESP32 をUSBケーブルでパソコンに接続し、デバイスマネージャで、ポートを確認します。
例えば、Windows10で、`COM14` として認識されている場合、Ubuntuでは、`/dev/ttyS14` として認識されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/0ae641aa-39d6-e8f2-e701-3896cf4137f9.png)

## 消去と書込

ファームウェアをESP32マイコンに書き込む前に、`make erase`でフラッシュメモリの消去を行います。その後、`make deploy`で書き込みます。
デフォルトでは、通信速度（`BAUD`）が`460800`に、通信ポート（`PORT`）が`/dev/ttyUSB0`に、それぞれ設定されていますので、パラメーターで明示的に指定しています。`PORT`は、デバイスマネージャーで確認したポートに合わせてください。

```消去.
cd ~/esp32/micropython/ports/esp32
make erase BAUD=115200 PORT=/dev/ttyS14
```

```書込.
cd ~/esp32/micropython/ports/esp32
make deploy BAUD=115200 PORT=/dev/ttyS14
```

# MicroPythonの動作確認

シリアル通信ソフト（TeraTerm等）で、ESP32にシリアル通信接続します。通信速度は、`115200`です。

## Hello World

`uPyCraft`の下段ペインがターミナルエミュレータです。ここで、USBシリアルポート経由で、プロンプトにアクセスできます。例えば、次のコードを入力し、Enterキーを押下すると`Hello World`と表示されます。

```
print("Hello World")
```

# サンプルプログラムの動作確認（温度計）

## プログラム書き込みツールのインストール

プログラム書き込みツールとして、`ampy`をインストールします。

```
source ~/esp32/micropython/ports/esp32/build-venv/bin/activate
pip install adafruit-ampy
```

## サンプルプログラムの転送

`~/esp32/micropython/examples/bluetooth`ディレクトリにBLEのサンプルプログラムがありますので、`ble_advertising.py`ファイルと`ble_temperature.py`ファイルをESP32へ転送します(`put`)。[^unkwarg]

[^unkwarg]: (2020/06/26 追記) bluetooth.BLE.irq()の引数は、キーワード引数ではなくなりましたので、実行時にTypeErrorが発生することがあります。最新のexampleソースコードを取得してください。[参照：https://github.com/micropython/micropython/issues/6489](https://github.com/micropython/micropython/issues/6489)

```
cd ~/esp32/micropython/examples/bluetooth
ampy --port=/dev/ttyS14 put ble_advertising.py
ampy --port=/dev/ttyS14 put ble_temperature.py
```

ファイルが転送されたかどうかを確認します（`ls`）。

```
ampy --port=/dev/ttyS14 ls
```

## サンプルプログラムの自動実行
転送した`ble_temperature.py`ファイルを自動実行させる為、`main.py`ファイルを作成し、転送します。

```main.py
import ble_temperature
ble_temperature.demo()
```

```
ampy --port=/dev/ttyS14 put main.py
```

## サンプルプログラムの動作確認

ESP32を再起動するとサンプルプログラムが自動実行されますので、スマホアプリの`nRF Connect`等を使って温度計の動作確認できます。
ESP32とシリアル通信しておけば、ログの確認もできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/f439803c-ff10-405e-09b1-888a480ea5ea.png)

# 最後に

ESP32用のMicroPythonで、サンプルプログラムのBLE温度計の動作確認を行いました。

プロファイル/サービスの仕様に関しては、ESP/ESSを参照してください。
https://www.bluetooth.com/specifications/gatt/
ESP	Environmental Sensing Profile	1.0	Active	18 Nov 2014	N/A
ESS	Environmental Sensing Service	1.0	Active	18 Nov 2014	N/A