ESP32 向けに TinyGo をセットアップする

このページには、 ESP32 + TinyGo を使ってマイコンプログラミングを始めるための情報を記載します。
ESP32 を搭載したボードは多数ありますが、ボード固有の話よりもまずは ESP32 全般の環境を立ち上げます。
あと、試してないですが、 ESP8266 および ESP32-C もこのページに従って環境立ち上げできるはずです。

## TinyGo とは

マイコンや WASM などの Small Places 向けの Go Compiler です。
ここでは Go の文法でマイコン開発ができるもの、という程度の認識でよいです。

* [TinyGo - Go on Microcontrollers and WASM](https://tinygo.org/)

このページは 2021/11/18 にリリースされた TinyGo 0.21 を対象としています。

## ESP32 とは

WiFi + Bluetooth を内蔵するマイクロコントローラーです。
Tensilica の Xtensa LX6 マイクロプロセッサを採用し、デュアルコアとシングルコア版があります。

https://ja.wikipedia.org/wiki/ESP32


## TinyGo がサポートする ESP32 ボード

TinyGo 0.21.0 時点で、サポート状況は以下の通りです。

* マイクロコントローラーレベルでは Xtensa 32-bit LX6 に対応
* ボードレベルでは以下に対応 (0.21.0)
    * ESP32 Core Board V2 / ESP32 DevKitC
    * ESP32 Mini32
    * M5Stack Core2
* Interfaces
    * https://tinygo.org/docs/reference/microcontrollers/esp32-coreboard-v2/
    * GPIO / UART / SPI に対応
    * I2C は tinygo.org/x/drivers@0.18.0 (release branch 最新) にて software I2C に対応
    * ADC / PWM は未対応
    * WiFi / Bluetooth は未対応 (今の所、技術的に対応が難しい)
        * [#1683 ESP32 WiFi support](https://github.com/tinygo-org/tinygo/issues/1683)
        * [#1427 ESP8266 WiFi support](https://github.com/tinygo-org/tinygo/issues/1427)
* その他
    * シングルコアのみを使った動作となります
        * [デュアルコア対応は今の時点では予定されていません](https://tinygo.org/docs/reference/microcontrollers/esp32-coreboard-v2/)

なお、 0.22 では M5Stack (Gray 等) もサポートされる予定です。


## TinyGo のインストール

以下を参照してください。

https://qiita.com/sago35/items/92b22e8cbbf99d0cd3ef#tinygo-%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB

## TinyGo に必要な ESP32 環境のインストール

TinyGo で ESP32 マイコンをビルド／書き込みするには以下が必要です。
後述の手順に従ってインストールしてください。
必要なのは、以下のみです。

* xtensa-esp32-elf-ld
* esptool.py


### xtensa-esp32-elf-ld のインストール

以下の Toolchain Setup に記載のファイルをダウンロードします。

* linux
    * https://docs.espressif.com/projects/esp-idf/en/release-v3.0/get-started/linux-setup.html#toolchain-setup
        * https://dl.espressif.com/dl/xtensa-esp32-elf-linux64-1.22.0-80-g6c4433a-5.2.0.tar.gz
        * https://dl.espressif.com/dl/xtensa-esp32-elf-linux32-1.22.0-80-g6c4433a-5.2.0.tar.gz
* macos
    * https://docs.espressif.com/projects/esp-idf/en/release-v3.0/get-started/macos-setup.html#toolchain-setup
        * https://dl.espressif.com/dl/xtensa-esp32-elf-osx-1.22.0-80-g6c4433a-5.2.0.tar.gz
* windows
    * https://docs.espressif.com/projects/esp-idf/en/release-v3.0/get-started/windows-setup.html#toolchain-setup
        * https://dl.espressif.com/dl/esp32_win32_msys2_environment_and_toolchain-20180110.zip

その後、 xtensa-esp32-elf-ld が含まれるフォルダに環境変数 PATH を通します。

* linux
    * xtensa-esp32-elf/bin
* macos
    * xtensa-esp32-elf/bin
* windows
    * msys32/opt/xtensa-esp32-elf/bin

```shell
# bash 等
$ export PATH=$PATH:/path/to/xtensa-esp32-elf/bin

# windows cmd.exe
$ set PATH=%PATH%;C:\path\to\msys32\opt\xtensa-esp32-elf\bin
```

なお Windows の場合は、 xtensa-esp32-elf-ld.exe 単体があればよいので他のファイルは消しても問題ありません。
依存が極めて小さいのでとても快適です。

### esptool.py のインストール (python 経由でインストールする)

python に慣れている人は、以下に従いインストールしてください。

https://docs.espressif.com/projects/esptool/en/latest/esp32/installation.html#installation

```shell
$ pip install esptool
```

### esptool.py のインストール (バイナリを入手する)

以下のページからバイナリを入手することができます。
ただし、 TinyGo で必要となるファイル (ファイル名) は `esptool` ではなく `esptool.py` であることに注意 (後述) 。

https://github.com/espressif/esptool/releases/

ダウンロードしたファイル内から esptool / esptool.exe を取り出して PATH の通った場所 (先ほどの xtensa-esp32-elf-ld がある場所など) に **esptool.py に rename しつつ** 置きます。
windows の場合は `esptool.py.exe` に rename してください。


## ESP32 で L チカする

ここではスイッチサイエンスの ESPr Developer 32 を使って説明します。

https://www.switch-science.com/catalog/3210/

ESPr Developer 32 は、ほぼ ESP32 Coreboard v2 と同じであるため、 `--target esp32-coreboard-v2` を使うと良いです。
以下のように書き込むことができます。

```shell
$ tinygo flash --target esp32-coreboard-v2 --size short examples/blinky1
   code    data     bss |   flash     ram
   3030       0    4136 |    3030    4136
esptool.py v3.0
Serial port COM14
Connecting.......
Chip is ESP32-D0WDQ6 (revision 1)
Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None
Crystal is 40MHz
MAC: a4:cf:12:56:2b:08
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Flash params set to 0x031f
Compressed 3120 bytes to 2347...
Wrote 3120 bytes (2347 compressed) at 0x00001000 in 0.2 seconds (effective 111.4 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...
```

`examples/blinky1` は TinyGo をインストールしたフォルダの `src/examples/blinky1` にあります。
このあたりは、以下に書いてある内容と同じです。

https://qiita.com/sago35/items/92b22e8cbbf99d0cd3ef#hello-tinygo


なお、 ESPr Developer 32 に target として使用している `esp32-coreboard-v2` の `machine.LED` は以下の定義になっています。

```go
// https://github.com/tinygo-org/tinygo/blob/06df31944c6af706d6cb8b30a2e92d19060436d2/src/machine/board_esp32-coreboard-v2.go#L6

// Built-in LED on some ESP32 boards.
const LED = IO2
```

なので、以下のように接続することで L チカ可能となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63649/fb0c119a-ed4e-53a1-5ee4-5818de0e17cd.png)


### M5Stack Core2 で L チカする

M5Stack Core2 は、 ESP32 から直接操作できる場所に LED が無いため、ここでは扱いません。
近日 `MM5Stack Core2 で TinyGo プログラミングを始めよう` という記事を公開予定なのでお楽しみに。
それまでの間は、 `examples/serial` を試すのが良いと思います。
`examples/serial` を書き込んだ後は、シリアルモニターのソフトでポートを開いてみてください。
その際、 115200 bps に設定するのを忘れずに。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63649/8a5c9427-89d8-cafe-04e3-f0003551da82.png)

## I2C 対応

以下のようにして i2csoft package を使うことで使用することができます。

https://github.com/tinygo-org/drivers/blob/release/examples/i2csoft/adt7410/main.go

```go
package main

import (
	"fmt"
	"machine"
	"time"

	"tinygo.org/x/drivers/adt7410"
	"tinygo.org/x/drivers/i2csoft"
)

func main() {
	i2c := i2csoft.New(machine.SCL_PIN, machine.SDA_PIN)
	i2c.Configure(i2csoft.I2CConfig{
		Frequency: 400e3,
	})

	sensor := adt7410.New(i2c)
	sensor.Configure()

	for {
		temp := sensor.ReadTempF()
		fmt.Printf("temperature: %f\r\n", temp)
		time.Sleep(time.Second)
	}

}
```

## まとめ

ESP32 + TinyGo を使ってマイコンプログラミングを始めるための情報を記載しました。
現時点で WiFi / Bluetooth が使えないなどの制限がありますが、 SPI / I2C なども使えるようになったためマイコンボードとしてそれなりに遊べる状態になりました。
是非試してみてください。